From 2a7e16841a440569b3355aa284afd78874c20b02 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sun, 19 Jun 2022 14:47:54 +0530 Subject: [PATCH 01/59] Initial commit - storagevec --- sway-lib-std/src/vec.sw | 84 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/sway-lib-std/src/vec.sw b/sway-lib-std/src/vec.sw index 1655e4b4cc9..51b09891ae8 100644 --- a/sway-lib-std/src/vec.sw +++ b/sway-lib-std/src/vec.sw @@ -2,8 +2,11 @@ library vec; use ::alloc::{alloc, realloc}; use ::intrinsics::size_of; +use ::hash::sha256; use ::mem::{read, write}; use ::option::Option; +use ::result::Result; +use ::storage::{store, get}; struct RawVec { ptr: u64, @@ -142,3 +145,84 @@ impl Vec { self.len == 0 } } + +/// TODO: Add proper errors + +pub struct StorageVec {} + +impl StorageVec { + #[storage(read, write)] + fn push(self, value: V) { + let len = get::(__get_storage_key()); + let key = sha256((len, __get_storage_key())); + store::(key, value); + store(__get_storage_key(), len + 1); + } + + #[storage(read, write)] + fn pop(self) -> Option { + let len = get::(__get_storage_key()); + if len == 0 { + return Option::None; + } + + let key = sha256((len, __get_storage_key())); + store(__get_storage_key(), len - 1); + + Option::Some(get::(key)) + } + + #[storage(read)] + fn get(self, index: u64) -> Option { + let len = get::(__get_storage_key()); + if len <= index { + return Option::None; + } + + let key = sha256((index, __get_storage_key())); + Option::Some(get::(key)) + } + + #[storage(read, write)] + fn remove_index(self, index: u64) -> Result<(), ()> { + let len = get::(__get_storage_key()); + if len <= index { + return Result::Err(()); + } + + let mut count = index + 1; + while count < len { + let key = sha256((count - 1, __get_storage_key())); + // shifts all the values down one index + store::(key, get::(sha256((count, __get_storage_key())))); + + count += 1; + } + + store(__get_storage_key(), len - 1); + Result::Ok(()) + } + + #[storage(read, write)] + fn insert(self, index: u64, value: V) -> Result<(), ()> { + let len = get::(__get_storage_key()); + if index >= len { + return Result::Err(()); + } + + let mut count = len; + while count > index { + let key = sha256((count + 1, __get_storage_key())); + // shifts all the values up one index + store::(key, get::(sha256((count, __get_storage_key())))); + + count -= 1 + } + + let key = sha256((index, __get_storage_key())); + store::(key, value); + + store(__get_storage_key(), len + 1); + Result::Ok(()) + } +} \ No newline at end of file From 23f925f55850a6b5e9b9fb707d3528169931d07f Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sun, 19 Jun 2022 19:09:15 +0530 Subject: [PATCH 02/59] added an error and comments and documentation --- sway-lib-std/src/vec.sw | 54 ++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/sway-lib-std/src/vec.sw b/sway-lib-std/src/vec.sw index 51b09891ae8..19a62ee9128 100644 --- a/sway-lib-std/src/vec.sw +++ b/sway-lib-std/src/vec.sw @@ -146,35 +146,49 @@ impl Vec { } } -/// TODO: Add proper errors +enum StorageVecError { + IndexOutOfBounds: (), +} +/// A persistant vector struct pub struct StorageVec {} impl StorageVec { + /// Appends the value to the end of the vector #[storage(read, write)] fn push(self, value: V) { + // The length of the vec is stored in the __get_storage_key() slot let len = get::(__get_storage_key()); + + // Storing the value at the current length index (if this is the first item, starts off at 0) let key = sha256((len, __get_storage_key())); store::(key, value); + + // Incrementing the length store(__get_storage_key(), len + 1); } + /// Removes the last element of the vector #[storage(read, write)] fn pop(self) -> Option { let len = get::(__get_storage_key()); + // if the length is 0, there is no item to pop from the vec if len == 0 { return Option::None; } - let key = sha256((len, __get_storage_key())); + // reduces len by 1, effectively removing the last item in the vec store(__get_storage_key(), len - 1); + let key = sha256((len, __get_storage_key())); Option::Some(get::(key)) } + /// Gets the value in the given index #[storage(read)] fn get(self, index: u64) -> Option { let len = get::(__get_storage_key()); + // if the index is larger or equal to len, there is no item to return if len <= index { return Option::None; } @@ -183,33 +197,53 @@ impl StorageVec { Option::Some(get::(key)) } + /// Removes the value in the given index and moves all the values in the following indexes + /// Down one index + /// WARNING: Expensive for larger vecs #[storage(read, write)] - fn remove_index(self, index: u64) -> Result<(), ()> { + fn remove_index(self, index: u64) -> Result { let len = get::(__get_storage_key()); + // if the index is larger or equal to len, there is no item to remove if len <= index { - return Result::Err(()); + return Result::Err(StorageVecError::IndexOutOfBounds); } + // gets the element before removing it, so it can be returned + let element_to_be_removed = get::(sha256((index, __get_storage_key()))); + + // for every element in the vec with an index greater than the input index, + // shifts the index for that element down one let mut count = index + 1; while count < len { + // gets the storage location for the previous index let key = sha256((count - 1, __get_storage_key())); - // shifts all the values down one index + // moves the element of the current index into the previous index store::(key, get::(sha256((count, __get_storage_key())))); count += 1; } + // decrements len by 1 store(__get_storage_key(), len - 1); - Result::Ok(()) + + // returns the removed element + Result::Ok(element_to_be_removed) } + /// Inserts the value at the given index, moving the current index's value aswell as the following's + /// Up one index + /// WARNING: Expensive for larger vecs #[storage(read, write)] - fn insert(self, index: u64, value: V) -> Result<(), ()> { + fn insert(self, index: u64, value: V) -> Result { let len = get::(__get_storage_key()); + // if the index is larger or equal to len, there is no space to insert if index >= len { - return Result::Err(()); + return Result::Err(StorageVecError::IndexOutOfBounds); } + // for every element in the vec with an index larger than the input index, + // move the element up one index. + // performed in reverse to prevent data overwriting let mut count = len; while count > index { let key = sha256((count + 1, __get_storage_key())); @@ -219,10 +253,12 @@ impl StorageVec { count -= 1 } + // inserts the value into the now unused index let key = sha256((index, __get_storage_key())); store::(key, value); + // increments len by 1 store(__get_storage_key(), len + 1); Result::Ok(()) } -} \ No newline at end of file +} From 81a0ea6d8707db7d2876008203050cbc565c1368 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sun, 19 Jun 2022 19:10:48 +0530 Subject: [PATCH 03/59] fixed the order of the Result types --- sway-lib-std/src/vec.sw | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sway-lib-std/src/vec.sw b/sway-lib-std/src/vec.sw index 19a62ee9128..be1b6a6e281 100644 --- a/sway-lib-std/src/vec.sw +++ b/sway-lib-std/src/vec.sw @@ -201,7 +201,7 @@ impl StorageVec { /// Down one index /// WARNING: Expensive for larger vecs #[storage(read, write)] - fn remove_index(self, index: u64) -> Result { + fn remove_index(self, index: u64) -> Result { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no item to remove if len <= index { @@ -234,7 +234,7 @@ impl StorageVec { /// Up one index /// WARNING: Expensive for larger vecs #[storage(read, write)] - fn insert(self, index: u64, value: V) -> Result { + fn insert(self, index: u64, value: V) -> Result<(), StorageVecError> { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no space to insert if index >= len { @@ -261,4 +261,6 @@ impl StorageVec { store(__get_storage_key(), len + 1); Result::Ok(()) } + + } From 7985f5586c0f6599c46dbf6b281991e9a0ecd761 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sun, 19 Jun 2022 19:28:02 +0530 Subject: [PATCH 04/59] added suggested functions --- sway-lib-std/src/vec.sw | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/sway-lib-std/src/vec.sw b/sway-lib-std/src/vec.sw index be1b6a6e281..5cef2cd2697 100644 --- a/sway-lib-std/src/vec.sw +++ b/sway-lib-std/src/vec.sw @@ -156,7 +156,7 @@ pub struct StorageVec {} impl StorageVec { /// Appends the value to the end of the vector #[storage(read, write)] - fn push(self, value: V) { + pub fn push(self, value: V) { // The length of the vec is stored in the __get_storage_key() slot let len = get::(__get_storage_key()); @@ -170,7 +170,7 @@ impl StorageVec { /// Removes the last element of the vector #[storage(read, write)] - fn pop(self) -> Option { + pub fn pop(self) -> Option { let len = get::(__get_storage_key()); // if the length is 0, there is no item to pop from the vec if len == 0 { @@ -186,7 +186,7 @@ impl StorageVec { /// Gets the value in the given index #[storage(read)] - fn get(self, index: u64) -> Option { + pub fn get(self, index: u64) -> Option { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no item to return if len <= index { @@ -201,7 +201,7 @@ impl StorageVec { /// Down one index /// WARNING: Expensive for larger vecs #[storage(read, write)] - fn remove_index(self, index: u64) -> Result { + pub fn remove_index(self, index: u64) -> Result { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no item to remove if len <= index { @@ -234,7 +234,7 @@ impl StorageVec { /// Up one index /// WARNING: Expensive for larger vecs #[storage(read, write)] - fn insert(self, index: u64, value: V) -> Result<(), StorageVecError> { + pub fn insert(self, index: u64, value: V) -> Result<(), StorageVecError> { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no space to insert if index >= len { @@ -262,5 +262,27 @@ impl StorageVec { Result::Ok(()) } + /// Returns the length of the vector + #[storage(read)] + pub fn len(self) -> u64 { + get::(__get_storage_key()) + } + + /// Checks whether the len is 0 or not + #[storage(read)] + pub fn is_empty(self) -> bool { + let len = get::(__get_storage_key()); + if len == 0 { + true + } else { + false + } + } + + /// Sets the len to 0 + #[storage(write)] + pub fn clear(self) { + store(__get_storage_key(), 0); + } } From 28e9be334bfdbf4460ec661e4d15c2de73689c18 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sun, 19 Jun 2022 19:29:18 +0530 Subject: [PATCH 05/59] removed unncessary code --- sway-lib-std/src/vec.sw | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sway-lib-std/src/vec.sw b/sway-lib-std/src/vec.sw index 5cef2cd2697..e9ceb8dd572 100644 --- a/sway-lib-std/src/vec.sw +++ b/sway-lib-std/src/vec.sw @@ -273,11 +273,7 @@ impl StorageVec { pub fn is_empty(self) -> bool { let len = get::(__get_storage_key()); - if len == 0 { - true - } else { - false - } + len == 0 } /// Sets the len to 0 From 6b629db647b8eeb4337c1c5384b7db0056e457b9 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sun, 19 Jun 2022 19:32:38 +0530 Subject: [PATCH 06/59] renamed remove_index --- sway-lib-std/src/vec.sw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway-lib-std/src/vec.sw b/sway-lib-std/src/vec.sw index e9ceb8dd572..9fbebb78940 100644 --- a/sway-lib-std/src/vec.sw +++ b/sway-lib-std/src/vec.sw @@ -201,7 +201,7 @@ impl StorageVec { /// Down one index /// WARNING: Expensive for larger vecs #[storage(read, write)] - pub fn remove_index(self, index: u64) -> Result { + pub fn remove(self, index: u64) -> Result { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no item to remove if len <= index { From a4a90935f896193132096567d25c1bb290ccbc41 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sun, 19 Jun 2022 19:45:31 +0530 Subject: [PATCH 07/59] added swap remove and removed unncessary annotations --- sway-lib-std/src/vec.sw | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/sway-lib-std/src/vec.sw b/sway-lib-std/src/vec.sw index 9fbebb78940..2788f33c78d 100644 --- a/sway-lib-std/src/vec.sw +++ b/sway-lib-std/src/vec.sw @@ -148,6 +148,7 @@ impl Vec { enum StorageVecError { IndexOutOfBounds: (), + CannotSwapAndRemoveTheSameElement: (), } /// A persistant vector struct @@ -162,7 +163,7 @@ impl StorageVec { // Storing the value at the current length index (if this is the first item, starts off at 0) let key = sha256((len, __get_storage_key())); - store::(key, value); + store(key, value); // Incrementing the length store(__get_storage_key(), len + 1); @@ -181,7 +182,7 @@ impl StorageVec { store(__get_storage_key(), len - 1); let key = sha256((len, __get_storage_key())); - Option::Some(get::(key)) + Option::Some(get(key)) } /// Gets the value in the given index @@ -194,7 +195,7 @@ impl StorageVec { } let key = sha256((index, __get_storage_key())); - Option::Some(get::(key)) + Option::Some(get(key)) } /// Removes the value in the given index and moves all the values in the following indexes @@ -209,7 +210,7 @@ impl StorageVec { } // gets the element before removing it, so it can be returned - let element_to_be_removed = get::(sha256((index, __get_storage_key()))); + let element_to_be_removed = get(sha256((index, __get_storage_key()))); // for every element in the vec with an index greater than the input index, // shifts the index for that element down one @@ -218,7 +219,7 @@ impl StorageVec { // gets the storage location for the previous index let key = sha256((count - 1, __get_storage_key())); // moves the element of the current index into the previous index - store::(key, get::(sha256((count, __get_storage_key())))); + store(key, get(sha256((count, __get_storage_key())))); count += 1; } @@ -230,6 +231,30 @@ impl StorageVec { Result::Ok(element_to_be_removed) } + /// Removes the element at the specified index and fills it with the last element + /// Does not preserve ordering + #[storage(read, write)] + pub fn swap_remove(self, index: u64) -> Result<(), StorageVecError> { + let len = get::(__get_storage_key()); + // if the index is larger or equal to len, there is no item to remove + if len <= index { + return Result::Err(StorageVecError::IndexOutOfBounds); + } + + // if the index is the last one, the function should not try to remove and then swap the same element + if index == len - 1 { + return Result::Err(StorageVecError::CannotSwapAndRemoveTheSameElement); + } + + let last_element = get(sha256(len - 1, __get_storage_key())); + store(sha256(index, __get_storage_key()), last_element); + + // decrements len by 1 + store(__get_storage_key(), len - 1); + + Result::Ok(()) + } + /// Inserts the value at the given index, moving the current index's value aswell as the following's /// Up one index /// WARNING: Expensive for larger vecs @@ -248,14 +273,14 @@ impl StorageVec { while count > index { let key = sha256((count + 1, __get_storage_key())); // shifts all the values up one index - store::(key, get::(sha256((count, __get_storage_key())))); + store(key, get(sha256((count, __get_storage_key())))); count -= 1 } // inserts the value into the now unused index let key = sha256((index, __get_storage_key())); - store::(key, value); + store(key, value); // increments len by 1 store(__get_storage_key(), len + 1); From f09060fb603d478826febb167e37e22d3c477675 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 22 Jun 2022 17:37:50 +0530 Subject: [PATCH 08/59] moved storage_vec to storage and started on tests --- sway-lib-std/src/storage.sw | 165 ++++++++++++++++++ sway-lib-std/src/vec.sw | 165 +----------------- test/src/sdk-harness/test_projects/harness.rs | 1 + .../test_projects/storage_vec/.gitignore | 2 + .../test_projects/storage_vec/Cargo.toml | 16 ++ .../test_projects/storage_vec/Forc.toml | 8 + .../test_projects/storage_vec/src/main.sw | 13 ++ .../storage_vec/tests/harness.rs | 25 +++ 8 files changed, 231 insertions(+), 164 deletions(-) create mode 100644 test/src/sdk-harness/test_projects/storage_vec/.gitignore create mode 100644 test/src/sdk-harness/test_projects/storage_vec/Cargo.toml create mode 100644 test/src/sdk-harness/test_projects/storage_vec/Forc.toml create mode 100644 test/src/sdk-harness/test_projects/storage_vec/src/main.sw create mode 100644 test/src/sdk-harness/test_projects/storage_vec/tests/harness.rs diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index 1ec7160fc9b..09f6613b3d7 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -1,6 +1,8 @@ library storage; use ::hash::sha256; +use ::option::Option; +use ::result::Result; use ::context::registers::stack_ptr; /// Store a stack variable in storage. @@ -106,3 +108,166 @@ impl StorageMap { get::(key) } } + + +enum StorageVecError { + IndexOutOfBounds: (), + CannotSwapAndRemoveTheSameElement: (), +} + +/// A persistant vector struct +pub struct StorageVec {} + +impl StorageVec { + /// Appends the value to the end of the vector + #[storage(read, write)] + pub fn push(self, value: V) { + // The length of the vec is stored in the __get_storage_key() slot + let len = get::(__get_storage_key()); + + // Storing the value at the current length index (if this is the first item, starts off at 0) + let key = sha256((len, __get_storage_key())); + store(key, value); + + // Incrementing the length + store(__get_storage_key(), len + 1); + } + + /// Removes the last element of the vector + #[storage(read, write)] + pub fn pop(self) -> Option { + let len = get::(__get_storage_key()); + // if the length is 0, there is no item to pop from the vec + if len == 0 { + return Option::None; + } + + // reduces len by 1, effectively removing the last item in the vec + store(__get_storage_key(), len - 1); + + let key = sha256((len, __get_storage_key())); + Option::Some(get(key)) + } + + /// Gets the value in the given index + #[storage(read)] + pub fn get(self, index: u64) -> Option { + let len = get::(__get_storage_key()); + // if the index is larger or equal to len, there is no item to return + if len <= index { + return Option::None; + } + + let key = sha256((index, __get_storage_key())); + Option::Some(get(key)) + } + + /// Removes the value in the given index and moves all the values in the following indexes + /// Down one index + /// WARNING: Expensive for larger vecs + #[storage(read, write)] + pub fn remove(self, index: u64) -> Result { + let len = get::(__get_storage_key()); + // if the index is larger or equal to len, there is no item to remove + if len <= index { + return Result::Err(StorageVecError::IndexOutOfBounds); + } + + // gets the element before removing it, so it can be returned + let element_to_be_removed = get(sha256((index, __get_storage_key()))); + + // for every element in the vec with an index greater than the input index, + // shifts the index for that element down one + let mut count = index + 1; + while count < len { + // gets the storage location for the previous index + let key = sha256((count - 1, __get_storage_key())); + // moves the element of the current index into the previous index + store(key, get(sha256((count, __get_storage_key())))); + + count += 1; + } + + // decrements len by 1 + store(__get_storage_key(), len - 1); + + // returns the removed element + Result::Ok(element_to_be_removed) + } + + /// Removes the element at the specified index and fills it with the last element + /// Does not preserve ordering + #[storage(read, write)] + pub fn swap_remove(self, index: u64) -> Result<(), StorageVecError> { + let len = get::(__get_storage_key()); + // if the index is larger or equal to len, there is no item to remove + if len <= index { + return Result::Err(StorageVecError::IndexOutOfBounds); + } + + // if the index is the last one, the function should not try to remove and then swap the same element + if index == len - 1 { + return Result::Err(StorageVecError::CannotSwapAndRemoveTheSameElement); + } + + let last_element = get(sha256(len - 1, __get_storage_key())); + store(sha256(index, __get_storage_key()), last_element); + + // decrements len by 1 + store(__get_storage_key(), len - 1); + + Result::Ok(()) + } + + /// Inserts the value at the given index, moving the current index's value aswell as the following's + /// Up one index + /// WARNING: Expensive for larger vecs + #[storage(read, write)] + pub fn insert(self, index: u64, value: V) -> Result<(), StorageVecError> { + let len = get::(__get_storage_key()); + // if the index is larger or equal to len, there is no space to insert + if index >= len { + return Result::Err(StorageVecError::IndexOutOfBounds); + } + + // for every element in the vec with an index larger than the input index, + // move the element up one index. + // performed in reverse to prevent data overwriting + let mut count = len; + while count > index { + let key = sha256((count + 1, __get_storage_key())); + // shifts all the values up one index + store(key, get(sha256((count, __get_storage_key())))); + + count -= 1 + } + + // inserts the value into the now unused index + let key = sha256((index, __get_storage_key())); + store(key, value); + + // increments len by 1 + store(__get_storage_key(), len + 1); + Result::Ok(()) + } + + /// Returns the length of the vector + #[storage(read)] + pub fn len(self) -> u64 { + get::(__get_storage_key()) + } + + /// Checks whether the len is 0 or not + #[storage(read)] + pub fn is_empty(self) -> bool { + let len = get::(__get_storage_key()); + + len == 0 + } + + /// Sets the len to 0 + #[storage(write)] + pub fn clear(self) { + store(__get_storage_key(), 0); + } +} diff --git a/sway-lib-std/src/vec.sw b/sway-lib-std/src/vec.sw index 2788f33c78d..dbb4105dccf 100644 --- a/sway-lib-std/src/vec.sw +++ b/sway-lib-std/src/vec.sw @@ -5,8 +5,7 @@ use ::intrinsics::size_of; use ::hash::sha256; use ::mem::{read, write}; use ::option::Option; -use ::result::Result; -use ::storage::{store, get}; + struct RawVec { ptr: u64, @@ -145,165 +144,3 @@ impl Vec { self.len == 0 } } - -enum StorageVecError { - IndexOutOfBounds: (), - CannotSwapAndRemoveTheSameElement: (), -} - -/// A persistant vector struct -pub struct StorageVec {} - -impl StorageVec { - /// Appends the value to the end of the vector - #[storage(read, write)] - pub fn push(self, value: V) { - // The length of the vec is stored in the __get_storage_key() slot - let len = get::(__get_storage_key()); - - // Storing the value at the current length index (if this is the first item, starts off at 0) - let key = sha256((len, __get_storage_key())); - store(key, value); - - // Incrementing the length - store(__get_storage_key(), len + 1); - } - - /// Removes the last element of the vector - #[storage(read, write)] - pub fn pop(self) -> Option { - let len = get::(__get_storage_key()); - // if the length is 0, there is no item to pop from the vec - if len == 0 { - return Option::None; - } - - // reduces len by 1, effectively removing the last item in the vec - store(__get_storage_key(), len - 1); - - let key = sha256((len, __get_storage_key())); - Option::Some(get(key)) - } - - /// Gets the value in the given index - #[storage(read)] - pub fn get(self, index: u64) -> Option { - let len = get::(__get_storage_key()); - // if the index is larger or equal to len, there is no item to return - if len <= index { - return Option::None; - } - - let key = sha256((index, __get_storage_key())); - Option::Some(get(key)) - } - - /// Removes the value in the given index and moves all the values in the following indexes - /// Down one index - /// WARNING: Expensive for larger vecs - #[storage(read, write)] - pub fn remove(self, index: u64) -> Result { - let len = get::(__get_storage_key()); - // if the index is larger or equal to len, there is no item to remove - if len <= index { - return Result::Err(StorageVecError::IndexOutOfBounds); - } - - // gets the element before removing it, so it can be returned - let element_to_be_removed = get(sha256((index, __get_storage_key()))); - - // for every element in the vec with an index greater than the input index, - // shifts the index for that element down one - let mut count = index + 1; - while count < len { - // gets the storage location for the previous index - let key = sha256((count - 1, __get_storage_key())); - // moves the element of the current index into the previous index - store(key, get(sha256((count, __get_storage_key())))); - - count += 1; - } - - // decrements len by 1 - store(__get_storage_key(), len - 1); - - // returns the removed element - Result::Ok(element_to_be_removed) - } - - /// Removes the element at the specified index and fills it with the last element - /// Does not preserve ordering - #[storage(read, write)] - pub fn swap_remove(self, index: u64) -> Result<(), StorageVecError> { - let len = get::(__get_storage_key()); - // if the index is larger or equal to len, there is no item to remove - if len <= index { - return Result::Err(StorageVecError::IndexOutOfBounds); - } - - // if the index is the last one, the function should not try to remove and then swap the same element - if index == len - 1 { - return Result::Err(StorageVecError::CannotSwapAndRemoveTheSameElement); - } - - let last_element = get(sha256(len - 1, __get_storage_key())); - store(sha256(index, __get_storage_key()), last_element); - - // decrements len by 1 - store(__get_storage_key(), len - 1); - - Result::Ok(()) - } - - /// Inserts the value at the given index, moving the current index's value aswell as the following's - /// Up one index - /// WARNING: Expensive for larger vecs - #[storage(read, write)] - pub fn insert(self, index: u64, value: V) -> Result<(), StorageVecError> { - let len = get::(__get_storage_key()); - // if the index is larger or equal to len, there is no space to insert - if index >= len { - return Result::Err(StorageVecError::IndexOutOfBounds); - } - - // for every element in the vec with an index larger than the input index, - // move the element up one index. - // performed in reverse to prevent data overwriting - let mut count = len; - while count > index { - let key = sha256((count + 1, __get_storage_key())); - // shifts all the values up one index - store(key, get(sha256((count, __get_storage_key())))); - - count -= 1 - } - - // inserts the value into the now unused index - let key = sha256((index, __get_storage_key())); - store(key, value); - - // increments len by 1 - store(__get_storage_key(), len + 1); - Result::Ok(()) - } - - /// Returns the length of the vector - #[storage(read)] - pub fn len(self) -> u64 { - get::(__get_storage_key()) - } - - /// Checks whether the len is 0 or not - #[storage(read)] - pub fn is_empty(self) -> bool { - let len = get::(__get_storage_key()); - - len == 0 - } - - /// Sets the len to 0 - #[storage(write)] - pub fn clear(self) { - store(__get_storage_key(), 0); - } -} diff --git a/test/src/sdk-harness/test_projects/harness.rs b/test/src/sdk-harness/test_projects/harness.rs index 4469718f340..77b72b36c53 100644 --- a/test/src/sdk-harness/test_projects/harness.rs +++ b/test/src/sdk-harness/test_projects/harness.rs @@ -11,5 +11,6 @@ mod registers; mod script_data; mod storage; mod storage_map; +mod storage_vec; mod token_ops; mod tx_fields; diff --git a/test/src/sdk-harness/test_projects/storage_vec/.gitignore b/test/src/sdk-harness/test_projects/storage_vec/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_projects/storage_vec/Cargo.toml b/test/src/sdk-harness/test_projects/storage_vec/Cargo.toml new file mode 100644 index 00000000000..cc3a15a5e0c --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "storage_vec" +version = "0.1.0" +authors = ["Swaystar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_projects/storage_vec/Forc.toml b/test/src/sdk-harness/test_projects/storage_vec/Forc.toml new file mode 100644 index 00000000000..404e2bb6050 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "storage_vec" + +[dependencies] +std = { path = "../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw new file mode 100644 index 00000000000..05f460bf749 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw @@ -0,0 +1,13 @@ +contract; + +use std::storage::StorageVec; + +abi MyContract { + fn test_function() -> bool; +} + +impl MyContract for Contract { + fn test_function() -> bool { + true + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/tests/harness.rs b/test/src/sdk-harness/test_projects/storage_vec/tests/harness.rs new file mode 100644 index 00000000000..c8bc8583220 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/tests/harness.rs @@ -0,0 +1,25 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(MyContract, "out/debug/storage_vec-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/storage_vec.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} From 9c2a914e1f5e65b3db58aad9561fe2fe0513774f Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 22 Jun 2022 17:56:23 +0530 Subject: [PATCH 09/59] built some of the contract -- WIP --- .../test_projects/storage_vec/src/main.sw | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw index 05f460bf749..e79aff2a977 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw +++ b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw @@ -1,13 +1,55 @@ contract; -use std::storage::StorageVec; +use std::Result::*; +use std::storage::{StorageVec, StorageVecError}; + +enum TestEnum { + A: (), + B: (), +} + +struct TestStruct { + A: bool, + B: u64, +} abi MyContract { fn test_function() -> bool; } +storage { + vec_u8: StorageVec, + vec_u16: StorageVec, + vec_u32: StorageVec, + vec_u64: StorageVec, + vec_bool: StorageVec, + vec_str4: StorageVec, + vec_b256: StorageVec, + vec_u64_tuple: StorageVec<(u64, u64)>, + vec_u64_array: StorageVec<[u64; 2]>, + vec_enum: StorageVec, + vec_struct: StorageVec, +} + impl MyContract for Contract { - fn test_function() -> bool { - true + #[store(write)] + fn vec_u8_push(value: u8) { + storage.vec_u8.push(value); + } + #[store(read)] + fn vec_u8_get(index: u64) { + storage.vec_u8.get(index); + } + #[store(write)] + fn vec_u8_pop() { + storage.vec_u8.pop(); + } + #[store(read, write)] + fn vec_u8_remove(index: u64) -> Result { + storage.vec_u8.remove(index) + } + #[store(read, write)] + fn vec_u8_swap_remove(index: u64) -> Result { + storage.vec_u8.swap_remove(index) } } From 37ed447fbd872830143005f54168c54033757a3b Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 22 Jun 2022 17:57:51 +0530 Subject: [PATCH 10/59] made it so swap_remove returns the removed element --- sway-lib-std/src/storage.sw | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index 09f6613b3d7..a1404946009 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -198,7 +198,7 @@ impl StorageVec { /// Removes the element at the specified index and fills it with the last element /// Does not preserve ordering #[storage(read, write)] - pub fn swap_remove(self, index: u64) -> Result<(), StorageVecError> { + pub fn swap_remove(self, index: u64) -> Result { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no item to remove if len <= index { @@ -210,13 +210,16 @@ impl StorageVec { return Result::Err(StorageVecError::CannotSwapAndRemoveTheSameElement); } + // gets the element before removing it, so it can be returned + let element_to_be_removed = get(sha256((index, __get_storage_key()))); + let last_element = get(sha256(len - 1, __get_storage_key())); store(sha256(index, __get_storage_key()), last_element); // decrements len by 1 store(__get_storage_key(), len - 1); - Result::Ok(()) + Result::Ok(element_to_be_removed)) } /// Inserts the value at the given index, moving the current index's value aswell as the following's From 51961a712c2a126c481a8c8f8b058019d379645b Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 22 Jun 2022 18:21:08 +0530 Subject: [PATCH 11/59] removed extra ) and added all the test functions --- sway-lib-std/src/storage.sw | 2 +- .../test_projects/storage_vec/Forc.lock | 14 + .../test_projects/storage_vec/src/main.sw | 621 +++++++++++++++++- 3 files changed, 633 insertions(+), 4 deletions(-) create mode 100644 test/src/sdk-harness/test_projects/storage_vec/Forc.lock diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index a1404946009..77587530830 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -219,7 +219,7 @@ impl StorageVec { // decrements len by 1 store(__get_storage_key(), len - 1); - Result::Ok(element_to_be_removed)) + Result::Ok(element_to_be_removed) } /// Inserts the value at the given index, moving the current index's value aswell as the following's diff --git a/test/src/sdk-harness/test_projects/storage_vec/Forc.lock b/test/src/sdk-harness/test_projects/storage_vec/Forc.lock new file mode 100644 index 00000000000..3e36af898b8 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-23C4ABBB223F2848' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-23C4ABBB223F2848' +dependencies = ['core'] + +[[package]] +name = 'storage_vec' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw index e79aff2a977..805766194ad 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw +++ b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw @@ -14,7 +14,214 @@ struct TestStruct { } abi MyContract { - fn test_function() -> bool; + #[store(write)] + fn vec_u8_push(value: u8); + #[store(read)] + fn vec_u8_get(index: u64); + #[store(write)] + fn vec_u8_pop(); + #[store(read, write)] + fn vec_u8_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_u8_swap_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError>; + #[store(read)] + fn vec_u8_len() -> u64; + #[store(read)] + fn vec_u8_is_empty() -> bool; + #[store(write)] + fn vec_u8_clear(); + + #[store(write)] + fn vec_u16_push(value: u16); + #[store(read)] + fn vec_u16_get(index: u64); + #[store(write)] + fn vec_u16_pop(); + #[store(read, write)] + fn vec_u16_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_u16_swap_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_u16_insert(index: u64, value: u16) -> Result<(), StorageVecError>; + #[store(read)] + fn vec_u16_len() -> u64; + #[store(read)] + fn vec_u16_is_empty() -> bool; + #[store(write)] + fn vec_u16_clear(); + + #[store(write)] + fn vec_u32_push(value: u32); + #[store(read)] + fn vec_u32_get(index: u64); + #[store(write)] + fn vec_u32_pop(); + #[store(read, write)] + fn vec_u32_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_u32_swap_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_u32_insert(index: u64, value: u32) -> Result<(), StorageVecError>; + #[store(read)] + fn vec_u32_len() -> u64; + #[store(read)] + fn vec_u32_is_empty() -> bool; + #[store(write)] + fn vec_u32_clear(); + + #[store(write)] + fn vec_u64_push(value: u64); + #[store(read)] + fn vec_u64_get(index: u64); + #[store(write)] + fn vec_u64_pop(); + #[store(read, write)] + fn vec_u64_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_u64_swap_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_u64_insert(index: u64, value: u64) -> Result<(), StorageVecError>; + #[store(read)] + fn vec_u64_len() -> u64; + #[store(read)] + fn vec_u64_is_empty() -> bool; + #[store(write)] + fn vec_u64_clear(); + + #[store(write)] + fn vec_bool_push(value: bool); + #[store(read)] + fn vec_bool_get(index: u64); + #[store(write)] + fn vec_bool_pop(); + #[store(read, write)] + fn vec_bool_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_bool_swap_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_bool_insert(index: u64, value: bool) -> Result<(), StorageVecError>; + #[store(read)] + fn vec_bool_len() -> u64; + #[store(read)] + fn vec_bool_is_empty() -> bool; + #[store(write)] + fn vec_bool_clear(); + + #[store(write)] + fn vec_str4_push(value: str[4]); + #[store(read)] + fn vec_str4_get(index: u64); + #[store(write)] + fn vec_str4_pop(); + #[store(read, write)] + fn vec_str4_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_str4_swap_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_str4_insert(index: u64, value: str[4]) -> Result<(), StorageVecError>; + #[store(read)] + fn vec_str4_len() -> u64; + #[store(read)] + fn vec_str4_is_empty() -> bool; + #[store(write)] + fn vec_str4_clear(); + + #[store(write)] + fn vec_b256_push(value: b256); + #[store(read)] + fn vec_b256_get(index: u64); + #[store(write)] + fn vec_b256_pop(); + #[store(read, write)] + fn vec_b256_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_b256_swap_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_b256_insert(index: u64, value: b256) -> Result<(), StorageVecError>; + #[store(read)] + fn vec_b256_len() -> u64; + #[store(read)] + fn vec_b256_is_empty() -> bool; + #[store(write)] + fn vec_b256_clear(); + + #[store(write)] + fn vec_u64_tuple_push(value: (u64, u64)); + #[store(read)] + fn vec_u64_tuple_get(index: u64); + #[store(write)] + fn vec_u64_tuple_pop(); + #[store(read, write)] + fn vec_u64_tuple_remove(index: u64) -> Result<(u64, u64), StorageVecError>; + #[store(read, write)] + fn vec_u64_tuple_swap_remove(index: u64) -> Result<(u64, u64), StorageVecError>; + #[store(read, write)] + fn vec_u64_tuple_insert(index: u64, value: (u64, u64)) -> Result<(), StorageVecError>; + #[store(read)] + fn vec_u64_tuple_len() -> u64; + #[store(read)] + fn vec_u64_tuple_is_empty() -> bool; + #[store(write)] + fn vec_u64_tuple_clear(); + + #[store(write)] + fn vec_u64_array_push(value: [u64; 2]); + #[store(read)] + fn vec_u64_array_get(index: u64); + #[store(write)] + fn vec_u64_array_pop(); + #[store(read, write)] + fn vec_u64_array_remove(index: u64) -> Result<[u64; 2], StorageVecError>; + #[store(read, write)] + fn vec_u64_array_swap_remove(index: u64) -> Result<[u64; 2], StorageVecError>; + #[store(read, write)] + fn vec_u64_array_insert(index: u64, value: [u64; 2]) -> Result<(), StorageVecError>; + #[store(read)] + fn vec_u64_array_len() -> u64; + #[store(read)] + fn vec_u64_array_is_empty() -> bool; + #[store(write)] + fn vec_u64_array_clear(); + + #[store(write)] + fn vec_enum_push(value: TestEnum); + #[store(read)] + fn vec_enum_get(index: u64); + #[store(write)] + fn vec_enum_pop(); + #[store(read, write)] + fn vec_enum_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_enum_swap_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_enum_insert(index: u64, value: TestEnum) -> Result<(), StorageVecError>; + #[store(read)] + fn vec_enum_len() -> u64; + #[store(read)] + fn vec_enum_is_empty() -> bool; + #[store(write)] + fn vec_enum_clear(); + + #[store(write)] + fn vec_struct_push(value: TestStruct); + #[store(read)] + fn vec_struct_get(index: u64); + #[store(write)] + fn vec_struct_pop(); + #[store(read, write)] + fn vec_struct_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_struct_swap_remove(index: u64) -> Result; + #[store(read, write)] + fn vec_struct_insert(index: u64, value: TestStruct) -> Result<(), StorageVecError>; + #[store(read)] + fn vec_struct_len() -> u64; + #[store(read)] + fn vec_struct_is_empty() -> bool; + #[store(write)] + fn vec_struct_clear(); } storage { @@ -45,11 +252,419 @@ impl MyContract for Contract { storage.vec_u8.pop(); } #[store(read, write)] - fn vec_u8_remove(index: u64) -> Result { + fn vec_u8_remove(index: u64) -> Result { storage.vec_u8.remove(index) } #[store(read, write)] - fn vec_u8_swap_remove(index: u64) -> Result { + fn vec_u8_swap_remove(index: u64) -> Result { storage.vec_u8.swap_remove(index) } + #[store(read, write)] + fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError> { + storage.vec_u8.insert(index, value) + } + #[store(read)] + fn vec_u8_len() -> u64 { + storage.vec_u8.len() + } + #[store(read)] + fn vec_u8_is_empty() -> bool { + storage.vec_u8.is_empty() + } + #[store(write)] + fn vec_u8_clear() { + storage.vec_u8.clear(); + } + + + + #[store(write)] + fn vec_u16_push(value: u16) { + storage.vec_u16.push(value); + } + #[store(read)] + fn vec_u16_get(index: u64) { + storage.vec_u16.get(index); + } + #[store(write)] + fn vec_u16_pop() { + storage.vec_u16.pop(); + } + #[store(read, write)] + fn vec_u16_remove(index: u64) -> Result { + storage.vec_u16.remove(index) + } + #[store(read, write)] + fn vec_u16_swap_remove(index: u64) -> Result { + storage.vec_u16.swap_remove(index) + } + #[store(read, write)] + fn vec_u16_insert(index: u64, value: u16) -> Result<(), StorageVecError> { + storage.vec_u16.insert(index, value) + } + #[store(read)] + fn vec_u16_len() -> u64 { + storage.vec_u16.len() + } + #[store(read)] + fn vec_u16_is_empty() -> bool { + storage.vec_u16.is_empty() + } + #[store(write)] + fn vec_u16_clear() { + storage.vec_u16.clear(); + } + + + + #[store(write)] + fn vec_u32_push(value: u32) { + storage.vec_u32.push(value); + } + #[store(read)] + fn vec_u32_get(index: u64) { + storage.vec_u32.get(index); + } + #[store(write)] + fn vec_u32_pop() { + storage.vec_u32.pop(); + } + #[store(read, write)] + fn vec_u32_remove(index: u64) -> Result { + storage.vec_u32.remove(index) + } + #[store(read, write)] + fn vec_u32_swap_remove(index: u64) -> Result { + storage.vec_u32.swap_remove(index) + } + #[store(read, write)] + fn vec_u32_insert(index: u64, value: u32) -> Result<(), StorageVecError> { + storage.vec_u32.insert(index, value) + } + #[store(read)] + fn vec_u32_len() -> u64 { + storage.vec_u32.len() + } + #[store(read)] + fn vec_u32_is_empty() -> bool { + storage.vec_u32.is_empty() + } + #[store(write)] + fn vec_u32_clear() { + storage.vec_u32.clear(); + } + + + + + #[store(write)] + fn vec_u64_push(value: u64) { + storage.vec_u64.push(value); + } + #[store(read)] + fn vec_u64_get(index: u64) { + storage.vec_u64.get(index); + } + #[store(write)] + fn vec_u64_pop() { + storage.vec_u64.pop(); + } + #[store(read, write)] + fn vec_u64_remove(index: u64) -> Result { + storage.vec_u64.remove(index) + } + #[store(read, write)] + fn vec_u64_swap_remove(index: u64) -> Result { + storage.vec_u64.swap_remove(index) + } + #[store(read, write)] + fn vec_u64_insert(index: u64, value: u64) -> Result<(), StorageVecError> { + storage.vec_u64.insert(index, value) + } + #[store(read)] + fn vec_u64_len() -> u64 { + storage.vec_u64.len() + } + #[store(read)] + fn vec_u64_is_empty() -> bool { + storage.vec_u64.is_empty() + } + #[store(write)] + fn vec_u64_clear() { + storage.vec_u64.clear(); + } + + + + #[store(write)] + fn vec_bool_push(value: bool) { + storage.vec_bool.push(value); + } + #[store(read)] + fn vec_bool_get(index: u64) { + storage.vec_bool.get(index); + } + #[store(write)] + fn vec_bool_pop() { + storage.vec_bool.pop(); + } + #[store(read, write)] + fn vec_bool_remove(index: u64) -> Result { + storage.vec_bool.remove(index) + } + #[store(read, write)] + fn vec_bool_swap_remove(index: u64) -> Result { + storage.vec_bool.swap_remove(index) + } + #[store(read, write)] + fn vec_bool_insert(index: u64, value: bool) -> Result<(), StorageVecError> { + storage.vec_bool.insert(index, value) + } + #[store(read)] + fn vec_bool_len() -> u64 { + storage.vec_bool.len() + } + #[store(read)] + fn vec_bool_is_empty() -> bool { + storage.vec_bool.is_empty() + } + #[store(write)] + fn vec_bool_clear() { + storage.vec_bool.clear(); + } + + + + + #[store(write)] + fn vec_str4_push(value: str[4]) { + storage.vec_str4.push(value); + } + #[store(read)] + fn vec_str4_get(index: u64) { + storage.vec_str4.get(index); + } + #[store(write)] + fn vec_str4_pop() { + storage.vec_str4.pop(); + } + #[store(read, write)] + fn vec_str4_remove(index: u64) -> Result { + storage.vec_str4.remove(index) + } + #[store(read, write)] + fn vec_str4_swap_remove(index: u64) -> Result { + storage.vec_str4.swap_remove(index) + } + #[store(read, write)] + fn vec_str4_insert(index: u64, value: str[4]) -> Result<(), StorageVecError> { + storage.vec_str4.insert(index, value) + } + #[store(read)] + fn vec_str4_len() -> u64 { + storage.vec_str4.len() + } + #[store(read)] + fn vec_str4_is_empty() -> bool { + storage.vec_str4.is_empty() + } + #[store(write)] + fn vec_str4_clear() { + storage.vec_str4.clear(); + } + + + + #[store(write)] + fn vec_b256_push(value: b256) { + storage.vec_b256.push(value); + } + #[store(read)] + fn vec_b256_get(index: u64) { + storage.vec_b256.get(index); + } + #[store(write)] + fn vec_b256_pop() { + storage.vec_b256.pop(); + } + #[store(read, write)] + fn vec_b256_remove(index: u64) -> Result { + storage.vec_b256.remove(index) + } + #[store(read, write)] + fn vec_b256_swap_remove(index: u64) -> Result { + storage.vec_b256.swap_remove(index) + } + #[store(read, write)] + fn vec_b256_insert(index: u64, value: b256) -> Result<(), StorageVecError> { + storage.vec_b256.insert(index, value) + } + #[store(read)] + fn vec_b256_len() -> u64 { + storage.vec_b256.len() + } + #[store(read)] + fn vec_b256_is_empty() -> bool { + storage.vec_b256.is_empty() + } + #[store(write)] + fn vec_b256_clear() { + storage.vec_b256.clear(); + } + + + + #[store(write)] + fn vec_u64_tuple_push(value: (u64, u64)) { + storage.vec_u64_tuple.push(value); + } + #[store(read)] + fn vec_u64_tuple_get(index: u64) { + storage.vec_u64_tuple.get(index); + } + #[store(write)] + fn vec_u64_tuple_pop() { + storage.vec_u64_tuple.pop(); + } + #[store(read, write)] + fn vec_u64_tuple_remove(index: u64) -> Result<(u64, u64), StorageVecError> { + storage.vec_u64_tuple.remove(index) + } + #[store(read, write)] + fn vec_u64_tuple_swap_remove(index: u64) -> Result<(u64, u64), StorageVecError> { + storage.vec_u64_tuple.swap_remove(index) + } + #[store(read, write)] + fn vec_u64_tuple_insert(index: u64, value: (u64, u64)) -> Result<(), StorageVecError> { + storage.vec_u64_tuple.insert(index, value) + } + #[store(read)] + fn vec_u64_tuple_len() -> u64 { + storage.vec_u64_tuple.len() + } + #[store(read)] + fn vec_u64_tuple_is_empty() -> bool { + storage.vec_u64_tuple.is_empty() + } + #[store(write)] + fn vec_u64_tuple_clear() { + storage.vec_u64_tuple.clear(); + } + + + + #[store(write)] + fn vec_u64_array_push(value: [u64, u64]) { + storage.vec_u64_array.push(value); + } + #[store(read)] + fn vec_u64_array_get(index: u64) { + storage.vec_u64_array.get(index); + } + #[store(write)] + fn vec_u64_array_pop() { + storage.vec_u64_array.pop(); + } + #[store(read, write)] + fn vec_u64_array_remove(index: u64) -> Result<[u64, u64], StorageVecError> { + storage.vec_u64_array.remove(index) + } + #[store(read, write)] + fn vec_u64_array_swap_remove(index: u64) -> Result<[u64, u64], StorageVecError> { + storage.vec_u64_array.swap_remove(index) + } + #[store(read, write)] + fn vec_u64_array_insert(index: u64, value: [u64, u64]) -> Result<(), StorageVecError> { + storage.vec_u64_array.insert(index, value) + } + #[store(read)] + fn vec_u64_array_len() -> u64 { + storage.vec_u64_array.len() + } + #[store(read)] + fn vec_u64_array_is_empty() -> bool { + storage.vec_u64_array.is_empty() + } + #[store(write)] + fn vec_u64_array_clear() { + storage.vec_u64_array.clear(); + } + + + + #[store(write)] + fn vec_enum_push(value: TestEnum) { + storage.vec_enum.push(value); + } + #[store(read)] + fn vec_enum_get(index: u64) { + storage.vec_enum.get(index); + } + #[store(write)] + fn vec_enum_pop() { + storage.vec_enum.pop(); + } + #[store(read, write)] + fn vec_enum_remove(index: u64) -> Result { + storage.vec_enum.remove(index) + } + #[store(read, write)] + fn vec_enum_swap_remove(index: u64) -> Result { + storage.vec_enum.swap_remove(index) + } + #[store(read, write)] + fn vec_enum_insert(index: u64, value: TestEnum) -> Result<(), StorageVecError> { + storage.vec_enum.insert(index, value) + } + #[store(read)] + fn vec_enum_len() -> u64 { + storage.vec_enum.len() + } + #[store(read)] + fn vec_enum_is_empty() -> bool { + storage.vec_enum.is_empty() + } + #[store(write)] + fn vec_enum_clear() { + storage.vec_enum.clear(); + } + + + + #[store(write)] + fn vec_struct_push(value: TestStruct) { + storage.vec_struct.push(value); + } + #[store(read)] + fn vec_struct_get(index: u64) { + storage.vec_struct.get(index); + } + #[store(write)] + fn vec_struct_pop() { + storage.vec_struct.pop(); + } + #[store(read, write)] + fn vec_struct_remove(index: u64) -> Result { + storage.vec_struct.remove(index) + } + #[store(read, write)] + fn vec_struct_swap_remove(index: u64) -> Result { + storage.vec_struct.swap_remove(index) + } + #[store(read, write)] + fn vec_struct_insert(index: u64, value: TestStruct) -> Result<(),StorageVecError> { + storage.vec_struct.insert(index, value) + } + #[store(read)] + fn vec_struct_len() -> u64 { + storage.vec_struct.len() + } + #[store(read)] + fn vec_struct_is_empty() -> bool { + storage.vec_struct.is_empty() + } + #[store(write)] + fn vec_struct_clear() { + storage.vec_struct.clear(); + } } From c42229dfd767b331ac305c8a311a82e79681cdf0 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 22 Jun 2022 18:23:00 +0530 Subject: [PATCH 12/59] fixed a syntax error --- .../src/sdk-harness/test_projects/storage_vec/src/main.sw | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw index 805766194ad..21772a15a41 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw +++ b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw @@ -554,7 +554,7 @@ impl MyContract for Contract { #[store(write)] - fn vec_u64_array_push(value: [u64, u64]) { + fn vec_u64_array_push(value: [u64; 2]) { storage.vec_u64_array.push(value); } #[store(read)] @@ -566,15 +566,15 @@ impl MyContract for Contract { storage.vec_u64_array.pop(); } #[store(read, write)] - fn vec_u64_array_remove(index: u64) -> Result<[u64, u64], StorageVecError> { + fn vec_u64_array_remove(index: u64) -> Result<[u64; 2], StorageVecError> { storage.vec_u64_array.remove(index) } #[store(read, write)] - fn vec_u64_array_swap_remove(index: u64) -> Result<[u64, u64], StorageVecError> { + fn vec_u64_array_swap_remove(index: u64) -> Result<[u64; 2], StorageVecError> { storage.vec_u64_array.swap_remove(index) } #[store(read, write)] - fn vec_u64_array_insert(index: u64, value: [u64, u64]) -> Result<(), StorageVecError> { + fn vec_u64_array_insert(index: u64, value: [u64; 2]) -> Result<(), StorageVecError> { storage.vec_u64_array.insert(index, value) } #[store(read)] From 8b059b35377d11dc987299e80d4ada5526d5f132 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 22 Jun 2022 18:30:10 +0530 Subject: [PATCH 13/59] changed store to storage --- .../test_projects/storage_vec/src/main.sw | 398 +++++++++--------- 1 file changed, 199 insertions(+), 199 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw index 21772a15a41..599063bc980 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw +++ b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw @@ -1,6 +1,6 @@ contract; -use std::Result::*; +use std::result::*; use std::storage::{StorageVec, StorageVecError}; enum TestEnum { @@ -14,213 +14,213 @@ struct TestStruct { } abi MyContract { - #[store(write)] + #[storage(write)] fn vec_u8_push(value: u8); - #[store(read)] + #[storage(read)] fn vec_u8_get(index: u64); - #[store(write)] + #[storage(write)] fn vec_u8_pop(); - #[store(read, write)] + #[storage(read, write)] fn vec_u8_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_u8_swap_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError>; - #[store(read)] + #[storage(read)] fn vec_u8_len() -> u64; - #[store(read)] + #[storage(read)] fn vec_u8_is_empty() -> bool; - #[store(write)] + #[storage(write)] fn vec_u8_clear(); - #[store(write)] + #[storage(write)] fn vec_u16_push(value: u16); - #[store(read)] + #[storage(read)] fn vec_u16_get(index: u64); - #[store(write)] + #[storage(write)] fn vec_u16_pop(); - #[store(read, write)] + #[storage(read, write)] fn vec_u16_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_u16_swap_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_u16_insert(index: u64, value: u16) -> Result<(), StorageVecError>; - #[store(read)] + #[storage(read)] fn vec_u16_len() -> u64; - #[store(read)] + #[storage(read)] fn vec_u16_is_empty() -> bool; - #[store(write)] + #[storage(write)] fn vec_u16_clear(); - #[store(write)] + #[storage(write)] fn vec_u32_push(value: u32); - #[store(read)] + #[storage(read)] fn vec_u32_get(index: u64); - #[store(write)] + #[storage(write)] fn vec_u32_pop(); - #[store(read, write)] + #[storage(read, write)] fn vec_u32_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_u32_swap_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_u32_insert(index: u64, value: u32) -> Result<(), StorageVecError>; - #[store(read)] + #[storage(read)] fn vec_u32_len() -> u64; - #[store(read)] + #[storage(read)] fn vec_u32_is_empty() -> bool; - #[store(write)] + #[storage(write)] fn vec_u32_clear(); - #[store(write)] + #[storage(write)] fn vec_u64_push(value: u64); - #[store(read)] + #[storage(read)] fn vec_u64_get(index: u64); - #[store(write)] + #[storage(write)] fn vec_u64_pop(); - #[store(read, write)] + #[storage(read, write)] fn vec_u64_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_u64_swap_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_u64_insert(index: u64, value: u64) -> Result<(), StorageVecError>; - #[store(read)] + #[storage(read)] fn vec_u64_len() -> u64; - #[store(read)] + #[storage(read)] fn vec_u64_is_empty() -> bool; - #[store(write)] + #[storage(write)] fn vec_u64_clear(); - #[store(write)] + #[storage(write)] fn vec_bool_push(value: bool); - #[store(read)] + #[storage(read)] fn vec_bool_get(index: u64); - #[store(write)] + #[storage(write)] fn vec_bool_pop(); - #[store(read, write)] + #[storage(read, write)] fn vec_bool_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_bool_swap_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_bool_insert(index: u64, value: bool) -> Result<(), StorageVecError>; - #[store(read)] + #[storage(read)] fn vec_bool_len() -> u64; - #[store(read)] + #[storage(read)] fn vec_bool_is_empty() -> bool; - #[store(write)] + #[storage(write)] fn vec_bool_clear(); - #[store(write)] + #[storage(write)] fn vec_str4_push(value: str[4]); - #[store(read)] + #[storage(read)] fn vec_str4_get(index: u64); - #[store(write)] + #[storage(write)] fn vec_str4_pop(); - #[store(read, write)] + #[storage(read, write)] fn vec_str4_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_str4_swap_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_str4_insert(index: u64, value: str[4]) -> Result<(), StorageVecError>; - #[store(read)] + #[storage(read)] fn vec_str4_len() -> u64; - #[store(read)] + #[storage(read)] fn vec_str4_is_empty() -> bool; - #[store(write)] + #[storage(write)] fn vec_str4_clear(); - #[store(write)] + #[storage(write)] fn vec_b256_push(value: b256); - #[store(read)] + #[storage(read)] fn vec_b256_get(index: u64); - #[store(write)] + #[storage(write)] fn vec_b256_pop(); - #[store(read, write)] + #[storage(read, write)] fn vec_b256_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_b256_swap_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_b256_insert(index: u64, value: b256) -> Result<(), StorageVecError>; - #[store(read)] + #[storage(read)] fn vec_b256_len() -> u64; - #[store(read)] + #[storage(read)] fn vec_b256_is_empty() -> bool; - #[store(write)] + #[storage(write)] fn vec_b256_clear(); - #[store(write)] + #[storage(write)] fn vec_u64_tuple_push(value: (u64, u64)); - #[store(read)] + #[storage(read)] fn vec_u64_tuple_get(index: u64); - #[store(write)] + #[storage(write)] fn vec_u64_tuple_pop(); - #[store(read, write)] + #[storage(read, write)] fn vec_u64_tuple_remove(index: u64) -> Result<(u64, u64), StorageVecError>; - #[store(read, write)] + #[storage(read, write)] fn vec_u64_tuple_swap_remove(index: u64) -> Result<(u64, u64), StorageVecError>; - #[store(read, write)] + #[storage(read, write)] fn vec_u64_tuple_insert(index: u64, value: (u64, u64)) -> Result<(), StorageVecError>; - #[store(read)] + #[storage(read)] fn vec_u64_tuple_len() -> u64; - #[store(read)] + #[storage(read)] fn vec_u64_tuple_is_empty() -> bool; - #[store(write)] + #[storage(write)] fn vec_u64_tuple_clear(); - #[store(write)] + #[storage(write)] fn vec_u64_array_push(value: [u64; 2]); - #[store(read)] + #[storage(read)] fn vec_u64_array_get(index: u64); - #[store(write)] + #[storage(write)] fn vec_u64_array_pop(); - #[store(read, write)] + #[storage(read, write)] fn vec_u64_array_remove(index: u64) -> Result<[u64; 2], StorageVecError>; - #[store(read, write)] + #[storage(read, write)] fn vec_u64_array_swap_remove(index: u64) -> Result<[u64; 2], StorageVecError>; - #[store(read, write)] + #[storage(read, write)] fn vec_u64_array_insert(index: u64, value: [u64; 2]) -> Result<(), StorageVecError>; - #[store(read)] + #[storage(read)] fn vec_u64_array_len() -> u64; - #[store(read)] + #[storage(read)] fn vec_u64_array_is_empty() -> bool; - #[store(write)] + #[storage(write)] fn vec_u64_array_clear(); - #[store(write)] + #[storage(write)] fn vec_enum_push(value: TestEnum); - #[store(read)] + #[storage(read)] fn vec_enum_get(index: u64); - #[store(write)] + #[storage(write)] fn vec_enum_pop(); - #[store(read, write)] + #[storage(read, write)] fn vec_enum_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_enum_swap_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_enum_insert(index: u64, value: TestEnum) -> Result<(), StorageVecError>; - #[store(read)] + #[storage(read)] fn vec_enum_len() -> u64; - #[store(read)] + #[storage(read)] fn vec_enum_is_empty() -> bool; - #[store(write)] + #[storage(write)] fn vec_enum_clear(); - #[store(write)] + #[storage(write)] fn vec_struct_push(value: TestStruct); - #[store(read)] + #[storage(read)] fn vec_struct_get(index: u64); - #[store(write)] + #[storage(write)] fn vec_struct_pop(); - #[store(read, write)] + #[storage(read, write)] fn vec_struct_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_struct_swap_remove(index: u64) -> Result; - #[store(read, write)] + #[storage(read, write)] fn vec_struct_insert(index: u64, value: TestStruct) -> Result<(), StorageVecError>; - #[store(read)] + #[storage(read)] fn vec_struct_len() -> u64; - #[store(read)] + #[storage(read)] fn vec_struct_is_empty() -> bool; - #[store(write)] + #[storage(write)] fn vec_struct_clear(); } @@ -239,117 +239,117 @@ storage { } impl MyContract for Contract { - #[store(write)] + #[storage(write)] fn vec_u8_push(value: u8) { storage.vec_u8.push(value); } - #[store(read)] + #[storage(read)] fn vec_u8_get(index: u64) { storage.vec_u8.get(index); } - #[store(write)] + #[storage(write)] fn vec_u8_pop() { storage.vec_u8.pop(); } - #[store(read, write)] + #[storage(read, write)] fn vec_u8_remove(index: u64) -> Result { storage.vec_u8.remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_u8_swap_remove(index: u64) -> Result { storage.vec_u8.swap_remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError> { storage.vec_u8.insert(index, value) } - #[store(read)] + #[storage(read)] fn vec_u8_len() -> u64 { storage.vec_u8.len() } - #[store(read)] + #[storage(read)] fn vec_u8_is_empty() -> bool { storage.vec_u8.is_empty() } - #[store(write)] + #[storage(write)] fn vec_u8_clear() { storage.vec_u8.clear(); } - #[store(write)] + #[storage(write)] fn vec_u16_push(value: u16) { storage.vec_u16.push(value); } - #[store(read)] + #[storage(read)] fn vec_u16_get(index: u64) { storage.vec_u16.get(index); } - #[store(write)] + #[storage(write)] fn vec_u16_pop() { storage.vec_u16.pop(); } - #[store(read, write)] + #[storage(read, write)] fn vec_u16_remove(index: u64) -> Result { storage.vec_u16.remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_u16_swap_remove(index: u64) -> Result { storage.vec_u16.swap_remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_u16_insert(index: u64, value: u16) -> Result<(), StorageVecError> { storage.vec_u16.insert(index, value) } - #[store(read)] + #[storage(read)] fn vec_u16_len() -> u64 { storage.vec_u16.len() } - #[store(read)] + #[storage(read)] fn vec_u16_is_empty() -> bool { storage.vec_u16.is_empty() } - #[store(write)] + #[storage(write)] fn vec_u16_clear() { storage.vec_u16.clear(); } - #[store(write)] + #[storage(write)] fn vec_u32_push(value: u32) { storage.vec_u32.push(value); } - #[store(read)] + #[storage(read)] fn vec_u32_get(index: u64) { storage.vec_u32.get(index); } - #[store(write)] + #[storage(write)] fn vec_u32_pop() { storage.vec_u32.pop(); } - #[store(read, write)] + #[storage(read, write)] fn vec_u32_remove(index: u64) -> Result { storage.vec_u32.remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_u32_swap_remove(index: u64) -> Result { storage.vec_u32.swap_remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_u32_insert(index: u64, value: u32) -> Result<(), StorageVecError> { storage.vec_u32.insert(index, value) } - #[store(read)] + #[storage(read)] fn vec_u32_len() -> u64 { storage.vec_u32.len() } - #[store(read)] + #[storage(read)] fn vec_u32_is_empty() -> bool { storage.vec_u32.is_empty() } - #[store(write)] + #[storage(write)] fn vec_u32_clear() { storage.vec_u32.clear(); } @@ -357,78 +357,78 @@ impl MyContract for Contract { - #[store(write)] + #[storage(write)] fn vec_u64_push(value: u64) { storage.vec_u64.push(value); } - #[store(read)] + #[storage(read)] fn vec_u64_get(index: u64) { storage.vec_u64.get(index); } - #[store(write)] + #[storage(write)] fn vec_u64_pop() { storage.vec_u64.pop(); } - #[store(read, write)] + #[storage(read, write)] fn vec_u64_remove(index: u64) -> Result { storage.vec_u64.remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_u64_swap_remove(index: u64) -> Result { storage.vec_u64.swap_remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_u64_insert(index: u64, value: u64) -> Result<(), StorageVecError> { storage.vec_u64.insert(index, value) } - #[store(read)] + #[storage(read)] fn vec_u64_len() -> u64 { storage.vec_u64.len() } - #[store(read)] + #[storage(read)] fn vec_u64_is_empty() -> bool { storage.vec_u64.is_empty() } - #[store(write)] + #[storage(write)] fn vec_u64_clear() { storage.vec_u64.clear(); } - #[store(write)] + #[storage(write)] fn vec_bool_push(value: bool) { storage.vec_bool.push(value); } - #[store(read)] + #[storage(read)] fn vec_bool_get(index: u64) { storage.vec_bool.get(index); } - #[store(write)] + #[storage(write)] fn vec_bool_pop() { storage.vec_bool.pop(); } - #[store(read, write)] + #[storage(read, write)] fn vec_bool_remove(index: u64) -> Result { storage.vec_bool.remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_bool_swap_remove(index: u64) -> Result { storage.vec_bool.swap_remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_bool_insert(index: u64, value: bool) -> Result<(), StorageVecError> { storage.vec_bool.insert(index, value) } - #[store(read)] + #[storage(read)] fn vec_bool_len() -> u64 { storage.vec_bool.len() } - #[store(read)] + #[storage(read)] fn vec_bool_is_empty() -> bool { storage.vec_bool.is_empty() } - #[store(write)] + #[storage(write)] fn vec_bool_clear() { storage.vec_bool.clear(); } @@ -436,234 +436,234 @@ impl MyContract for Contract { - #[store(write)] + #[storage(write)] fn vec_str4_push(value: str[4]) { storage.vec_str4.push(value); } - #[store(read)] + #[storage(read)] fn vec_str4_get(index: u64) { storage.vec_str4.get(index); } - #[store(write)] + #[storage(write)] fn vec_str4_pop() { storage.vec_str4.pop(); } - #[store(read, write)] + #[storage(read, write)] fn vec_str4_remove(index: u64) -> Result { storage.vec_str4.remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_str4_swap_remove(index: u64) -> Result { storage.vec_str4.swap_remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_str4_insert(index: u64, value: str[4]) -> Result<(), StorageVecError> { storage.vec_str4.insert(index, value) } - #[store(read)] + #[storage(read)] fn vec_str4_len() -> u64 { storage.vec_str4.len() } - #[store(read)] + #[storage(read)] fn vec_str4_is_empty() -> bool { storage.vec_str4.is_empty() } - #[store(write)] + #[storage(write)] fn vec_str4_clear() { storage.vec_str4.clear(); } - #[store(write)] + #[storage(write)] fn vec_b256_push(value: b256) { storage.vec_b256.push(value); } - #[store(read)] + #[storage(read)] fn vec_b256_get(index: u64) { storage.vec_b256.get(index); } - #[store(write)] + #[storage(write)] fn vec_b256_pop() { storage.vec_b256.pop(); } - #[store(read, write)] + #[storage(read, write)] fn vec_b256_remove(index: u64) -> Result { storage.vec_b256.remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_b256_swap_remove(index: u64) -> Result { storage.vec_b256.swap_remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_b256_insert(index: u64, value: b256) -> Result<(), StorageVecError> { storage.vec_b256.insert(index, value) } - #[store(read)] + #[storage(read)] fn vec_b256_len() -> u64 { storage.vec_b256.len() } - #[store(read)] + #[storage(read)] fn vec_b256_is_empty() -> bool { storage.vec_b256.is_empty() } - #[store(write)] + #[storage(write)] fn vec_b256_clear() { storage.vec_b256.clear(); } - #[store(write)] + #[storage(write)] fn vec_u64_tuple_push(value: (u64, u64)) { storage.vec_u64_tuple.push(value); } - #[store(read)] + #[storage(read)] fn vec_u64_tuple_get(index: u64) { storage.vec_u64_tuple.get(index); } - #[store(write)] + #[storage(write)] fn vec_u64_tuple_pop() { storage.vec_u64_tuple.pop(); } - #[store(read, write)] + #[storage(read, write)] fn vec_u64_tuple_remove(index: u64) -> Result<(u64, u64), StorageVecError> { storage.vec_u64_tuple.remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_u64_tuple_swap_remove(index: u64) -> Result<(u64, u64), StorageVecError> { storage.vec_u64_tuple.swap_remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_u64_tuple_insert(index: u64, value: (u64, u64)) -> Result<(), StorageVecError> { storage.vec_u64_tuple.insert(index, value) } - #[store(read)] + #[storage(read)] fn vec_u64_tuple_len() -> u64 { storage.vec_u64_tuple.len() } - #[store(read)] + #[storage(read)] fn vec_u64_tuple_is_empty() -> bool { storage.vec_u64_tuple.is_empty() } - #[store(write)] + #[storage(write)] fn vec_u64_tuple_clear() { storage.vec_u64_tuple.clear(); } - #[store(write)] + #[storage(write)] fn vec_u64_array_push(value: [u64; 2]) { storage.vec_u64_array.push(value); } - #[store(read)] + #[storage(read)] fn vec_u64_array_get(index: u64) { storage.vec_u64_array.get(index); } - #[store(write)] + #[storage(write)] fn vec_u64_array_pop() { storage.vec_u64_array.pop(); } - #[store(read, write)] + #[storage(read, write)] fn vec_u64_array_remove(index: u64) -> Result<[u64; 2], StorageVecError> { storage.vec_u64_array.remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_u64_array_swap_remove(index: u64) -> Result<[u64; 2], StorageVecError> { storage.vec_u64_array.swap_remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_u64_array_insert(index: u64, value: [u64; 2]) -> Result<(), StorageVecError> { storage.vec_u64_array.insert(index, value) } - #[store(read)] + #[storage(read)] fn vec_u64_array_len() -> u64 { storage.vec_u64_array.len() } - #[store(read)] + #[storage(read)] fn vec_u64_array_is_empty() -> bool { storage.vec_u64_array.is_empty() } - #[store(write)] + #[storage(write)] fn vec_u64_array_clear() { storage.vec_u64_array.clear(); } - #[store(write)] + #[storage(write)] fn vec_enum_push(value: TestEnum) { storage.vec_enum.push(value); } - #[store(read)] + #[storage(read)] fn vec_enum_get(index: u64) { storage.vec_enum.get(index); } - #[store(write)] + #[storage(write)] fn vec_enum_pop() { storage.vec_enum.pop(); } - #[store(read, write)] + #[storage(read, write)] fn vec_enum_remove(index: u64) -> Result { storage.vec_enum.remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_enum_swap_remove(index: u64) -> Result { storage.vec_enum.swap_remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_enum_insert(index: u64, value: TestEnum) -> Result<(), StorageVecError> { storage.vec_enum.insert(index, value) } - #[store(read)] + #[storage(read)] fn vec_enum_len() -> u64 { storage.vec_enum.len() } - #[store(read)] + #[storage(read)] fn vec_enum_is_empty() -> bool { storage.vec_enum.is_empty() } - #[store(write)] + #[storage(write)] fn vec_enum_clear() { storage.vec_enum.clear(); } - #[store(write)] + #[storage(write)] fn vec_struct_push(value: TestStruct) { storage.vec_struct.push(value); } - #[store(read)] + #[storage(read)] fn vec_struct_get(index: u64) { storage.vec_struct.get(index); } - #[store(write)] + #[storage(write)] fn vec_struct_pop() { storage.vec_struct.pop(); } - #[store(read, write)] + #[storage(read, write)] fn vec_struct_remove(index: u64) -> Result { storage.vec_struct.remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_struct_swap_remove(index: u64) -> Result { storage.vec_struct.swap_remove(index) } - #[store(read, write)] + #[storage(read, write)] fn vec_struct_insert(index: u64, value: TestStruct) -> Result<(),StorageVecError> { storage.vec_struct.insert(index, value) } - #[store(read)] + #[storage(read)] fn vec_struct_len() -> u64 { storage.vec_struct.len() } - #[store(read)] + #[storage(read)] fn vec_struct_is_empty() -> bool { storage.vec_struct.is_empty() } - #[store(write)] + #[storage(write)] fn vec_struct_clear() { storage.vec_struct.clear(); } From 082ded9adfa3fb67d641dfa7289f407a4c7e3be6 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 22 Jun 2022 18:31:35 +0530 Subject: [PATCH 14/59] removed all other types for now --- .../test_projects/storage_vec/src/main.sw | 580 +----------------- 1 file changed, 2 insertions(+), 578 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw index 599063bc980..1f00a55db7e 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw +++ b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw @@ -33,195 +33,7 @@ abi MyContract { #[storage(write)] fn vec_u8_clear(); - #[storage(write)] - fn vec_u16_push(value: u16); - #[storage(read)] - fn vec_u16_get(index: u64); - #[storage(write)] - fn vec_u16_pop(); - #[storage(read, write)] - fn vec_u16_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u16_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u16_insert(index: u64, value: u16) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_u16_len() -> u64; - #[storage(read)] - fn vec_u16_is_empty() -> bool; - #[storage(write)] - fn vec_u16_clear(); - - #[storage(write)] - fn vec_u32_push(value: u32); - #[storage(read)] - fn vec_u32_get(index: u64); - #[storage(write)] - fn vec_u32_pop(); - #[storage(read, write)] - fn vec_u32_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u32_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u32_insert(index: u64, value: u32) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_u32_len() -> u64; - #[storage(read)] - fn vec_u32_is_empty() -> bool; - #[storage(write)] - fn vec_u32_clear(); - - #[storage(write)] - fn vec_u64_push(value: u64); - #[storage(read)] - fn vec_u64_get(index: u64); - #[storage(write)] - fn vec_u64_pop(); - #[storage(read, write)] - fn vec_u64_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u64_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u64_insert(index: u64, value: u64) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_u64_len() -> u64; - #[storage(read)] - fn vec_u64_is_empty() -> bool; - #[storage(write)] - fn vec_u64_clear(); - - #[storage(write)] - fn vec_bool_push(value: bool); - #[storage(read)] - fn vec_bool_get(index: u64); - #[storage(write)] - fn vec_bool_pop(); - #[storage(read, write)] - fn vec_bool_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_bool_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_bool_insert(index: u64, value: bool) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_bool_len() -> u64; - #[storage(read)] - fn vec_bool_is_empty() -> bool; - #[storage(write)] - fn vec_bool_clear(); - - #[storage(write)] - fn vec_str4_push(value: str[4]); - #[storage(read)] - fn vec_str4_get(index: u64); - #[storage(write)] - fn vec_str4_pop(); - #[storage(read, write)] - fn vec_str4_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_str4_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_str4_insert(index: u64, value: str[4]) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_str4_len() -> u64; - #[storage(read)] - fn vec_str4_is_empty() -> bool; - #[storage(write)] - fn vec_str4_clear(); - - #[storage(write)] - fn vec_b256_push(value: b256); - #[storage(read)] - fn vec_b256_get(index: u64); - #[storage(write)] - fn vec_b256_pop(); - #[storage(read, write)] - fn vec_b256_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_b256_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_b256_insert(index: u64, value: b256) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_b256_len() -> u64; - #[storage(read)] - fn vec_b256_is_empty() -> bool; - #[storage(write)] - fn vec_b256_clear(); - - #[storage(write)] - fn vec_u64_tuple_push(value: (u64, u64)); - #[storage(read)] - fn vec_u64_tuple_get(index: u64); - #[storage(write)] - fn vec_u64_tuple_pop(); - #[storage(read, write)] - fn vec_u64_tuple_remove(index: u64) -> Result<(u64, u64), StorageVecError>; - #[storage(read, write)] - fn vec_u64_tuple_swap_remove(index: u64) -> Result<(u64, u64), StorageVecError>; - #[storage(read, write)] - fn vec_u64_tuple_insert(index: u64, value: (u64, u64)) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_u64_tuple_len() -> u64; - #[storage(read)] - fn vec_u64_tuple_is_empty() -> bool; - #[storage(write)] - fn vec_u64_tuple_clear(); - - #[storage(write)] - fn vec_u64_array_push(value: [u64; 2]); - #[storage(read)] - fn vec_u64_array_get(index: u64); - #[storage(write)] - fn vec_u64_array_pop(); - #[storage(read, write)] - fn vec_u64_array_remove(index: u64) -> Result<[u64; 2], StorageVecError>; - #[storage(read, write)] - fn vec_u64_array_swap_remove(index: u64) -> Result<[u64; 2], StorageVecError>; - #[storage(read, write)] - fn vec_u64_array_insert(index: u64, value: [u64; 2]) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_u64_array_len() -> u64; - #[storage(read)] - fn vec_u64_array_is_empty() -> bool; - #[storage(write)] - fn vec_u64_array_clear(); - - #[storage(write)] - fn vec_enum_push(value: TestEnum); - #[storage(read)] - fn vec_enum_get(index: u64); - #[storage(write)] - fn vec_enum_pop(); - #[storage(read, write)] - fn vec_enum_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_enum_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_enum_insert(index: u64, value: TestEnum) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_enum_len() -> u64; - #[storage(read)] - fn vec_enum_is_empty() -> bool; - #[storage(write)] - fn vec_enum_clear(); - - #[storage(write)] - fn vec_struct_push(value: TestStruct); - #[storage(read)] - fn vec_struct_get(index: u64); - #[storage(write)] - fn vec_struct_pop(); - #[storage(read, write)] - fn vec_struct_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_struct_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_struct_insert(index: u64, value: TestStruct) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_struct_len() -> u64; - #[storage(read)] - fn vec_struct_is_empty() -> bool; - #[storage(write)] - fn vec_struct_clear(); + } storage { @@ -278,393 +90,5 @@ impl MyContract for Contract { - #[storage(write)] - fn vec_u16_push(value: u16) { - storage.vec_u16.push(value); - } - #[storage(read)] - fn vec_u16_get(index: u64) { - storage.vec_u16.get(index); - } - #[storage(write)] - fn vec_u16_pop() { - storage.vec_u16.pop(); - } - #[storage(read, write)] - fn vec_u16_remove(index: u64) -> Result { - storage.vec_u16.remove(index) - } - #[storage(read, write)] - fn vec_u16_swap_remove(index: u64) -> Result { - storage.vec_u16.swap_remove(index) - } - #[storage(read, write)] - fn vec_u16_insert(index: u64, value: u16) -> Result<(), StorageVecError> { - storage.vec_u16.insert(index, value) - } - #[storage(read)] - fn vec_u16_len() -> u64 { - storage.vec_u16.len() - } - #[storage(read)] - fn vec_u16_is_empty() -> bool { - storage.vec_u16.is_empty() - } - #[storage(write)] - fn vec_u16_clear() { - storage.vec_u16.clear(); - } - - - - #[storage(write)] - fn vec_u32_push(value: u32) { - storage.vec_u32.push(value); - } - #[storage(read)] - fn vec_u32_get(index: u64) { - storage.vec_u32.get(index); - } - #[storage(write)] - fn vec_u32_pop() { - storage.vec_u32.pop(); - } - #[storage(read, write)] - fn vec_u32_remove(index: u64) -> Result { - storage.vec_u32.remove(index) - } - #[storage(read, write)] - fn vec_u32_swap_remove(index: u64) -> Result { - storage.vec_u32.swap_remove(index) - } - #[storage(read, write)] - fn vec_u32_insert(index: u64, value: u32) -> Result<(), StorageVecError> { - storage.vec_u32.insert(index, value) - } - #[storage(read)] - fn vec_u32_len() -> u64 { - storage.vec_u32.len() - } - #[storage(read)] - fn vec_u32_is_empty() -> bool { - storage.vec_u32.is_empty() - } - #[storage(write)] - fn vec_u32_clear() { - storage.vec_u32.clear(); - } - - - - - #[storage(write)] - fn vec_u64_push(value: u64) { - storage.vec_u64.push(value); - } - #[storage(read)] - fn vec_u64_get(index: u64) { - storage.vec_u64.get(index); - } - #[storage(write)] - fn vec_u64_pop() { - storage.vec_u64.pop(); - } - #[storage(read, write)] - fn vec_u64_remove(index: u64) -> Result { - storage.vec_u64.remove(index) - } - #[storage(read, write)] - fn vec_u64_swap_remove(index: u64) -> Result { - storage.vec_u64.swap_remove(index) - } - #[storage(read, write)] - fn vec_u64_insert(index: u64, value: u64) -> Result<(), StorageVecError> { - storage.vec_u64.insert(index, value) - } - #[storage(read)] - fn vec_u64_len() -> u64 { - storage.vec_u64.len() - } - #[storage(read)] - fn vec_u64_is_empty() -> bool { - storage.vec_u64.is_empty() - } - #[storage(write)] - fn vec_u64_clear() { - storage.vec_u64.clear(); - } - - - - #[storage(write)] - fn vec_bool_push(value: bool) { - storage.vec_bool.push(value); - } - #[storage(read)] - fn vec_bool_get(index: u64) { - storage.vec_bool.get(index); - } - #[storage(write)] - fn vec_bool_pop() { - storage.vec_bool.pop(); - } - #[storage(read, write)] - fn vec_bool_remove(index: u64) -> Result { - storage.vec_bool.remove(index) - } - #[storage(read, write)] - fn vec_bool_swap_remove(index: u64) -> Result { - storage.vec_bool.swap_remove(index) - } - #[storage(read, write)] - fn vec_bool_insert(index: u64, value: bool) -> Result<(), StorageVecError> { - storage.vec_bool.insert(index, value) - } - #[storage(read)] - fn vec_bool_len() -> u64 { - storage.vec_bool.len() - } - #[storage(read)] - fn vec_bool_is_empty() -> bool { - storage.vec_bool.is_empty() - } - #[storage(write)] - fn vec_bool_clear() { - storage.vec_bool.clear(); - } - - - - - #[storage(write)] - fn vec_str4_push(value: str[4]) { - storage.vec_str4.push(value); - } - #[storage(read)] - fn vec_str4_get(index: u64) { - storage.vec_str4.get(index); - } - #[storage(write)] - fn vec_str4_pop() { - storage.vec_str4.pop(); - } - #[storage(read, write)] - fn vec_str4_remove(index: u64) -> Result { - storage.vec_str4.remove(index) - } - #[storage(read, write)] - fn vec_str4_swap_remove(index: u64) -> Result { - storage.vec_str4.swap_remove(index) - } - #[storage(read, write)] - fn vec_str4_insert(index: u64, value: str[4]) -> Result<(), StorageVecError> { - storage.vec_str4.insert(index, value) - } - #[storage(read)] - fn vec_str4_len() -> u64 { - storage.vec_str4.len() - } - #[storage(read)] - fn vec_str4_is_empty() -> bool { - storage.vec_str4.is_empty() - } - #[storage(write)] - fn vec_str4_clear() { - storage.vec_str4.clear(); - } - - - - #[storage(write)] - fn vec_b256_push(value: b256) { - storage.vec_b256.push(value); - } - #[storage(read)] - fn vec_b256_get(index: u64) { - storage.vec_b256.get(index); - } - #[storage(write)] - fn vec_b256_pop() { - storage.vec_b256.pop(); - } - #[storage(read, write)] - fn vec_b256_remove(index: u64) -> Result { - storage.vec_b256.remove(index) - } - #[storage(read, write)] - fn vec_b256_swap_remove(index: u64) -> Result { - storage.vec_b256.swap_remove(index) - } - #[storage(read, write)] - fn vec_b256_insert(index: u64, value: b256) -> Result<(), StorageVecError> { - storage.vec_b256.insert(index, value) - } - #[storage(read)] - fn vec_b256_len() -> u64 { - storage.vec_b256.len() - } - #[storage(read)] - fn vec_b256_is_empty() -> bool { - storage.vec_b256.is_empty() - } - #[storage(write)] - fn vec_b256_clear() { - storage.vec_b256.clear(); - } - - - - #[storage(write)] - fn vec_u64_tuple_push(value: (u64, u64)) { - storage.vec_u64_tuple.push(value); - } - #[storage(read)] - fn vec_u64_tuple_get(index: u64) { - storage.vec_u64_tuple.get(index); - } - #[storage(write)] - fn vec_u64_tuple_pop() { - storage.vec_u64_tuple.pop(); - } - #[storage(read, write)] - fn vec_u64_tuple_remove(index: u64) -> Result<(u64, u64), StorageVecError> { - storage.vec_u64_tuple.remove(index) - } - #[storage(read, write)] - fn vec_u64_tuple_swap_remove(index: u64) -> Result<(u64, u64), StorageVecError> { - storage.vec_u64_tuple.swap_remove(index) - } - #[storage(read, write)] - fn vec_u64_tuple_insert(index: u64, value: (u64, u64)) -> Result<(), StorageVecError> { - storage.vec_u64_tuple.insert(index, value) - } - #[storage(read)] - fn vec_u64_tuple_len() -> u64 { - storage.vec_u64_tuple.len() - } - #[storage(read)] - fn vec_u64_tuple_is_empty() -> bool { - storage.vec_u64_tuple.is_empty() - } - #[storage(write)] - fn vec_u64_tuple_clear() { - storage.vec_u64_tuple.clear(); - } - - - - #[storage(write)] - fn vec_u64_array_push(value: [u64; 2]) { - storage.vec_u64_array.push(value); - } - #[storage(read)] - fn vec_u64_array_get(index: u64) { - storage.vec_u64_array.get(index); - } - #[storage(write)] - fn vec_u64_array_pop() { - storage.vec_u64_array.pop(); - } - #[storage(read, write)] - fn vec_u64_array_remove(index: u64) -> Result<[u64; 2], StorageVecError> { - storage.vec_u64_array.remove(index) - } - #[storage(read, write)] - fn vec_u64_array_swap_remove(index: u64) -> Result<[u64; 2], StorageVecError> { - storage.vec_u64_array.swap_remove(index) - } - #[storage(read, write)] - fn vec_u64_array_insert(index: u64, value: [u64; 2]) -> Result<(), StorageVecError> { - storage.vec_u64_array.insert(index, value) - } - #[storage(read)] - fn vec_u64_array_len() -> u64 { - storage.vec_u64_array.len() - } - #[storage(read)] - fn vec_u64_array_is_empty() -> bool { - storage.vec_u64_array.is_empty() - } - #[storage(write)] - fn vec_u64_array_clear() { - storage.vec_u64_array.clear(); - } - - - - #[storage(write)] - fn vec_enum_push(value: TestEnum) { - storage.vec_enum.push(value); - } - #[storage(read)] - fn vec_enum_get(index: u64) { - storage.vec_enum.get(index); - } - #[storage(write)] - fn vec_enum_pop() { - storage.vec_enum.pop(); - } - #[storage(read, write)] - fn vec_enum_remove(index: u64) -> Result { - storage.vec_enum.remove(index) - } - #[storage(read, write)] - fn vec_enum_swap_remove(index: u64) -> Result { - storage.vec_enum.swap_remove(index) - } - #[storage(read, write)] - fn vec_enum_insert(index: u64, value: TestEnum) -> Result<(), StorageVecError> { - storage.vec_enum.insert(index, value) - } - #[storage(read)] - fn vec_enum_len() -> u64 { - storage.vec_enum.len() - } - #[storage(read)] - fn vec_enum_is_empty() -> bool { - storage.vec_enum.is_empty() - } - #[storage(write)] - fn vec_enum_clear() { - storage.vec_enum.clear(); - } - - - - #[storage(write)] - fn vec_struct_push(value: TestStruct) { - storage.vec_struct.push(value); - } - #[storage(read)] - fn vec_struct_get(index: u64) { - storage.vec_struct.get(index); - } - #[storage(write)] - fn vec_struct_pop() { - storage.vec_struct.pop(); - } - #[storage(read, write)] - fn vec_struct_remove(index: u64) -> Result { - storage.vec_struct.remove(index) - } - #[storage(read, write)] - fn vec_struct_swap_remove(index: u64) -> Result { - storage.vec_struct.swap_remove(index) - } - #[storage(read, write)] - fn vec_struct_insert(index: u64, value: TestStruct) -> Result<(),StorageVecError> { - storage.vec_struct.insert(index, value) - } - #[storage(read)] - fn vec_struct_len() -> u64 { - storage.vec_struct.len() - } - #[storage(read)] - fn vec_struct_is_empty() -> bool { - storage.vec_struct.is_empty() - } - #[storage(write)] - fn vec_struct_clear() { - storage.vec_struct.clear(); - } + } From f6315fa0af25d9194cc4686285b95cad6b0e6b55 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 22 Jun 2022 18:32:19 +0530 Subject: [PATCH 15/59] made storagevecerror public --- sway-lib-std/src/storage.sw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index 77587530830..778c28d41b3 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -110,7 +110,7 @@ impl StorageMap { } -enum StorageVecError { +pub enum StorageVecError { IndexOutOfBounds: (), CannotSwapAndRemoveTheSameElement: (), } From 9ddaf7d78c5bd7fa4371f84e2e023845e6950e06 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 22 Jun 2022 18:42:00 +0530 Subject: [PATCH 16/59] removed unncessary code to streamline bugfixing --- .../test_projects/storage_vec/src/main.sw | 47 +++++-------------- 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw index 1f00a55db7e..3d215a92a6c 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw +++ b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw @@ -1,25 +1,16 @@ contract; +use std::option::*; use std::result::*; use std::storage::{StorageVec, StorageVecError}; -enum TestEnum { - A: (), - B: (), -} - -struct TestStruct { - A: bool, - B: u64, -} - abi MyContract { - #[storage(write)] + #[storage(read, write)] fn vec_u8_push(value: u8); #[storage(read)] - fn vec_u8_get(index: u64); - #[storage(write)] - fn vec_u8_pop(); + fn vec_u8_get(index: u64) -> Option; + #[storage(read, write)] + fn vec_u8_pop() -> Option; #[storage(read, write)] fn vec_u8_remove(index: u64) -> Result; #[storage(read, write)] @@ -32,36 +23,24 @@ abi MyContract { fn vec_u8_is_empty() -> bool; #[storage(write)] fn vec_u8_clear(); - - } storage { vec_u8: StorageVec, - vec_u16: StorageVec, - vec_u32: StorageVec, - vec_u64: StorageVec, - vec_bool: StorageVec, - vec_str4: StorageVec, - vec_b256: StorageVec, - vec_u64_tuple: StorageVec<(u64, u64)>, - vec_u64_array: StorageVec<[u64; 2]>, - vec_enum: StorageVec, - vec_struct: StorageVec, } impl MyContract for Contract { - #[storage(write)] + #[storage(read, write)] fn vec_u8_push(value: u8) { storage.vec_u8.push(value); } #[storage(read)] - fn vec_u8_get(index: u64) { - storage.vec_u8.get(index); + fn vec_u8_get(index: u64) -> Option { + storage.vec_u8.get(index) } - #[storage(write)] - fn vec_u8_pop() { - storage.vec_u8.pop(); + #[storage(read, write)] + fn vec_u8_pop() -> Option { + storage.vec_u8.pop() } #[storage(read, write)] fn vec_u8_remove(index: u64) -> Result { @@ -87,8 +66,4 @@ impl MyContract for Contract { fn vec_u8_clear() { storage.vec_u8.clear(); } - - - - } From b22e00d41f0341c2b0558e4cd7b1e01e6e68f83f Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 22 Jun 2022 19:36:32 +0530 Subject: [PATCH 17/59] fixed annotations --- sway-lib-std/src/storage.sw | 23 +++-- .../test_projects/storage_vec/src/main.sw | 99 ++++++++++--------- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index 778c28d41b3..b5af3edc2db 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -127,7 +127,7 @@ impl StorageVec { // Storing the value at the current length index (if this is the first item, starts off at 0) let key = sha256((len, __get_storage_key())); - store(key, value); + store::(key, value); // Incrementing the length store(__get_storage_key(), len + 1); @@ -146,7 +146,7 @@ impl StorageVec { store(__get_storage_key(), len - 1); let key = sha256((len, __get_storage_key())); - Option::Some(get(key)) + Option::Some::(get::(key)) } /// Gets the value in the given index @@ -159,7 +159,7 @@ impl StorageVec { } let key = sha256((index, __get_storage_key())); - Option::Some(get(key)) + Option::Some::(get::(key)) } /// Removes the value in the given index and moves all the values in the following indexes @@ -174,7 +174,7 @@ impl StorageVec { } // gets the element before removing it, so it can be returned - let element_to_be_removed = get(sha256((index, __get_storage_key()))); + let removed_element = get::(sha256((index, __get_storage_key()))); // for every element in the vec with an index greater than the input index, // shifts the index for that element down one @@ -183,7 +183,7 @@ impl StorageVec { // gets the storage location for the previous index let key = sha256((count - 1, __get_storage_key())); // moves the element of the current index into the previous index - store(key, get(sha256((count, __get_storage_key())))); + store::(key, get::(sha256((count, __get_storage_key())))); count += 1; } @@ -192,7 +192,7 @@ impl StorageVec { store(__get_storage_key(), len - 1); // returns the removed element - Result::Ok(element_to_be_removed) + Result::Ok(removed_element) } /// Removes the element at the specified index and fills it with the last element @@ -211,10 +211,10 @@ impl StorageVec { } // gets the element before removing it, so it can be returned - let element_to_be_removed = get(sha256((index, __get_storage_key()))); + let element_to_be_removed = get::(sha256((index, __get_storage_key()))); - let last_element = get(sha256(len - 1, __get_storage_key())); - store(sha256(index, __get_storage_key()), last_element); + let last_element = get::(sha256(len - 1, __get_storage_key())); + store::(sha256(index, __get_storage_key()), last_element); // decrements len by 1 store(__get_storage_key(), len - 1); @@ -240,14 +240,14 @@ impl StorageVec { while count > index { let key = sha256((count + 1, __get_storage_key())); // shifts all the values up one index - store(key, get(sha256((count, __get_storage_key())))); + store::(key, get::(sha256((count, __get_storage_key())))); count -= 1 } // inserts the value into the now unused index let key = sha256((index, __get_storage_key())); - store(key, value); + store::(key, value); // increments len by 1 store(__get_storage_key(), len + 1); @@ -264,7 +264,6 @@ impl StorageVec { #[storage(read)] pub fn is_empty(self) -> bool { let len = get::(__get_storage_key()); - len == 0 } diff --git a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw index 3d215a92a6c..4c33aa82cf3 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw +++ b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw @@ -5,24 +5,24 @@ use std::result::*; use std::storage::{StorageVec, StorageVecError}; abi MyContract { - #[storage(read, write)] - fn vec_u8_push(value: u8); - #[storage(read)] - fn vec_u8_get(index: u64) -> Option; - #[storage(read, write)] - fn vec_u8_pop() -> Option; + // #[storage(read, write)] + // fn vec_u8_push(value: u8); + // #[storage(read)] + // fn vec_u8_get(index: u64) -> Option; + // #[storage(read, write)] + // fn vec_u8_pop() -> Option; #[storage(read, write)] fn vec_u8_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u8_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_u8_len() -> u64; - #[storage(read)] - fn vec_u8_is_empty() -> bool; - #[storage(write)] - fn vec_u8_clear(); + // #[storage(read, write)] + // fn vec_u8_swap_remove(index: u64) -> Result; + // #[storage(read, write)] + // fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError>; + // #[storage(read)] + // fn vec_u8_len() -> u64; + // #[storage(read)] + // fn vec_u8_is_empty() -> bool; + // #[storage(write)] + // fn vec_u8_clear(); } storage { @@ -30,40 +30,41 @@ storage { } impl MyContract for Contract { - #[storage(read, write)] - fn vec_u8_push(value: u8) { - storage.vec_u8.push(value); - } - #[storage(read)] - fn vec_u8_get(index: u64) -> Option { - storage.vec_u8.get(index) - } - #[storage(read, write)] - fn vec_u8_pop() -> Option { - storage.vec_u8.pop() - } + // #[storage(read, write)] + // fn vec_u8_push(value: u8) { + // storage.vec_u8.push(value); + // } + // #[storage(read)] + // fn vec_u8_get(index: u64) -> Option { + // storage.vec_u8.get(index) + // } + // #[storage(read, write)] + // fn vec_u8_pop() -> Option { + // storage.vec_u8.pop() + // } #[storage(read, write)] fn vec_u8_remove(index: u64) -> Result { - storage.vec_u8.remove(index) - } - #[storage(read, write)] - fn vec_u8_swap_remove(index: u64) -> Result { - storage.vec_u8.swap_remove(index) - } - #[storage(read, write)] - fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError> { - storage.vec_u8.insert(index, value) - } - #[storage(read)] - fn vec_u8_len() -> u64 { - storage.vec_u8.len() - } - #[storage(read)] - fn vec_u8_is_empty() -> bool { - storage.vec_u8.is_empty() - } - #[storage(write)] - fn vec_u8_clear() { - storage.vec_u8.clear(); + let res: Result = storage.vec_u8.remove(index); + res } + // #[storage(read, write)] + // fn vec_u8_swap_remove(index: u64) -> Result { + // storage.vec_u8.swap_remove(index) + // } + // #[storage(read, write)] + // fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError> { + // storage.vec_u8.insert(index, value) + // } + // #[storage(read)] + // fn vec_u8_len() -> u64 { + // storage.vec_u8.len() + // } + // #[storage(read)] + // fn vec_u8_is_empty() -> bool { + // storage.vec_u8.is_empty() + // } + // #[storage(write)] + // fn vec_u8_clear() { + // storage.vec_u8.clear(); + // } } From 049b162dfc4706891be34999c3510b8d3c300552 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 22 Jun 2022 23:09:57 +0530 Subject: [PATCH 18/59] made all the test contracts --- .../storage_vec/svec_array/.gitignore | 2 + .../storage_vec/svec_array/Cargo.toml | 16 ++++ .../storage_vec/svec_array/Forc.lock | 14 +++ .../storage_vec/svec_array/Forc.toml | 8 ++ .../storage_vec/svec_array/src/main.sw | 70 ++++++++++++++ .../storage_vec/svec_array/tests/harness.rs | 25 +++++ .../storage_vec/svec_b256/.gitignore | 2 + .../storage_vec/svec_b256/Cargo.toml | 16 ++++ .../storage_vec/svec_b256/Forc.toml | 8 ++ .../storage_vec/svec_b256/src/main.sw | 70 ++++++++++++++ .../storage_vec/svec_b256/tests/harness.rs | 25 +++++ .../storage_vec/svec_bool/.gitignore | 2 + .../storage_vec/svec_bool/Cargo.toml | 16 ++++ .../storage_vec/svec_bool/Forc.toml | 8 ++ .../storage_vec/svec_bool/src/main.sw | 69 +++++++++++++ .../storage_vec/svec_bool/tests/harness.rs | 25 +++++ .../storage_vec/svec_enum/.gitignore | 2 + .../storage_vec/svec_enum/Cargo.toml | 16 ++++ .../storage_vec/svec_enum/Forc.toml | 8 ++ .../storage_vec/svec_enum/src/main.sw | 75 +++++++++++++++ .../storage_vec/svec_enum/tests/harness.rs | 25 +++++ .../storage_vec/svec_str/.gitignore | 2 + .../storage_vec/svec_str/Cargo.toml | 16 ++++ .../storage_vec/svec_str/Forc.toml | 8 ++ .../storage_vec/svec_str/src/main.sw | 70 ++++++++++++++ .../storage_vec/svec_str/tests/harness.rs | 25 +++++ .../storage_vec/svec_struct/.gitignore | 2 + .../storage_vec/svec_struct/Cargo.toml | 16 ++++ .../storage_vec/svec_struct/Forc.toml | 8 ++ .../storage_vec/svec_struct/src/main.sw | 75 +++++++++++++++ .../storage_vec/svec_struct/tests/harness.rs | 25 +++++ .../storage_vec/svec_tuple/.gitignore | 2 + .../storage_vec/svec_tuple/Cargo.toml | 16 ++++ .../storage_vec/svec_tuple/Forc.lock | 14 +++ .../storage_vec/svec_tuple/Forc.toml | 8 ++ .../storage_vec/svec_tuple/src/main.sw | 69 +++++++++++++ .../storage_vec/svec_tuple/tests/harness.rs | 25 +++++ .../storage_vec/svec_u16/.gitignore | 2 + .../storage_vec/svec_u16/Cargo.toml | 16 ++++ .../storage_vec/svec_u16/Forc.toml | 8 ++ .../storage_vec/svec_u16/src/main.sw | 70 ++++++++++++++ .../storage_vec/svec_u16/tests/harness.rs | 25 +++++ .../storage_vec/svec_u32/.gitignore | 2 + .../storage_vec/svec_u32/Cargo.toml | 16 ++++ .../storage_vec/svec_u32/Forc.toml | 8 ++ .../storage_vec/svec_u32/src/main.sw | 70 ++++++++++++++ .../storage_vec/svec_u32/tests/harness.rs | 25 +++++ .../storage_vec/svec_u64/.gitignore | 2 + .../storage_vec/svec_u64/Cargo.toml | 16 ++++ .../storage_vec/svec_u64/Forc.toml | 8 ++ .../storage_vec/svec_u64/src/main.sw | 70 ++++++++++++++ .../storage_vec/svec_u64/tests/harness.rs | 25 +++++ .../storage_vec/svec_u8/.gitignore | 2 + .../storage_vec/svec_u8/Cargo.toml | 16 ++++ .../storage_vec/svec_u8/Forc.toml | 8 ++ .../storage_vec/svec_u8/src/main.sw | 70 ++++++++++++++ .../storage_vec/svec_u8/tests/harness.rs | 25 +++++ .../test_projects/storage_vec/src/main.sw | 96 +++++++++---------- .../test_projects/storage_vec/src/main_u16.sw | 21 ++++ 59 files changed, 1436 insertions(+), 48 deletions(-) create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_array/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Cargo.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_array/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_array/tests/harness.rs create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Cargo.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/tests/harness.rs create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Cargo.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/tests/harness.rs create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Cargo.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/tests/harness.rs create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Cargo.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/tests/harness.rs create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Cargo.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/tests/harness.rs create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Cargo.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/tests/harness.rs create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Cargo.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/tests/harness.rs create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Cargo.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/tests/harness.rs create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Cargo.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/tests/harness.rs create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/tests/harness.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/src/main_u16.sw diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Cargo.toml new file mode 100644 index 00000000000..a471f7fab0f --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "svec_array" +version = "0.1.0" +authors = ["Swaystar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.lock new file mode 100644 index 00000000000..baa6e736c98 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-F1A9B05C249770CB' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-F1A9B05C249770CB' +dependencies = ['core'] + +[[package]] +name = 'svec_array' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.toml new file mode 100644 index 00000000000..a5e3bc65639 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_array" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/src/main.sw new file mode 100644 index 00000000000..2039fac25c5 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/src/main.sw @@ -0,0 +1,70 @@ +contract; + +use std::option::*; +use std::result::*; +use std::storage::{StorageVec, StorageVecError}; + +abi MyContract { + #[storage(read, write)] + fn vec_array_push(value: [u64; 2]); + #[storage(read)] + fn vec_array_get(index: u64) -> Option<[u64; 2]>; + #[storage(read, write)] + fn vec_array_pop() -> Option<[u64; 2]>; + #[storage(read, write)] + fn vec_array_remove(index: u64) -> Result<[u64; 2], StorageVecError>; + #[storage(read, write)] + fn vec_array_swap_remove(index: u64) -> Result<[u64; 2], StorageVecError>; + #[storage(read, write)] + fn vec_array_insert(index: u64, value: [u64; 2]) -> Result<(), StorageVecError>; + #[storage(read)] + fn vec_array_len() -> u64; + #[storage(read)] + fn vec_array_is_empty() -> bool; + #[storage(write)] + fn vec_array_clear(); +} + +storage { + vec_array: StorageVec<[u64; 2]>, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn vec_array_push(value: [u64; 2]) { + storage.vec_array.push(value); + } + #[storage(read)] + fn vec_array_get(index: u64) -> Option<[u64; 2]> { + storage.vec_array.get(index) + } + #[storage(read, write)] + fn vec_array_pop() -> Option<[u64; 2]> { + storage.vec_array.pop() + } + #[storage(read, write)] + fn vec_array_remove(index: u64) -> Result<[u64; 2], StorageVecError> { + let res: Result<[u64; 2], StorageVecError> = storage.vec_array.remove(index); + res + } + #[storage(read, write)] + fn vec_array_swap_remove(index: u64) -> Result<[u64; 2], StorageVecError> { + storage.vec_array.swap_remove(index) + } + #[storage(read, write)] + fn vec_array_insert(index: u64, value: [u64; 2]) -> Result<(), StorageVecError> { + storage.vec_array.insert(index, value) + } + #[storage(read)] + fn vec_array_len() -> u64 { + storage.vec_array.len() + } + #[storage(read)] + fn vec_array_is_empty() -> bool { + storage.vec_array.is_empty() + } + #[storage(write)] + fn vec_array_clear() { + storage.vec_array.clear(); + } +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/tests/harness.rs new file mode 100644 index 00000000000..513330cadaa --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/tests/harness.rs @@ -0,0 +1,25 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(MyContract, "out/debug/svec_array-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/svec_array.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Cargo.toml new file mode 100644 index 00000000000..ce674a3ee50 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "svec_b256" +version = "0.1.0" +authors = ["Swaystar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.toml new file mode 100644 index 00000000000..862b2b60675 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_b256" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/src/main.sw new file mode 100644 index 00000000000..116d705687b --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/src/main.sw @@ -0,0 +1,70 @@ +contract; + +use std::option::*; +use std::result::*; +use std::storage::{StorageVec, StorageVecError}; + +abi MyContract { + #[storage(read, write)] + fn vec_b256_push(value: b256); + #[storage(read)] + fn vec_b256_get(index: u64) -> Option; + #[storage(read, write)] + fn vec_b256_pop() -> Option; + #[storage(read, write)] + fn vec_b256_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_b256_swap_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_b256_insert(index: u64, value: b256) -> Result<(), StorageVecError>; + #[storage(read)] + fn vec_b256_len() -> u64; + #[storage(read)] + fn vec_b256_is_empty() -> bool; + #[storage(write)] + fn vec_b256_clear(); +} + +storage { + vec_b256: StorageVec, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn vec_b256_push(value: b256) { + storage.vec_b256.push(value); + } + #[storage(read)] + fn vec_b256_get(index: u64) -> Option { + storage.vec_b256.get(index) + } + #[storage(read, write)] + fn vec_b256_pop() -> Option { + storage.vec_b256.pop() + } + #[storage(read, write)] + fn vec_b256_remove(index: u64) -> Result { + let res: Result = storage.vec_b256.remove(index); + res + } + #[storage(read, write)] + fn vec_b256_swap_remove(index: u64) -> Result { + storage.vec_b256.swap_remove(index) + } + #[storage(read, write)] + fn vec_b256_insert(index: u64, value: b256) -> Result<(), StorageVecError> { + storage.vec_b256.insert(index, value) + } + #[storage(read)] + fn vec_b256_len() -> u64 { + storage.vec_b256.len() + } + #[storage(read)] + fn vec_b256_is_empty() -> bool { + storage.vec_b256.is_empty() + } + #[storage(write)] + fn vec_b256_clear() { + storage.vec_b256.clear(); + } +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/tests/harness.rs new file mode 100644 index 00000000000..457930b90c4 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/tests/harness.rs @@ -0,0 +1,25 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(MyContract, "out/debug/svec_b256-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/svec_b256.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Cargo.toml new file mode 100644 index 00000000000..6a391e26136 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "svec_bool" +version = "0.1.0" +authors = ["Swaystar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.toml new file mode 100644 index 00000000000..0e8331413af --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_bool" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/src/main.sw new file mode 100644 index 00000000000..ff16641c130 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/src/main.sw @@ -0,0 +1,69 @@ +contract; + +use std::option::*; +use std::result::*;use std::storage::{StorageVec, StorageVecError}; + +abi MyContract { + #[storage(read, write)] + fn vec_bool_push(value: bool); + #[storage(read)] + fn vec_bool_get(index: u64) -> Option; + #[storage(read, write)] + fn vec_bool_pop() -> Option; + #[storage(read, write)] + fn vec_bool_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_bool_swap_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_bool_insert(index: u64, value: bool) -> Result<(), StorageVecError>; + #[storage(read)] + fn vec_bool_len() -> u64; + #[storage(read)] + fn vec_bool_is_empty() -> bool; + #[storage(write)] + fn vec_bool_clear(); +} + +storage { + vec_bool: StorageVec, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn vec_bool_push(value: bool) { + storage.vec_bool.push(value); + } + #[storage(read)] + fn vec_bool_get(index: u64) -> Option { + storage.vec_bool.get(index) + } + #[storage(read, write)] + fn vec_bool_pop() -> Option { + storage.vec_bool.pop() + } + #[storage(read, write)] + fn vec_bool_remove(index: u64) -> Result { + let res: Result = storage.vec_bool.remove(index); + res + } + #[storage(read, write)] + fn vec_bool_swap_remove(index: u64) -> Result { + storage.vec_bool.swap_remove(index) + } + #[storage(read, write)] + fn vec_bool_insert(index: u64, value: bool) -> Result<(), StorageVecError> { + storage.vec_bool.insert(index, value) + } + #[storage(read)] + fn vec_bool_len() -> u64 { + storage.vec_bool.len() + } + #[storage(read)] + fn vec_bool_is_empty() -> bool { + storage.vec_bool.is_empty() + } + #[storage(write)] + fn vec_bool_clear() { + storage.vec_bool.clear(); + } +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/tests/harness.rs new file mode 100644 index 00000000000..18a887b6f06 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/tests/harness.rs @@ -0,0 +1,25 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(MyContract, "out/debug/svec_bool-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/svec_bool.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Cargo.toml new file mode 100644 index 00000000000..0f00934c353 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "svec_enum" +version = "0.1.0" +authors = ["Swaystar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.toml new file mode 100644 index 00000000000..1c7b7856cc7 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_enum" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/src/main.sw new file mode 100644 index 00000000000..d096f322b0e --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/src/main.sw @@ -0,0 +1,75 @@ +contract; + +use std::option::*; +use std::result::*; +use std::storage::{StorageVec, StorageVecError}; + +enum TestEnum { + A: (), + B: (), +} + +abi MyContract { + #[storage(read, write)] + fn vec_enum_push(value: TestEnum); + #[storage(read)] + fn vec_enum_get(index: u64) -> Option; + #[storage(read, write)] + fn vec_enum_pop() -> Option; + #[storage(read, write)] + fn vec_enum_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_enum_swap_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_enum_insert(index: u64, value: TestEnum) -> Result<(), StorageVecError>; + #[storage(read)] + fn vec_enum_len() -> u64; + #[storage(read)] + fn vec_enum_is_empty() -> bool; + #[storage(write)] + fn vec_enum_clear(); +} + +storage { + vec_enum: StorageVec, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn vec_enum_push(value: TestEnum) { + storage.vec_enum.push(value); + } + #[storage(read)] + fn vec_enum_get(index: u64) -> Option { + storage.vec_enum.get(index) + } + #[storage(read, write)] + fn vec_enum_pop() -> Option { + storage.vec_enum.pop() + } + #[storage(read, write)] + fn vec_enum_remove(index: u64) -> Result { + let res: Result = storage.vec_enum.remove(index); + res + } + #[storage(read, write)] + fn vec_enum_swap_remove(index: u64) -> Result { + storage.vec_enum.swap_remove(index) + } + #[storage(read, write)] + fn vec_enum_insert(index: u64, value: TestEnum) -> Result<(), StorageVecError> { + storage.vec_enum.insert(index, value) + } + #[storage(read)] + fn vec_enum_len() -> u64 { + storage.vec_enum.len() + } + #[storage(read)] + fn vec_enum_is_empty() -> bool { + storage.vec_enum.is_empty() + } + #[storage(write)] + fn vec_enum_clear() { + storage.vec_enum.clear(); + } +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/tests/harness.rs new file mode 100644 index 00000000000..2512f82c41c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/tests/harness.rs @@ -0,0 +1,25 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(MyContract, "out/debug/svec_enum-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/svec_enum.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Cargo.toml new file mode 100644 index 00000000000..973a1eddcbd --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "svec_str" +version = "0.1.0" +authors = ["Swaystar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.toml new file mode 100644 index 00000000000..7ed62be1140 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_str" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/src/main.sw new file mode 100644 index 00000000000..e6a59d88e0c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/src/main.sw @@ -0,0 +1,70 @@ +contract; + +use std::option::*; +use std::result::*; +use std::storage::{StorageVec, StorageVecError}; + +abi MyContract { + #[storage(read, write)] + fn vec_str_push(value: str[4]); + #[storage(read)] + fn vec_str_get(index: u64) -> Option; + #[storage(read, write)] + fn vec_str_pop() -> Option; + #[storage(read, write)] + fn vec_str_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_str_swap_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_str_insert(index: u64, value: str[4]) -> Result<(), StorageVecError>; + #[storage(read)] + fn vec_str_len() -> u64; + #[storage(read)] + fn vec_str_is_empty() -> bool; + #[storage(write)] + fn vec_str_clear(); +} + +storage { + vec_str: StorageVec, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn vec_str_push(value: str[4]) { + storage.vec_str.push(value); + } + #[storage(read)] + fn vec_str_get(index: u64) -> Option { + storage.vec_str.get(index) + } + #[storage(read, write)] + fn vec_str_pop() -> Option { + storage.vec_str.pop() + } + #[storage(read, write)] + fn vec_str_remove(index: u64) -> Result { + let res: Result = storage.vec_str.remove(index); + res + } + #[storage(read, write)] + fn vec_str_swap_remove(index: u64) -> Result { + storage.vec_str.swap_remove(index) + } + #[storage(read, write)] + fn vec_str_insert(index: u64, value: str[4]) -> Result<(), StorageVecError> { + storage.vec_str.insert(index, value) + } + #[storage(read)] + fn vec_str_len() -> u64 { + storage.vec_str.len() + } + #[storage(read)] + fn vec_str_is_empty() -> bool { + storage.vec_str.is_empty() + } + #[storage(write)] + fn vec_str_clear() { + storage.vec_str.clear(); + } +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/tests/harness.rs new file mode 100644 index 00000000000..a0d48c38411 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/tests/harness.rs @@ -0,0 +1,25 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(MyContract, "out/debug/svec_str-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/svec_str.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Cargo.toml new file mode 100644 index 00000000000..cf1fb8175d3 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "svec_struct" +version = "0.1.0" +authors = ["Swaystar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.toml new file mode 100644 index 00000000000..aff4003212f --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_struct" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/src/main.sw new file mode 100644 index 00000000000..7e1a8acf2ff --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/src/main.sw @@ -0,0 +1,75 @@ +contract; + +use std::option::*; +use std::result::*; +use std::storage::{StorageVec, StorageVecError}; + +struct TestStruct { + A: bool, + B: u64, +} + +abi MyContract { + #[storage(read, write)] + fn vec_struct_push(value: TestStruct); + #[storage(read)] + fn vec_struct_get(index: u64) -> Option; + #[storage(read, write)] + fn vec_struct_pop() -> Option; + #[storage(read, write)] + fn vec_struct_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_struct_swap_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_struct_insert(index: u64, value: TestStruct) -> Result<(), StorageVecError>; + #[storage(read)] + fn vec_struct_len() -> u64; + #[storage(read)] + fn vec_struct_is_empty() -> bool; + #[storage(write)] + fn vec_struct_clear(); +} + +storage { + vec_struct: StorageVec, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn vec_struct_push(value: TestStruct) { + storage.vec_struct.push(value); + } + #[storage(read)] + fn vec_struct_get(index: u64) -> Option { + storage.vec_struct.get(index) + } + #[storage(read, write)] + fn vec_struct_pop() -> Option { + storage.vec_struct.pop() + } + #[storage(read, write)] + fn vec_struct_remove(index: u64) -> Result { + let res: Result = storage.vec_struct.remove(index); + res + } + #[storage(read, write)] + fn vec_struct_swap_remove(index: u64) -> Result { + storage.vec_struct.swap_remove(index) + } + #[storage(read, write)] + fn vec_struct_insert(index: u64, value: TestStruct) -> Result<(), StorageVecError> { + storage.vec_struct.insert(index, value) + } + #[storage(read)] + fn vec_struct_len() -> u64 { + storage.vec_struct.len() + } + #[storage(read)] + fn vec_struct_is_empty() -> bool { + storage.vec_struct.is_empty() + } + #[storage(write)] + fn vec_struct_clear() { + storage.vec_struct.clear(); + } +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/tests/harness.rs new file mode 100644 index 00000000000..21459b9d887 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/tests/harness.rs @@ -0,0 +1,25 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(MyContract, "out/debug/svec_struct-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/svec_struct.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Cargo.toml new file mode 100644 index 00000000000..7131428751b --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "svec_tuple" +version = "0.1.0" +authors = ["Swaystar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.lock new file mode 100644 index 00000000000..2f5681f767a --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-ADD23FE8604712AD' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-ADD23FE8604712AD' +dependencies = ['core'] + +[[package]] +name = 'svec_tuple' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.toml new file mode 100644 index 00000000000..6423633708f --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_tuple" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/src/main.sw new file mode 100644 index 00000000000..526678e2fa9 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/src/main.sw @@ -0,0 +1,69 @@ +contract; + +use std::option::*; +use std::result::*; +use std::storage::{StorageVec, StorageVecError}; + +abi MyContract { + #[storage(read, write)] + fn vec_tuple_push(value: (u64, u64)); + #[storage(read)] + fn vec_tuple_get(index: u64) -> Option<(u64, u64)>; + #[storage(read, write)] + fn vec_tuple_pop() -> Option<(u64, u64)>; + #[storage(read, write)] + fn vec_tuple_remove(index: u64) -> Result<(u64, u64), StorageVecError>; + #[storage(read, write)] + fn vec_tuple_swap_remove(index: u64) -> Result<(u64, u64), StorageVecError>; + #[storage(read, write)] + fn vec_tuple_insert(index: u64, value: (u64, u64)) -> Result<(), StorageVecError>; + #[storage(read)] + fn vec_tuple_len() -> u64; + #[storage(read)] + fn vec_tuple_is_empty() -> bool; + #[storage(write)] + fn vec_tuple_clear(); +} + +storage { + vec_tuple: StorageVec<(u64, u64)>, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn vec_tuple_push(value: (u64, u64)) { + storage.vec_tuple.push(value); + } + #[storage(read)] + fn vec_tuple_get(index: u64) -> Option<(u64, u64)> { + storage.vec_tuple.get(index) + } + #[storage(read, write)] + fn vec_tuple_pop() -> Option<(u64, u64)> { + storage.vec_tuple.pop() + } + #[storage(read, write)] + fn vec_tuple_remove(index: u64) -> Result<(u64, u64), StorageVecError> { + let res: Result<(u64, u64), StorageVecError> = storage.vec_tuple.remove(index); + res + } + #[storage(read, write)] + fn vec_tuple_swap_remove(index: u64) -> Result<(u64, u64), StorageVecError> { + storage.vec_tuple.swap_remove(index) + } + #[storage(read, write)] + fn vec_tuple_insert(index: u64, value: (u64, u64)) -> Result<(), StorageVecError> { + storage.vec_tuple.insert(index, value) + } + #[storage(read)] + fn vec_tuple_len() -> u64 { + storage.vec_tuple.len() + } + #[storage(read)] + fn vec_tuple_is_empty() -> bool { + storage.vec_tuple.is_empty() + } + #[storage(write)]fn vec_tuple_clear() { + storage.vec_tuple.clear(); + } +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/tests/harness.rs new file mode 100644 index 00000000000..5bd9c5c2b59 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/tests/harness.rs @@ -0,0 +1,25 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(MyContract, "out/debug/svec_tuple-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/svec_tuple.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Cargo.toml new file mode 100644 index 00000000000..f6f386eb174 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "svec_u16" +version = "0.1.0" +authors = ["Swaystar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.toml new file mode 100644 index 00000000000..e8bdd27b98f --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_u16" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/src/main.sw new file mode 100644 index 00000000000..4887b8d8074 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/src/main.sw @@ -0,0 +1,70 @@ +contract; + +use std::option::*; +use std::result::*; +use std::storage::{StorageVec, StorageVecError}; + +abi MyContract { + #[storage(read, write)] + fn vec_u16_push(value: u16); + #[storage(read)] + fn vec_u16_get(index: u64) -> Option; + #[storage(read, write)] + fn vec_u16_pop() -> Option; + #[storage(read, write)] + fn vec_u16_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_u16_swap_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_u16_insert(index: u64, value: u16) -> Result<(), StorageVecError>; + #[storage(read)] + fn vec_u16_len() -> u64; + #[storage(read)] + fn vec_u16_is_empty() -> bool; + #[storage(write)] + fn vec_u16_clear(); +} + +storage { + vec_u16: StorageVec, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn vec_u16_push(value: u16) { + storage.vec_u16.push(value); + } + #[storage(read)] + fn vec_u16_get(index: u64) -> Option { + storage.vec_u16.get(index) + } + #[storage(read, write)] + fn vec_u16_pop() -> Option { + storage.vec_u16.pop() + } + #[storage(read, write)] + fn vec_u16_remove(index: u64) -> Result { + let res: Result = storage.vec_u16.remove(index); + res + } + #[storage(read, write)] + fn vec_u16_swap_remove(index: u64) -> Result { + storage.vec_u16.swap_remove(index) + } + #[storage(read, write)] + fn vec_u16_insert(index: u64, value: u16) -> Result<(), StorageVecError> { + storage.vec_u16.insert(index, value) + } + #[storage(read)] + fn vec_u16_len() -> u64 { + storage.vec_u16.len() + } + #[storage(read)] + fn vec_u16_is_empty() -> bool { + storage.vec_u16.is_empty() + } + #[storage(write)] + fn vec_u16_clear() { + storage.vec_u16.clear(); + } +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/tests/harness.rs new file mode 100644 index 00000000000..bfbe5744601 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/tests/harness.rs @@ -0,0 +1,25 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(MyContract, "out/debug/svec_u16-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/svec_u16.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Cargo.toml new file mode 100644 index 00000000000..b6455a6222b --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "svec_u32" +version = "0.1.0" +authors = ["Swaystar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.toml new file mode 100644 index 00000000000..aab0b8e8a71 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_u32" + +[dependencies] +std = { path = "../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/src/main.sw new file mode 100644 index 00000000000..b0286090309 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/src/main.sw @@ -0,0 +1,70 @@ +contract; + +use std::option::*; +use std::result::*; +use std::storage::{StorageVec, StorageVecError}; + +abi MyContract { + #[storage(read, write)] + fn vec_u32_push(value: u32); + #[storage(read)] + fn vec_u32_get(index: u64) -> Option; + #[storage(read, write)] + fn vec_u32_pop() -> Option; + #[storage(read, write)] + fn vec_u32_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_u32_swap_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_u32_insert(index: u64, value: u32) -> Result<(), StorageVecError>; + #[storage(read)] + fn vec_u32_len() -> u64; + #[storage(read)] + fn vec_u32_is_empty() -> bool; + #[storage(write)] + fn vec_u32_clear(); +} + +storage { + vec_u32: StorageVec, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn vec_u32_push(value: u32) { + storage.vec_u32.push(value); + } + #[storage(read)] + fn vec_u32_get(index: u64) -> Option { + storage.vec_u32.get(index) + } + #[storage(read, write)] + fn vec_u32_pop() -> Option { + storage.vec_u32.pop() + } + #[storage(read, write)] + fn vec_u32_remove(index: u64) -> Result { + let res: Result = storage.vec_u32.remove(index); + res + } + #[storage(read, write)] + fn vec_u32_swap_remove(index: u64) -> Result { + storage.vec_u32.swap_remove(index) + } + #[storage(read, write)] + fn vec_u32_insert(index: u64, value: u32) -> Result<(), StorageVecError> { + storage.vec_u32.insert(index, value) + } + #[storage(read)] + fn vec_u32_len() -> u64 { + storage.vec_u32.len() + } + #[storage(read)] + fn vec_u32_is_empty() -> bool { + storage.vec_u32.is_empty() + } + #[storage(write)] + fn vec_u32_clear() { + storage.vec_u32.clear(); + } +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/tests/harness.rs new file mode 100644 index 00000000000..dfd8f65b436 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/tests/harness.rs @@ -0,0 +1,25 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(MyContract, "out/debug/svec_u32-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/svec_u32.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Cargo.toml new file mode 100644 index 00000000000..5a766397604 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "svec_u64" +version = "0.1.0" +authors = ["Swaystar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.toml new file mode 100644 index 00000000000..98f0a7acdec --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_u64" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/src/main.sw new file mode 100644 index 00000000000..f8599d19ab3 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/src/main.sw @@ -0,0 +1,70 @@ +contract; + +use std::option::*; +use std::result::*; +use std::storage::{StorageVec, StorageVecError}; + +abi MyContract { + #[storage(read, write)] + fn vec_u64_push(value: u64); + #[storage(read)] + fn vec_u64_get(index: u64) -> Option; + #[storage(read, write)] + fn vec_u64_pop() -> Option; + #[storage(read, write)] + fn vec_u64_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_u64_swap_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_u64_insert(index: u64, value: u64) -> Result<(), StorageVecError>; + #[storage(read)] + fn vec_u64_len() -> u64; + #[storage(read)] + fn vec_u64_is_empty() -> bool; + #[storage(write)] + fn vec_u64_clear(); +} + +storage { + vec_u64: StorageVec, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn vec_u64_push(value: u64) { + storage.vec_u64.push(value); + } + #[storage(read)] + fn vec_u64_get(index: u64) -> Option { + storage.vec_u64.get(index) + } + #[storage(read, write)] + fn vec_u64_pop() -> Option { + storage.vec_u64.pop() + } + #[storage(read, write)] + fn vec_u64_remove(index: u64) -> Result { + let res: Result = storage.vec_u64.remove(index); + res + } + #[storage(read, write)] + fn vec_u64_swap_remove(index: u64) -> Result { + storage.vec_u64.swap_remove(index) + } + #[storage(read, write)] + fn vec_u64_insert(index: u64, value: u64) -> Result<(), StorageVecError> { + storage.vec_u64.insert(index, value) + } + #[storage(read)] + fn vec_u64_len() -> u64 { + storage.vec_u64.len() + } + #[storage(read)] + fn vec_u64_is_empty() -> bool { + storage.vec_u64.is_empty() + } + #[storage(write)] + fn vec_u64_clear() { + storage.vec_u64.clear(); + } +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/tests/harness.rs new file mode 100644 index 00000000000..a7ca02b48f0 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/tests/harness.rs @@ -0,0 +1,25 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(MyContract, "out/debug/svec_u64-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/svec_u64.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml new file mode 100644 index 00000000000..ca4036b0d86 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "svec_u8" +version = "0.1.0" +authors = ["Swaystar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Forc.toml new file mode 100644 index 00000000000..8d753bb89ef --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_u8" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw new file mode 100644 index 00000000000..cf73ddcea0a --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw @@ -0,0 +1,70 @@ +contract; + +use std::option::*; +use std::result::*; +use std::storage::{StorageVec, StorageVecError}; + +abi MyContract { + #[storage(read, write)] + fn vec_u8_push(value: u8); + #[storage(read)] + fn vec_u8_get(index: u64) -> Option; + #[storage(read, write)] + fn vec_u8_pop() -> Option; + #[storage(read, write)] + fn vec_u8_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_u8_swap_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError>; + #[storage(read)] + fn vec_u8_len() -> u64; + #[storage(read)] + fn vec_u8_is_empty() -> bool; + #[storage(write)] + fn vec_u8_clear(); +} + +storage { + vec_u8: StorageVec, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn vec_u8_push(value: u8) { + storage.vec_u8.push(value); + } + #[storage(read)] + fn vec_u8_get(index: u64) -> Option { + storage.vec_u8.get(index) + } + #[storage(read, write)] + fn vec_u8_pop() -> Option { + storage.vec_u8.pop() + } + #[storage(read, write)] + fn vec_u8_remove(index: u64) -> Result { + let res: Result = storage.vec_u8.remove(index); + res + } + #[storage(read, write)] + fn vec_u8_swap_remove(index: u64) -> Result { + storage.vec_u8.swap_remove(index) + } + #[storage(read, write)] + fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError> { + storage.vec_u8.insert(index, value) + } + #[storage(read)] + fn vec_u8_len() -> u64 { + storage.vec_u8.len() + } + #[storage(read)] + fn vec_u8_is_empty() -> bool { + storage.vec_u8.is_empty() + } + #[storage(write)] + fn vec_u8_clear() { + storage.vec_u8.clear(); + } +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/tests/harness.rs new file mode 100644 index 00000000000..46a7bfc613b --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/tests/harness.rs @@ -0,0 +1,25 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(MyContract, "out/debug/svec_u8-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/svec_u8.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw index 4c33aa82cf3..cf73ddcea0a 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw +++ b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw @@ -5,24 +5,24 @@ use std::result::*; use std::storage::{StorageVec, StorageVecError}; abi MyContract { - // #[storage(read, write)] - // fn vec_u8_push(value: u8); - // #[storage(read)] - // fn vec_u8_get(index: u64) -> Option; - // #[storage(read, write)] - // fn vec_u8_pop() -> Option; + #[storage(read, write)] + fn vec_u8_push(value: u8); + #[storage(read)] + fn vec_u8_get(index: u64) -> Option; + #[storage(read, write)] + fn vec_u8_pop() -> Option; #[storage(read, write)] fn vec_u8_remove(index: u64) -> Result; - // #[storage(read, write)] - // fn vec_u8_swap_remove(index: u64) -> Result; - // #[storage(read, write)] - // fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError>; - // #[storage(read)] - // fn vec_u8_len() -> u64; - // #[storage(read)] - // fn vec_u8_is_empty() -> bool; - // #[storage(write)] - // fn vec_u8_clear(); + #[storage(read, write)] + fn vec_u8_swap_remove(index: u64) -> Result; + #[storage(read, write)] + fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError>; + #[storage(read)] + fn vec_u8_len() -> u64; + #[storage(read)] + fn vec_u8_is_empty() -> bool; + #[storage(write)] + fn vec_u8_clear(); } storage { @@ -30,41 +30,41 @@ storage { } impl MyContract for Contract { - // #[storage(read, write)] - // fn vec_u8_push(value: u8) { - // storage.vec_u8.push(value); - // } - // #[storage(read)] - // fn vec_u8_get(index: u64) -> Option { - // storage.vec_u8.get(index) - // } - // #[storage(read, write)] - // fn vec_u8_pop() -> Option { - // storage.vec_u8.pop() - // } + #[storage(read, write)] + fn vec_u8_push(value: u8) { + storage.vec_u8.push(value); + } + #[storage(read)] + fn vec_u8_get(index: u64) -> Option { + storage.vec_u8.get(index) + } + #[storage(read, write)] + fn vec_u8_pop() -> Option { + storage.vec_u8.pop() + } #[storage(read, write)] fn vec_u8_remove(index: u64) -> Result { let res: Result = storage.vec_u8.remove(index); res } - // #[storage(read, write)] - // fn vec_u8_swap_remove(index: u64) -> Result { - // storage.vec_u8.swap_remove(index) - // } - // #[storage(read, write)] - // fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError> { - // storage.vec_u8.insert(index, value) - // } - // #[storage(read)] - // fn vec_u8_len() -> u64 { - // storage.vec_u8.len() - // } - // #[storage(read)] - // fn vec_u8_is_empty() -> bool { - // storage.vec_u8.is_empty() - // } - // #[storage(write)] - // fn vec_u8_clear() { - // storage.vec_u8.clear(); - // } + #[storage(read, write)] + fn vec_u8_swap_remove(index: u64) -> Result { + storage.vec_u8.swap_remove(index) + } + #[storage(read, write)] + fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError> { + storage.vec_u8.insert(index, value) + } + #[storage(read)] + fn vec_u8_len() -> u64 { + storage.vec_u8.len() + } + #[storage(read)] + fn vec_u8_is_empty() -> bool { + storage.vec_u8.is_empty() + } + #[storage(write)] + fn vec_u8_clear() { + storage.vec_u8.clear(); + } } diff --git a/test/src/sdk-harness/test_projects/storage_vec/src/main_u16.sw b/test/src/sdk-harness/test_projects/storage_vec/src/main_u16.sw new file mode 100644 index 00000000000..27972112471 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/src/main_u16.sw @@ -0,0 +1,21 @@ +contract; + +use std::option::*; +use std::result::*; +use std::storage::{StorageVec, StorageVecError}; + +abi MyContract { + #[storage(read, write)] + fn vec_u16_push(value: u16); +} + +storage { + vec_u16: StorageVec, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn vec_u16_push(value: u16) { + storage.vec_u16.push(value); + } +} From cbfbedc3e022d1accefb66edf56ae0cd9804142e Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 23 Jun 2022 18:50:22 +0530 Subject: [PATCH 19/59] changed build.sh to include all the storage_vec projs --- test/src/sdk-harness/build.sh | 2 +- .../storage_vec/svec_b256}/Forc.lock | 6 +- .../storage_vec/svec_bool/Forc.lock | 14 ++++ .../storage_vec/svec_enum/Forc.lock | 14 ++++ .../storage_vec/svec_str/Forc.lock | 14 ++++ .../storage_vec/svec_struct/Forc.lock | 14 ++++ .../storage_vec/svec_u16/Forc.lock | 14 ++++ .../storage_vec/svec_u8/Forc.lock | 14 ++++ .../test_projects/storage_vec/.gitignore | 2 - .../test_projects/storage_vec/Cargo.toml | 16 ----- .../test_projects/storage_vec/Forc.toml | 8 --- .../test_projects/storage_vec/mod.rs | 1 + .../test_projects/storage_vec/src/main.sw | 70 ------------------- .../test_projects/storage_vec/src/main_u16.sw | 21 ------ .../{tests/harness.rs => utils/mod.rs} | 6 +- 15 files changed, 92 insertions(+), 124 deletions(-) rename test/src/sdk-harness/{test_projects/storage_vec => test_artifacts/storage_vec/svec_b256}/Forc.lock (57%) create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Forc.lock delete mode 100644 test/src/sdk-harness/test_projects/storage_vec/.gitignore delete mode 100644 test/src/sdk-harness/test_projects/storage_vec/Cargo.toml delete mode 100644 test/src/sdk-harness/test_projects/storage_vec/Forc.toml create mode 100644 test/src/sdk-harness/test_projects/storage_vec/mod.rs delete mode 100644 test/src/sdk-harness/test_projects/storage_vec/src/main.sw delete mode 100644 test/src/sdk-harness/test_projects/storage_vec/src/main_u16.sw rename test/src/sdk-harness/test_projects/storage_vec/{tests/harness.rs => utils/mod.rs} (72%) diff --git a/test/src/sdk-harness/build.sh b/test/src/sdk-harness/build.sh index 35459acd2c3..e9c7bb40de8 100755 --- a/test/src/sdk-harness/build.sh +++ b/test/src/sdk-harness/build.sh @@ -27,7 +27,7 @@ while true; do fi done -test_dirs="${base_dir}/test_artifacts/* ${base_dir}/test_projects/*" +test_dirs="${base_dir}/test_artifacts/* ${base_dir}/test_projects/* ${base_dir}/test_artifacts/storage_vec/*" for test_dir in $test_dirs; do if [[ -f "${test_dir}/Forc.toml" ]]; then diff --git a/test/src/sdk-harness/test_projects/storage_vec/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.lock similarity index 57% rename from test/src/sdk-harness/test_projects/storage_vec/Forc.lock rename to test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.lock index 3e36af898b8..37516c69109 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/Forc.lock +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.lock @@ -1,14 +1,14 @@ [[package]] name = 'core' -source = 'path+from-root-23C4ABBB223F2848' +source = 'path+from-root-BAD4826C86E6CE3D' dependencies = [] [[package]] name = 'std' -source = 'path+from-root-23C4ABBB223F2848' +source = 'path+from-root-BAD4826C86E6CE3D' dependencies = ['core'] [[package]] -name = 'storage_vec' +name = 'svec_b256' source = 'root' dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.lock new file mode 100644 index 00000000000..d16c4ca4065 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-112F6FFCFCECE066' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-112F6FFCFCECE066' +dependencies = ['core'] + +[[package]] +name = 'svec_bool' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.lock new file mode 100644 index 00000000000..06f1f17cd10 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-BA7DA646BFFC59D3' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-BA7DA646BFFC59D3' +dependencies = ['core'] + +[[package]] +name = 'svec_enum' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.lock new file mode 100644 index 00000000000..117a72a36a9 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-5A8E0F2C8C65E65F' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-5A8E0F2C8C65E65F' +dependencies = ['core'] + +[[package]] +name = 'svec_str' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.lock new file mode 100644 index 00000000000..e185915ccb2 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-5D548BD88B479EAC' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-5D548BD88B479EAC' +dependencies = ['core'] + +[[package]] +name = 'svec_struct' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.lock new file mode 100644 index 00000000000..3b133df026f --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-D2C27CF3A144E426' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-D2C27CF3A144E426' +dependencies = ['core'] + +[[package]] +name = 'svec_u16' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Forc.lock new file mode 100644 index 00000000000..b382eba9f5c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-0A9A4F1E1D370290' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-0A9A4F1E1D370290' +dependencies = ['core'] + +[[package]] +name = 'svec_u8' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_projects/storage_vec/.gitignore b/test/src/sdk-harness/test_projects/storage_vec/.gitignore deleted file mode 100644 index 77d3844f58c..00000000000 --- a/test/src/sdk-harness/test_projects/storage_vec/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -out -target diff --git a/test/src/sdk-harness/test_projects/storage_vec/Cargo.toml b/test/src/sdk-harness/test_projects/storage_vec/Cargo.toml deleted file mode 100644 index cc3a15a5e0c..00000000000 --- a/test/src/sdk-harness/test_projects/storage_vec/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "storage_vec" -version = "0.1.0" -authors = ["Swaystar"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_projects/storage_vec/Forc.toml b/test/src/sdk-harness/test_projects/storage_vec/Forc.toml deleted file mode 100644 index 404e2bb6050..00000000000 --- a/test/src/sdk-harness/test_projects/storage_vec/Forc.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -authors = ["Fuel Labs "] -entry = "main.sw" -license = "Apache-2.0" -name = "storage_vec" - -[dependencies] -std = { path = "../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs new file mode 100644 index 00000000000..40679bc7082 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -0,0 +1 @@ +mod utils; \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw b/test/src/sdk-harness/test_projects/storage_vec/src/main.sw deleted file mode 100644 index cf73ddcea0a..00000000000 --- a/test/src/sdk-harness/test_projects/storage_vec/src/main.sw +++ /dev/null @@ -1,70 +0,0 @@ -contract; - -use std::option::*; -use std::result::*; -use std::storage::{StorageVec, StorageVecError}; - -abi MyContract { - #[storage(read, write)] - fn vec_u8_push(value: u8); - #[storage(read)] - fn vec_u8_get(index: u64) -> Option; - #[storage(read, write)] - fn vec_u8_pop() -> Option; - #[storage(read, write)] - fn vec_u8_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u8_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_u8_len() -> u64; - #[storage(read)] - fn vec_u8_is_empty() -> bool; - #[storage(write)] - fn vec_u8_clear(); -} - -storage { - vec_u8: StorageVec, -} - -impl MyContract for Contract { - #[storage(read, write)] - fn vec_u8_push(value: u8) { - storage.vec_u8.push(value); - } - #[storage(read)] - fn vec_u8_get(index: u64) -> Option { - storage.vec_u8.get(index) - } - #[storage(read, write)] - fn vec_u8_pop() -> Option { - storage.vec_u8.pop() - } - #[storage(read, write)] - fn vec_u8_remove(index: u64) -> Result { - let res: Result = storage.vec_u8.remove(index); - res - } - #[storage(read, write)] - fn vec_u8_swap_remove(index: u64) -> Result { - storage.vec_u8.swap_remove(index) - } - #[storage(read, write)] - fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError> { - storage.vec_u8.insert(index, value) - } - #[storage(read)] - fn vec_u8_len() -> u64 { - storage.vec_u8.len() - } - #[storage(read)] - fn vec_u8_is_empty() -> bool { - storage.vec_u8.is_empty() - } - #[storage(write)] - fn vec_u8_clear() { - storage.vec_u8.clear(); - } -} diff --git a/test/src/sdk-harness/test_projects/storage_vec/src/main_u16.sw b/test/src/sdk-harness/test_projects/storage_vec/src/main_u16.sw deleted file mode 100644 index 27972112471..00000000000 --- a/test/src/sdk-harness/test_projects/storage_vec/src/main_u16.sw +++ /dev/null @@ -1,21 +0,0 @@ -contract; - -use std::option::*; -use std::result::*; -use std::storage::{StorageVec, StorageVecError}; - -abi MyContract { - #[storage(read, write)] - fn vec_u16_push(value: u16); -} - -storage { - vec_u16: StorageVec, -} - -impl MyContract for Contract { - #[storage(read, write)] - fn vec_u16_push(value: u16) { - storage.vec_u16.push(value); - } -} diff --git a/test/src/sdk-harness/test_projects/storage_vec/tests/harness.rs b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs similarity index 72% rename from test/src/sdk-harness/test_projects/storage_vec/tests/harness.rs rename to test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs index c8bc8583220..983fca31c18 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/tests/harness.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs @@ -2,13 +2,13 @@ use fuels::{prelude::*, tx::ContractId}; use fuels_abigen_macro::abigen; // Load abi from json -abigen!(MyContract, "out/debug/storage_vec-abi.json"); +abigen!(MyContract, "test_artifacts/storage_vec/svec_u8/out/debug/svec_u8-abi.json"); async fn get_contract_instance() -> (MyContract, ContractId) { // Launch a local network and deploy the contract let wallet = launch_provider_and_get_single_wallet().await; - let id = Contract::deploy("./out/debug/storage_vec.bin", &wallet, TxParameters::default()) + let id = Contract::deploy("./out/debug/svec_u8.bin", &wallet, TxParameters::default()) .await .unwrap(); @@ -18,7 +18,7 @@ async fn get_contract_instance() -> (MyContract, ContractId) { } #[tokio::test] -async fn can_get_contract_id() { +async fn can_get_contract_id() { let (_instance, _id) = get_contract_instance().await; // Now you have an instance of your contract you can use to test each function From 75c414b0a8f7729d4ba5779e845e37b0037c5041 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 23 Jun 2022 19:46:42 +0530 Subject: [PATCH 20/59] updated fuels version --- test/src/sdk-harness/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/src/sdk-harness/Cargo.toml b/test/src/sdk-harness/Cargo.toml index 2d95faae92b..ad01a33cf30 100644 --- a/test/src/sdk-harness/Cargo.toml +++ b/test/src/sdk-harness/Cargo.toml @@ -11,8 +11,8 @@ fuel-core = { version = "0.8", default-features = false } fuel-gql-client = { version = "0.8", default-features = false } fuel-types = "0.5" fuel-vm = "0.11" -fuels = "0.15" -fuels-abigen-macro = "0.15" +fuels = "0.16" +fuels-abigen-macro = "0.16" hex = "0.4.3" sha2 = "0.10" sha3 = "0.10.1" From 0da645a31eb7c4b2f2c7ad76313b9e4da27167f1 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 30 Jun 2022 17:37:06 +0530 Subject: [PATCH 21/59] unwrapped all results and options in the contract --- .../storage_vec/svec_u8/src/main.sw | 33 ++++++++++--------- .../test_projects/storage_vec/mod.rs | 13 +++++++- .../test_projects/storage_vec/utils/mod.rs | 13 ++------ 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw index cf73ddcea0a..abc964e7d93 100644 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw @@ -8,15 +8,15 @@ abi MyContract { #[storage(read, write)] fn vec_u8_push(value: u8); #[storage(read)] - fn vec_u8_get(index: u64) -> Option; + fn vec_u8_get(index: u64) -> u8; #[storage(read, write)] - fn vec_u8_pop() -> Option; + fn vec_u8_pop() -> u8; #[storage(read, write)] - fn vec_u8_remove(index: u64) -> Result; + fn vec_u8_remove(index: u64) -> u8; #[storage(read, write)] - fn vec_u8_swap_remove(index: u64) -> Result; + fn vec_u8_swap_remove(index: u64) -> u8; #[storage(read, write)] - fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError>; + fn vec_u8_insert(index: u64, value: u8); #[storage(read)] fn vec_u8_len() -> u64; #[storage(read)] @@ -35,25 +35,28 @@ impl MyContract for Contract { storage.vec_u8.push(value); } #[storage(read)] - fn vec_u8_get(index: u64) -> Option { - storage.vec_u8.get(index) + fn vec_u8_get(index: u64) -> u8 { + let item: Option = storage.vec_u8.get(index); + item.unwrap() } #[storage(read, write)] - fn vec_u8_pop() -> Option { - storage.vec_u8.pop() + fn vec_u8_pop() -> u8 { + let res: Option = storage.vec_u8.pop(); + res.unwrap() } #[storage(read, write)] - fn vec_u8_remove(index: u64) -> Result { + fn vec_u8_remove(index: u64) -> u8 { let res: Result = storage.vec_u8.remove(index); - res + res.unwrap() } #[storage(read, write)] - fn vec_u8_swap_remove(index: u64) -> Result { - storage.vec_u8.swap_remove(index) + fn vec_u8_swap_remove(index: u64) -> u8 { + let res: Result = storage.vec_u8.swap_remove(index); + res.unwrap() } #[storage(read, write)] - fn vec_u8_insert(index: u64, value: u8) -> Result<(), StorageVecError> { - storage.vec_u8.insert(index, value) + fn vec_u8_insert(index: u64, value: u8) { + let _ = storage.vec_u8.insert(index, value); } #[storage(read)] fn vec_u8_len() -> u64 { diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index 40679bc7082..fa4b0b96c52 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -1 +1,12 @@ -mod utils; \ No newline at end of file +mod utils; + +use fuels::{prelude::*, tx::ContractId}; + +use utils::get_contract_instance; + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs index 983fca31c18..fadcccc0b1d 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs @@ -4,22 +4,15 @@ use fuels_abigen_macro::abigen; // Load abi from json abigen!(MyContract, "test_artifacts/storage_vec/svec_u8/out/debug/svec_u8-abi.json"); -async fn get_contract_instance() -> (MyContract, ContractId) { +pub async fn get_contract_instance() -> (MyContract, ContractId) { // Launch a local network and deploy the contract let wallet = launch_provider_and_get_single_wallet().await; - let id = Contract::deploy("./out/debug/svec_u8.bin", &wallet, TxParameters::default()) + let id = Contract::deploy("test_artifacts/storage_vec/svec_u8/out/debug/svec_u8.bin", &wallet, TxParameters::default()) .await .unwrap(); let instance = MyContract::new(id.to_string(), wallet); (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} +} \ No newline at end of file From da514b71c7810caba7c7054cdef13ad2055550b9 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 30 Jun 2022 17:45:23 +0530 Subject: [PATCH 22/59] reduced fuels version --- test/src/sdk-harness/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/src/sdk-harness/Cargo.toml b/test/src/sdk-harness/Cargo.toml index ad01a33cf30..2d95faae92b 100644 --- a/test/src/sdk-harness/Cargo.toml +++ b/test/src/sdk-harness/Cargo.toml @@ -11,8 +11,8 @@ fuel-core = { version = "0.8", default-features = false } fuel-gql-client = { version = "0.8", default-features = false } fuel-types = "0.5" fuel-vm = "0.11" -fuels = "0.16" -fuels-abigen-macro = "0.16" +fuels = "0.15" +fuels-abigen-macro = "0.15" hex = "0.4.3" sha2 = "0.10" sha3 = "0.10.1" From 5f50e409fc8f9cbcdf1c3715000cbf7e2d1083a6 Mon Sep 17 00:00:00 2001 From: SwayStar123 <46050679+SwayStar123@users.noreply.github.com> Date: Thu, 30 Jun 2022 17:46:54 +0530 Subject: [PATCH 23/59] merge master to storage_vec branch (#2183) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove extra "the" (#2042) looks like an extra "the" got into this comment * Run `cargo update`. (#2045) * sway-fmt-v2 adds program type to the output (#1997) * Fix couple of bugs in handling returns in if blocks (#2029) * Config driven E2E testing. (#2003) Completely refactor E2E tests to be config driven. Rather than specifying which tests are to be run and how, we now can describe each test with a TOML file. * Handle enums and their impls for item imports (#2034) * Add `Identity` type to Sway Book (#2041) * Add Identity type to Sway Book * Move Identity code to examples directory * Add Forc.lock to gitignore * Update docs/src/basics/blockchain_types.md Co-authored-by: John Adler * Typo * Ran forc fmt * Update Cargo.toml * Update examples/identity/src/main.sw Co-authored-by: Mohammad Fawaz * Delete Cargo.toml * Update Identity docs to use anchor * Fix CI * Add path to std in Forc.toml and update Forc.lock std source * Run forc fmt again Co-authored-by: John Adler Co-authored-by: Mohammad Fawaz * Improve struct patterns with new warnings and rest pattern support. (#2032) * Improve struct patterns with new warnings and rest pattern support. This commit improves a couple aspects of handling of struct patterns. First of all, it adds semantic checking (with a new warning) when patterns are missing usage of all fields: ``` error --> src/main.sw:15:9 | 13 | 14 | let z = match p { 15 | Point { x } => { x }, | ^^^^^^^^^^^ Pattern does not mention field: y 16 | }; | ____ ``` Then it adds support for rest pattern, "..", which can be used as the last token in a pattern to not have to specify all the struct fields. The semantic AST model was updated to support modeling this pattern, and further type checking was added to the code. There is also a new warning for when the rest pattern doesn't appear as the last location, or when it appears multiple times: ``` error --> src/main.sw:17:20 | 15 | 16 | let z = match p { 17 | Point { x, .., .. } => { x }, | ^^ Unexpected rest token, must be at the end of pattern. 18 | }; | ____ ``` And lastly, tests were added to cover the changes and new functionality. Closes https://github.com/FuelLabs/sway/issues/1568. * Do not use an underscored identifier. * Add some more pattern matching tests. * Port to new config-driven tests. Co-authored-by: Mohammad Fawaz * Add the concept of semantic similarity to the type system (#1958) * Do not rely on TypeMapping when type checking declarations. * Prevent leaking types in impls. * Prevent unconstrained type parameters. * WIP * clippy * WIP * Use TypeId in TypeMapping and in TraitMap. * Add semantic type constraints. * Update test case. * fix * Some updates to the known issues section (#2060) Updates to the known issues section * Constants formatting for sway-fmt-v2 (#2021) * Update the check for unresolved types. (#2057) * Update the check for unresolved types. * clippy * Remove calls to log. * fmt * Remove unused file. * Make `resolve_type_with_self` and `resolve_type_without_self` take `TypeId`'s instead of `TypeInfo`'s (#1982) * Do not rely on TypeMapping when type checking declarations. * Prevent leaking types in impls. * Prevent unconstrained type parameters. * WIP * clippy * WIP * Use TypeId in TypeMapping and in TraitMap. * Add semantic type constraints. * Update test case. * fix * Use TypeId inside of resolve_type_with_self and resolve_type_without_self. * clippy * X * Bug is fixed. * Add forc.lock. * update * Move test to inside of the SDK. * Fix test cases. * Add lock files. * Fix test. * Bump non-transitive `dashmap` to v5.3.4. (#2062) Bump explicit `dashmap` to v5.3.4. * comby-rust (#2065) * comby-rust * Fix clippy warning Co-authored-by: Mohammad Fawaz * Adds `attribute` handling to `sway-fmt-v2` (#2061) * wip * add unit test * update tests * updated unimplemented cases to return span * test now passes incorrectly * update AttributeDecl::format() * update test comment * add close paren * update Annotated for consistency * chng return type for Annotated * remove test and add todos * Introduce a type check `Context`. Replaces `TypeCheckArguments`. (#2004) * Introduce a type check `Context`. Replaces `TypeCheckArguments`. * Add missing unknown type annotation. Clean up some formatting. Also adds some resetting of the help text and type annotation (to unknown) in many cases to better match the original behaviour. It's difficult to tell which locations these values were originally used as placeholders, and which locations they're a necessity for correctness. This at least appears to fix an issue with expression return type inference. * Rename semantic_analysis::Context to TypeCheckContext * Improve field doc comments for help_text, self_type * Add doc comment to mode field in TypeCheckContext * Construct TypeCheckContext at Program level, not module level. This should help to clarify how we can pass other type check context (like the declaration and type engines once they're added) through to the submodules. Previously, this was a little unclear as the `TypeCheckContext` was only constructed at the module level. * Add missing namespace field doc comment to TypeCheckContext * Fix TypeCheckContext constructor in IR test * Add `forc check` command (#2026) * wip * moving back to PC computer * adding check function to forc pkg * have ast returning from forc pkg * can now successfully parse all sway examples * fmt * added forc check * tidy up lsp tests * add forc check command * forc ops doesnt need to be public * tidy up lsp tests * remove non relevant code * rebase on master * add Cargo.lock file * add forc check to mdbook * Small fixes to the `storage_map` example (#2079) Small fix to storage_map example * Move `TypeArgument`, `TypeParameter`, and `TraitConstraints` to be conceptually inside of the type engine (#2074) Move the stuff. * Ensure lock is applied when `BuildPlan` validation would require changes (#2090) Ensure lock is applied if BuildPlan validation requires changes While reviewing #2085, I noticed that some recent additions to `BuildPlan` validation could result in some changes to the build plan (and in turn, rewriting the lock file) even in the case that `--locked` was specified. This moves the `--locked` check to the moment before writing the new lock file. This ensures all potential changes that would be required of the `BuildPlan` are caught. It also allows us to provide a "Cause" for *why* the lock file would need updating when `--locked` is passed to prevent it. Closes #2084 Closes #2085 * Add conceptual distinction between replacing `TypeInfo::Self` and monomorphization (#2017) * Do not rely on TypeMapping when type checking declarations. * Prevent leaking types in impls. * Prevent unconstrained type parameters. * WIP * clippy * WIP * Use TypeId in TypeMapping and in TraitMap. * Add semantic type constraints. * Update test case. * fix * Use TypeId inside of resolve_type_with_self and resolve_type_without_self. * clippy * X * Remove self_type from monomorphization. * Add conceptual distinction between replacing TypeInfo::Self and monomorphization. * Bug is fixed. * Add forc.lock. * update * Move test to inside of the SDK. * Fix test cases. * Add lock files. * Fix test. * Add `abi` handling to `sway-fmt-v2` (#2044) * Refactor `forc_pkg::BuildConfig` -> `BuildProfile`, fix CLI arg handling (#2094) Previously, if any of the `print` args were set, the rest of the selected build profile was ignored. This changes the behaviour so that the command line arguments only override their associated build profile fields. Also renames `BuildConfig` to `BuildProfile` and moves it from `forc_pkg::pkg` to `forc_pkg::manifest` along with the rest of the serializable manifest types. * Update all the E2E should_fail tests to verify their output. (#2082) Using the `FileCheck` crate it can now pattern match against the compiler output to be sure the errors and/or warnings are exactly what we expect. * forc: Improve the `print_*_asm` CLI option docs (#2095) Previously, these implied no bytecode was generated if the flag was not set, however this is not the case. * update fuelup related instructions (#2099) * update fuelup instructions * better instructions * better wording for modifying path * Adding `--time-phases` to `forc build` (#2091) * make items under [project] ordered alphabetically in forc.toml * issue #1893store/show bytecode hash * formatted * added cargo lock file * cargo toml dependencies in alphabetical order * hash bin of script or predicate only * format * generating bytecode hash only on scripts and predicates * removed option from Compiled::tree_type * ran clippy * added to forc_build documentation * made filename suffix containing bin hash a constant * get root of predicate bytecode * Apply suggestions from code review Co-authored-by: Mohammad Fawaz * if let to match on program type * Update forc/src/cli/commands/build.rs updating bin-root filename Co-authored-by: mitchmindtree * added benchmarks for compilation process * use macro instead of closure for wrapping parts of compilation process Co-authored-by: Waseem G Co-authored-by: Mohammad Fawaz Co-authored-by: mitchmindtree Co-authored-by: Toby Hutton * Add forc feature for overriding packages in the package graph, akin to cargo's [patch] feature (#1836) * Bump to v0.16.2 (#2105) * bump to v0.16.2 * Fix one test not pointing to local std * Add struct formatting to sway-fmt-v2 (#2058) * internal: Reduce amount of String::new() in sway-fmt-v2 (#2111) * examples: fix renaming to BASE_ASSET_ID in comment (#2120) * Added storage field alignment threshold to formatter config (#2113) * Enable storage initializers and emit a storage initialization JSON (#2078) * Enable storage initializers and dump out a JSON file * Move the new functions into a separate storage module * Use StorageSlot directly from fuel-tx * forc deploy now uses the storage slots * add some tests * lint, change initializers -> slots, and fixing some tests * enhance a comment * Revert unneeded changes to sway-types * add a failing test * Fix failing test * renaming some functions * Test the storage slots JSON in e2e tests and add forc json-storage-slots command * ignore *_output.json * forc documenter changes * Remove forc json-storage-slots and stop relying on forc json-abi * Enhance some comments * Remove unnecessary oracle * Improve reserved keywords checking and add support for raw identifiers. (#2066) Add support for raw identifiers and improve reserved keywords checking. This commit deals with the usage and checking of reserved keywords as identifiers, for code like: ``` fn main() { let mut mut = 0; } It introduces a new error that checks if an identifier is a reserved keyword: ``` error --> /main.sw:4:13 | 2 | 3 | fn main() { 4 | let mut mut = 0; | ^^^ Identifiers cannot be a reserved keyword. 5 | } | ____ ``` There was an existing issue in the standard library, which has a library/module named `storage`. Instead of working around this by renaming it to something else, an alternative solution with raw identifiers is implemented. This raw identifier feature is implemented at the lexer level, and allows you to use keywords as identifiers in places that generally wouldn't be allowed. Rust and a bunch of other modern languages also provide this escape hatch, and it seemed the simplest solution for me to handle the issue. It activates by declaring an identifier prefixed with `r#`, just like Rust. The complexity on the codebase to support this feature is pretty minimal, but if there any objections to this, I can easily remove it, but some other solution to the issue above will need to be figured out. Closes https://github.com/FuelLabs/sway/issues/1996. Co-authored-by: Mohammad Fawaz * remove `fuels-abigen-macro` dependency (#2007) * add remove fuels-abigen-macro dependency * add change dep. versions * add fuel 0.16 * add fuel-core-lib flag * add fuel-core-lib flag fix * add fuel-core-lib flag fix * add fuel-core-lib flag fix * add fuel-core-lib flag fix * add remove -- form forc test command * add replace constants * add expand CI command * add fix tests * add fix tests * Update test/src/sdk-harness/Cargo.toml Co-authored-by: John Adler * Update test/src/sdk-harness/Cargo.toml Co-authored-by: John Adler * Update test/src/sdk-harness/Cargo.toml Co-authored-by: John Adler * add return -- cmd * add remove fuels-abigen-macro from tests * add remove fuel-core-lib flag * add fuel-core-lib flag * add reverte CI file * add remove features * add remove [features] * add merge master Co-authored-by: Mohammad Fawaz Co-authored-by: John Adler * Adds `Generics` handling to `sway-fmt-v2` (#2110) * #2020 - changed BASE_ASSET_ID type to ContractId (#2137) * #2020 - changed BASE_ASSET_ID type to ContractId * Fix identity example * Changes after review * #2039 - add storage keyword highlighting in book (#2141) * #2039 - add storage keyword highlighting in book * Changes after review Co-authored-by: John Adler * Add the U256 type (#2103) * feat: add new bare u256 module to std * feat: Add base type + from,into traits * test: setup testing for U256 * cleanup * feat: add impl U256 max, min, bits, new * test: add new test assertions * style: fmt * test: generate oracle file * Update sway-lib-std/src/u256.sw Co-authored-by: John Adler * fix: remove * import * fix: improve error handling * test: better test coverage * style: fmt * docs: add test comments * test: add more test cases for to_u64() * fix: remove #r prefix from storage lib * test: remove redundant test * refactor: rename to_u64 to as_u64 * Revert "fix: remove #r prefix from storage lib" This reverts commit 8dd0738de0fef716193b6effee9b9956822157a7. Co-authored-by: John Adler * sway-fmt-v2 formatting should use tokens directly from sway-parse (#2097) * Move monomorphization conceptually inside of the type engine (#2093) * Do not rely on TypeMapping when type checking declarations. * Prevent leaking types in impls. * Prevent unconstrained type parameters. * WIP * clippy * WIP * Use TypeId in TypeMapping and in TraitMap. * Add semantic type constraints. * Update test case. * fix * Use TypeId inside of resolve_type_with_self and resolve_type_without_self. * clippy * X * Remove self_type from monomorphization. * Add conceptual distinction between replacing TypeInfo::Self and monomorphization. * Bug is fixed. * Add forc.lock. * update * Move test to inside of the SDK. * Fix test cases. * Add lock files. * Fix test. * Move the stuff. * Move monomorphization conceptually inside of the type engine. * Remove commented out test. * `forc-pkg` - Don't add transitive deps (besides `core`) to a package's initial namespace (#2136) `forc-pkg` - Don't add transitive deps (besides `core`) to namespace Currently `forc-pkg` adds all transitive dependencies to a package's initial namespace prior to its compilation. This had the benefit of implicitly including `core`, but with the downside of implicitly including every other transitive dependency package, even if not a direct depednency (not what we want). This PR changes the behaviour to only include direct dependencies and `core` within a package's initial namespace. Addresses 1, 2 of #2125. * Demonstrate that `T` for `Vec` can now be inferred by arguments (#2132) The bug is fixed. * Remove unnecessary "core" str check in `Span::join` (#2156) * Update the book to explicitly mention that `impl` functions can't call each other yet. (#2160) * Remove duplicate CI checks that already have dedicated jobs (#2161) I noticed a bunch of our CI jobs were were duplicating existing checks. In particular, there was a lot of copy-paste steps of installing forc and the forc-fmt plugin, even when unused in the following checks. This doesn't improve the real bottleneck (our stdlib test job), but it's a start. * Speedup `find_dead_code` pass in control flow analysis (#2159) Fix slow `find_dead_code` pass in control flow analysis While waiting for the tests to pass on a PR I thought I'd have a quick look to see if I could find any quick wins for dead code analysis #1952. I noticed that that we're using `has_path_connecting` for every combination of node and entry point. This means we were re-checking the same nodes many, many times, searching from scratch each time and not re-using any of the knowledge of already visited nodes in each consecutive traversal. This commit refactors the approach to first collect all known live nodes into a set by traversing from the entry points. We re-use the same `Dfs` when searching from each entry in order to re-use its inner set of visited nodes and avoid re-searching sections of the graph that we've already visited. The dead nodes are those not contained in the live set after traversal. This reduces the time taken within the `find_dead_code` call when building the `std` library in debug from ~7.9 seconds down to ~3.3 milliseconds. 1000x+ speedup in DCA :) Hopefully this speeds up our CI a bit! Closes #1952. * const initialization: a few fixes (#2158) * const initialization: a few fixes * cargo fmt * Address review comments * Add IR test Co-authored-by: Mohammad Fawaz * Update broken link for contributing to Sway in README.md (#2172) Closes https://github.com/FuelLabs/sway/issues/2171 * Backport improvements to `U128` type. (#2169) * feat: improve U128 type errors & rename to_u264 * test: add tests for renamed as_u64 * Introduce `__eq` intrinsic (#2100) * Introduce `__eq` intrinsic * Lower to `Instruction::Cmp` instead of to assembly in IRGen * Refactor intrinsics to all have arg and type arg vectors * Improvements around `forc plugins` command (#1969) Use the full path of the plugin when parsing it for a description. This avoids the following panic caused by trying to exec an executable in a sub-folder with a partial path: ``` ~/dev/sway/target/debug$ forc plugins Installed Plugins: thread 'main' panicked at 'Could not get plugin description.: Os { code: 2, kind: NotFound, message: "No such file or directory" }', forc/src/cli/commands/plugins.rs:43:10 stack backtrace: 0: rust_begin_unwind at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/panicking.rs:584:5 1: core::panicking::panic_fmt at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/panicking.rs:143:14 2: core::result::unwrap_failed at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/result.rs:1785:5 3: core::result::Result::expect at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/result.rs:1035:23 4: forc::cli::commands::plugins::parse_description_for_plugin at /home/joao/dev/sway/forc/src/cli/commands/plugins.rs:40:16 5: forc::cli::commands::plugins::format_print_description at /home/joao/dev/sway/forc/src/cli/commands/plugins.rs:81:23 6: forc::cli::commands::plugins::print_plugin at /home/joao/dev/sway/forc/src/cli/commands/plugins.rs:97:5 7: forc::cli::commands::plugins::exec at /home/joao/dev/sway/forc/src/cli/commands/plugins.rs:28:21 ``` * Updates `user_def` with `FieldAlignment` & fix corresponding use cases (#2153) * update user_def with AlignFields & fix corresponding use cases * rmv unused consts * update doc comments in ItemEnum * Add `lex_commented` and `CommentedTokenStream` to `sway_parse` (#2123) * Add `CommentedTokenStream` to `sway_parse` This doesn't yet collect any comments, but adds the necessary structure and attempts to preserve the original API and behaviour where possible. Collecting of comments to be added in a follow-up commit. * Collect multi-line comments in CommentedTokenStream * Collect single-line comments in CommentedTokenStream * Add token_trees and spanned impls for CommentedTokenStream * Add Spanned impl for CommentedTokenTree. Add comment lexing test. * Expose `lex_commented` function from root * Add CommentedTree and CommentedGroup aliases * Move CommentedTokenTree impl to better location * Clean up by using CommentedTree type alias where applicable Co-authored-by: Alex Hansen Co-authored-by: Chris O'Brien <57543709+eureka-cpu@users.noreply.github.com> * Remove unused field `const_decl_origin` from `TypedVariableDeclaration` (#2181) Remove unused const_decl_origin from TypedVariableDeclaration After #2158, constant declartaions use TypedConstantDeclaration AST node, and hence this field is now useless. It must have been removed in #2158 itself, but I missed doing that. Co-authored-by: John Adler Co-authored-by: Kaya Gökalp Co-authored-by: Vaivaswatha N Co-authored-by: Toby Hutton Co-authored-by: Mohammad Fawaz Co-authored-by: Cameron Carstens <54727135+bitzoic@users.noreply.github.com> Co-authored-by: João Matos Co-authored-by: Emily Herbert <17410721+emilyaherbert@users.noreply.github.com> Co-authored-by: rakita Co-authored-by: Chris O'Brien <57543709+eureka-cpu@users.noreply.github.com> Co-authored-by: mitchmindtree Co-authored-by: Joshua Batty Co-authored-by: bing Co-authored-by: seem-less Co-authored-by: Waseem G Co-authored-by: mitchmindtree Co-authored-by: zhou fan <1247714429@qq.com> Co-authored-by: Hlib Kanunnikov Co-authored-by: Emir Co-authored-by: r-sitko <19492095+r-sitko@users.noreply.github.com> Co-authored-by: Nick Furfaro Co-authored-by: Alex Hansen --- .github/workflows/ci.yml | 80 -- .gitignore | 1 + Cargo.lock | 718 +++++------ README.md | 2 +- docs/src/SUMMARY.md | 1 + docs/src/basics/blockchain_types.md | 32 + docs/src/forc/commands/forc_check.md | 1 + docs/src/forc/manifest_reference.md | 46 + docs/src/introduction/installation.md | 16 +- .../reference/known_issues_and_workarounds.md | 10 +- docs/theme/highlight.js | 2 +- examples/identity/Forc.lock | 14 + examples/identity/Forc.toml | 8 + examples/identity/src/abi.sw | 10 + examples/identity/src/errors.sw | 5 + examples/identity/src/main.sw | 68 ++ examples/storage_map/src/main.sw | 18 +- examples/wallet_smart_contract/src/main.sw | 6 +- forc-gm/Cargo.toml | 2 +- forc-pkg/Cargo.toml | 9 +- forc-pkg/src/lib.rs | 5 +- forc-pkg/src/manifest.rs | 100 +- forc-pkg/src/pkg.rs | 358 +++++- forc-plugins/forc-explore/Cargo.toml | 4 +- forc-plugins/forc-fmt-v2/Cargo.toml | 10 +- forc-plugins/forc-fmt/Cargo.toml | 10 +- forc-plugins/forc-lsp/Cargo.toml | 4 +- forc-util/Cargo.toml | 8 +- forc/Cargo.toml | 18 +- forc/src/cli/commands/build.rs | 18 +- forc/src/cli/commands/check.rs | 30 + forc/src/cli/commands/deploy.rs | 18 +- forc/src/cli/commands/mod.rs | 1 + forc/src/cli/commands/plugins.rs | 10 +- forc/src/cli/commands/run.rs | 20 +- forc/src/cli/mod.rs | 7 +- forc/src/lib.rs | 2 +- forc/src/ops/forc_build.rs | 142 +-- forc/src/ops/forc_check.rs | 23 + forc/src/ops/forc_deploy.rs | 19 +- forc/src/ops/forc_run.rs | 2 + forc/src/ops/mod.rs | 1 + forc/src/utils/defaults.rs | 4 +- forc/src/utils/parameters.rs | 2 +- scripts/highlightjs/sway.js | 1 + sway-core/Cargo.toml | 13 +- sway-core/src/constants.rs | 3 - .../dead_code_analysis.rs | 72 +- sway-core/src/convert_parse_tree.rs | 250 ++-- sway-core/src/error.rs | 25 + sway-core/src/ir_generation.rs | 5 +- sway-core/src/ir_generation/compile.rs | 19 +- sway-core/src/ir_generation/const_eval.rs | 24 +- sway-core/src/ir_generation/convert.rs | 17 - sway-core/src/ir_generation/function.rs | 164 ++- sway-core/src/ir_generation/storage.rs | 234 ++++ sway-core/src/lib.rs | 19 +- sway-core/src/parse_tree/declaration.rs | 4 - sway-core/src/parse_tree/declaration/enum.rs | 5 +- .../src/parse_tree/declaration/impl_trait.rs | 7 +- .../src/parse_tree/declaration/storage.rs | 3 +- .../src/parse_tree/declaration/struct.rs | 4 +- .../expression/intrinsic_function.rs | 18 - sway-core/src/parse_tree/expression/mod.rs | 10 +- .../src/parse_tree/expression/scrutinee.rs | 23 +- sway-core/src/semantic_analysis.rs | 4 +- .../semantic_analysis/ast_node/code_block.rs | 58 +- .../semantic_analysis/ast_node/declaration.rs | 11 +- .../ast_node/declaration/abi.rs | 16 +- .../ast_node/declaration/enum.rs | 41 +- .../ast_node/declaration/function.rs | 90 +- .../function/function_parameter.rs | 17 +- .../ast_node/declaration/impl_trait.rs | 138 +-- .../ast_node/declaration/monomorphize.rs | 203 ---- .../ast_node/declaration/storage.rs | 67 +- .../ast_node/declaration/struct.rs | 33 +- .../ast_node/declaration/trait.rs | 28 +- .../ast_node/declaration/variable.rs | 22 +- .../ast_node/expression/intrinsic_function.rs | 280 +++-- .../match_expression/analysis/pattern.rs | 30 +- .../typed/typed_match_branch.rs | 62 +- .../typed/typed_match_expression.rs | 48 +- .../match_expression/typed/typed_scrutinee.rs | 111 +- .../ast_node/expression/typed_expression.rs | 972 ++++++--------- .../typed_expression/enum_instantiation.rs | 28 +- .../typed_expression/function_application.rs | 42 +- .../typed_expression/if_expression.rs | 13 +- .../typed_expression/method_application.rs | 116 +- .../src/semantic_analysis/ast_node/mod.rs | 403 +++--- sway-core/src/semantic_analysis/module.rs | 37 +- .../src/semantic_analysis/namespace/items.rs | 27 - .../semantic_analysis/namespace/namespace.rs | 50 +- .../src/semantic_analysis/namespace/root.rs | 148 +-- .../semantic_analysis/namespace/trait_map.rs | 40 +- .../semantic_analysis/node_dependencies.rs | 8 +- sway-core/src/semantic_analysis/program.rs | 67 +- .../semantic_analysis/type_check_arguments.rs | 18 - .../semantic_analysis/type_check_context.rs | 224 ++++ sway-core/src/type_engine/engine.rs | 153 ++- sway-core/src/type_engine/mod.rs | 6 + sway-core/src/type_engine/trait_constraint.rs | 6 + .../type_argument.rs | 0 sway-core/src/type_engine/type_info.rs | 272 ++++- sway-core/src/type_engine/type_mapping.rs | 110 +- .../type_parameter.rs | 24 +- sway-core/tests/sway_to_ir/eq_intrinsic.ir | 21 + sway-core/tests/sway_to_ir/eq_intrinsic.sw | 6 + .../tests/sway_to_ir/local_const_init.ir | 20 + .../tests/sway_to_ir/local_const_init.sw | 14 + sway-fmt-v2/Cargo.toml | 10 +- sway-fmt-v2/src/config/heuristics.rs | 21 +- sway-fmt-v2/src/config/user_def.rs | 37 +- sway-fmt-v2/src/config/user_opts.rs | 4 +- sway-fmt-v2/src/constants.rs | 7 - sway-fmt-v2/src/error.rs | 2 + sway-fmt-v2/src/fmt.rs | 234 +++- sway-fmt-v2/src/items/item_abi.rs | 114 +- sway-fmt-v2/src/items/item_const.rs | 45 +- sway-fmt-v2/src/items/item_enum.rs | 264 ++-- sway-fmt-v2/src/items/item_fn.rs | 11 +- sway-fmt-v2/src/items/item_impl.rs | 11 +- sway-fmt-v2/src/items/item_storage.rs | 11 +- sway-fmt-v2/src/items/item_struct.rs | 233 +++- sway-fmt-v2/src/items/item_trait.rs | 11 +- sway-fmt-v2/src/items/item_use.rs | 11 +- sway-fmt-v2/src/utils.rs | 13 +- sway-fmt-v2/src/utils/attribute.rs | 93 ++ sway-fmt-v2/src/utils/attributes.rs | 11 - sway-fmt-v2/src/utils/bracket.rs | 52 +- sway-fmt-v2/src/utils/generics.rs | 48 + sway-fmt-v2/src/utils/item.rs | 23 + sway-fmt-v2/src/utils/item_len.rs | 3 + sway-fmt-v2/src/utils/program_type.rs | 29 + sway-fmt-v2/src/utils/punctuated.rs | 57 + sway-fmt/Cargo.toml | 6 +- sway-ir/Cargo.toml | 4 +- sway-ir/src/block.rs | 5 + sway-ir/src/verify.rs | 8 +- sway-lib-core/src/ops.sw | 25 +- sway-lib-std/src/constants.sw | 4 +- sway-lib-std/src/identity.sw | 2 + sway-lib-std/src/lib.sw | 5 +- sway-lib-std/src/storage.sw | 4 +- sway-lib-std/src/u128.sw | 15 +- sway-lib-std/src/u256.sw | 90 ++ sway-lsp/Cargo.toml | 16 +- sway-lsp/src/core/document.rs | 23 +- sway-lsp/src/core/token.rs | 17 +- sway-lsp/src/core/traverse_typed_tree.rs | 14 +- sway-lsp/src/server.rs | 60 +- sway-parse/Cargo.toml | 6 +- sway-parse/src/attribute.rs | 7 +- sway-parse/src/error.rs | 4 + sway-parse/src/expr/asm.rs | 15 +- sway-parse/src/expr/mod.rs | 4 +- sway-parse/src/intrinsics.rs | 23 +- sway-parse/src/item/item_use.rs | 7 +- sway-parse/src/keywords.rs | 49 + sway-parse/src/lib.rs | 4 +- sway-parse/src/literal.rs | 7 +- sway-parse/src/parse.rs | 7 + sway-parse/src/path.rs | 18 +- sway-parse/src/pattern.rs | 48 +- sway-parse/src/token.rs | 323 +++-- sway-types/Cargo.toml | 4 +- sway-types/src/ident.rs | 17 + sway-types/src/span.rs | 11 +- sway-utils/Cargo.toml | 2 +- test-sig-gen-util/Cargo.toml | 4 +- test/Cargo.toml | 9 +- test/src/e2e_vm_tests/harness.rs | 133 +- test/src/e2e_vm_tests/mod.rs | 1078 ++++++----------- test/src/e2e_vm_tests/test_programs/README.md | 115 ++ .../abi_impl_purity_mismatch/test.toml | 3 + .../abi_method_signature_mismatch/test.toml | 5 + .../abi_pure_calls_impure/test.toml | 4 + .../abort_control_flow_bad/test.toml | 16 + .../should_fail/array_bad_index/test.toml | 6 + .../should_fail/array_oob/test.toml | 3 + .../should_fail/asm_missing_return/test.toml | 13 + .../asm_should_not_have_return/test.toml | 15 + .../test.toml | 3 + .../bad_generic_annotation/test.toml | 7 + .../bad_generic_var_annotation/test.toml | 13 + .../better_type_error_message/test.toml | 4 + .../chained_if_let_missing_branch/test.toml | 3 + .../should_fail/const_nonconst_init/Forc.lock | 9 + .../should_fail/const_nonconst_init/Forc.toml | 8 + .../const_nonconst_init/src/main.sw | 10 + .../should_fail/const_nonconst_init/test.toml | 4 + .../contract_pure_calls_impure/test.toml | 4 + .../cyclic_dependency/dependency_a/test.toml | 3 + .../dependency_parsing_error/test.toml | 5 + .../different_contract_caller_types/test.toml | 15 + .../should_fail/disallow_turbofish/test.toml | 10 + .../should_fail/disallowed_gm/test.toml | 4 + .../double_underscore_enum/test.toml | 4 + .../double_underscore_fn/test.toml | 4 + .../double_underscore_impl_self_fn/test.toml | 4 + .../double_underscore_struct/test.toml | 4 + .../double_underscore_trait_fn/test.toml | 4 + .../double_underscore_var/test.toml | 4 + .../should_fail/empty_impl/test.toml | 3 + .../enum_bad_type_inference/Forc.toml | 2 +- .../enum_bad_type_inference/test.toml | 12 + .../enum_if_let_invalid_variable/test.toml | 4 + .../should_fail/eq_intrinsic/Forc.lock | 14 + .../should_fail/eq_intrinsic/Forc.toml | 8 + .../eq_intrinsic/json_abi_oracle.json | 14 + .../should_fail/eq_intrinsic/src/main.sw | 23 + .../should_fail/eq_intrinsic/test.toml | 25 + .../should_fail/excess_fn_arguments/Forc.lock | 7 +- .../should_fail/excess_fn_arguments/Forc.toml | 4 +- .../should_fail/excess_fn_arguments/test.toml | 5 + .../generic_shadows_generic/test.toml | 3 + .../generics_unhelpful_error/test.toml | 4 + .../impl_with_bad_generic/test.toml | 7 + .../.gitignore | 2 + .../Forc.lock | 14 + .../Forc.toml | 8 + .../src/main.sw | 54 + .../test.toml | 10 + .../test.toml | 5 + .../impure_read_calls_impure_write/test.toml | 5 + .../test.toml | 5 + .../infinite_dependencies/Forc.lock | 1 + .../infinite_dependencies/test.toml | 5 + .../insufficient_type_info/src/main.sw | 2 +- .../insufficient_type_info/test.toml | 4 + .../item_used_without_import/test.toml | 3 + .../literal_too_large_for_type/test.toml | 4 + .../match_expressions_empty_arms/test.toml | 4 + .../match_expressions_multiple_rest/Forc.lock | 4 + .../match_expressions_multiple_rest/Forc.toml | 6 + .../src/main.sw | 21 + .../match_expressions_multiple_rest/test.toml | 4 + .../Forc.toml | 2 +- .../test.toml | 34 + .../match_expressions_rest/Forc.lock | 4 + .../match_expressions_rest/Forc.toml | 6 + .../match_expressions_rest/src/main.sw | 21 + .../match_expressions_rest/test.toml | 4 + .../Forc.lock | 4 + .../Forc.toml | 6 + .../src/main.sw | 21 + .../test.toml | 4 + .../match_expressions_wrong_struct/test.toml | 21 + .../method_requires_mut_var/test.toml | 3 + .../missing_fn_arguments/Forc.lock | 7 +- .../missing_fn_arguments/Forc.toml | 4 +- .../missing_fn_arguments/test.toml | 4 + .../test.toml | 6 + .../missing_supertrait_impl/test.toml | 7 + .../should_fail/multiple_impl_abi/test.toml | 3 + .../should_fail/multiple_impl_fns/test.toml | 4 + .../should_fail/name_shadowing/test.toml | 4 + .../should_fail/nested_impure/test.toml | 10 + .../nonconst_storage_init/Forc.lock | 9 + .../nonconst_storage_init/Forc.toml | 8 + .../nonconst_storage_init/src/main.sw | 19 + .../nonconst_storage_init/test.toml | 9 + .../predicate_calls_impure/test.toml | 9 + .../primitive_type_argument/test.toml | 7 + .../should_fail/pure_calls_impure/test.toml | 4 + .../should_fail/recursive_calls/test.toml | 8 + .../should_fail/recursive_enum/test.toml | 3 + .../should_fail/recursive_struct/test.toml | 3 + .../recursive_type_chain/test.toml | 12 + .../repeated_enum_variant/test.toml | 10 + .../repeated_storage_field/test.toml | 10 + .../repeated_struct_field/test.toml | 9 + .../reserved_identifiers/Forc.lock | 4 + .../reserved_identifiers/Forc.toml | 6 + .../reserved_identifiers/src/main.sw | 39 + .../reserved_identifiers/test.toml | 4 + .../should_fail/script_calls_impure/test.toml | 4 + .../should_fail/shadow_import/test.toml | 6 + .../should_fail/star_import_alias/src/main.sw | 2 +- .../should_fail/star_import_alias/test.toml | 4 + .../should_fail/storage_conflict/test.toml | 49 + .../should_fail/storage_in_library/test.toml | 9 + .../storage_in_predicate/test.toml | 9 + .../should_fail/storage_in_script/test.toml | 9 + .../storage_ops_in_library/test.toml | 4 + .../supertrait_does_not_exist/test.toml | 3 + .../should_fail/top_level_vars/test.toml | 4 + .../trait_impl_purity_mismatch/test.toml | 3 + .../trait_method_signature_mismatch/test.toml | 5 + .../trait_pure_calls_impure/test.toml | 4 + .../type_mismatch_error_message/test.toml | 4 + .../unify_identical_unknowns/test.toml | 8 + .../test_programs/should_fail/vec/.gitignore | 2 + .../test_programs/should_fail/vec/Forc.lock | 14 + .../test_programs/should_fail/vec/Forc.toml | 8 + .../test_programs/should_fail/vec/src/main.sw | 113 ++ .../test_programs/should_fail/vec/test.toml | 10 + .../forc/dependency_package_field/test.toml | 3 + .../forc/dependency_patching/Forc.lock | 14 + .../forc/dependency_patching/Forc.toml | 10 + .../dependency_patching/json_abi_oracle.json | 14 + .../forc/dependency_patching/src/main.sw | 5 + .../forc/dependency_patching/test.toml | 1 + .../language/abort_control_flow/test.toml | 1 + .../abort_control_flow_good/test.toml | 3 + .../language/aliased_imports/test.toml | 3 + .../language/array_basics/test.toml | 3 + .../language/array_dynamic_oob/test.toml | 1 + .../language/array_generics/test.toml | 3 + .../language/asm_expr_basic/test.toml | 3 + .../language/asm_without_return/test.toml | 3 + .../language/b256_bad_jumps/test.toml | 3 + .../language/b256_bitwise_ops/test.toml | 3 + .../should_pass/language/b256_ops/test.toml | 3 + .../language/basic_func_decl/test.toml | 3 + .../language/basic_predicate/test.toml | 2 + .../binary_and_hex_literals/test.toml | 1 + .../language/bool_and_or/test.toml | 3 + .../builtin_type_method_call/test.toml | 3 + .../language/chained_if_let/test.toml | 3 + .../should_pass/language/const_decl/test.toml | 3 + .../language/const_decl_in_library/test.toml | 3 + .../language/const_inits/src/main.sw | 13 +- .../language/const_inits/test.toml | 3 + .../contract_caller_as_type/test.toml | 3 + .../language/dependencies/test.toml | 3 + .../language/doc_strings/test.toml | 1 + .../empty_method_initializer/test.toml | 3 + .../language/enum_destructuring/test.toml | 3 + .../language/enum_if_let/test.toml | 3 + .../language/enum_if_let_large_type/test.toml | 3 + .../language/enum_in_fn_decl/test.toml | 3 + .../language/enum_init_fn_call/test.toml | 3 + .../language/enum_padding/test.toml | 3 + .../language/enum_type_inference/test.toml | 3 + .../should_pass/language/eq_and_neq/test.toml | 3 + .../language/eq_intrinsic/Forc.lock | 14 + .../language/eq_intrinsic/Forc.toml | 8 + .../eq_intrinsic/json_abi_oracle.json | 14 + .../language/eq_intrinsic/src/main.sw | 39 + .../language/eq_intrinsic/test.toml | 3 + .../language/fix_opcode_bug/test.toml | 3 + .../funcs_with_generic_types/test.toml | 3 + .../language/generic-type-inference/test.toml | 3 + .../language/generic_enum/test.toml | 3 + .../language/generic_functions/test.toml | 3 + .../language/generic_impl_self/test.toml | 3 + .../language/generic_inside_generic/test.toml | 3 + .../language/generic_struct/test.toml | 3 + .../language/generic_structs/test.toml | 3 + .../language/if_elseif_enum/test.toml | 3 + .../language/if_implicit_unit/test.toml | 3 + .../language/implicit_return/test.toml | 3 + .../import_method_from_other_file/test.toml | 3 + .../language/import_trailing_comma/test.toml | 3 + .../should_pass/language/impure_ifs/Forc.lock | 14 + .../should_pass/language/impure_ifs/Forc.toml | 8 + .../language/impure_ifs/json_abi_oracle.json | 14 + .../language/impure_ifs/src/main.sw | 90 ++ .../should_pass/language/impure_ifs/test.toml | 3 + .../language/inline_if_expr_const/test.toml | 3 + .../should_pass/language/is_prime/test.toml | 3 + .../language/is_reference_type/test.toml | 3 + .../language/local_impl_for_ord/test.toml | 3 + .../language/main_returns_unit/test.toml | 3 + .../language/many_stack_variables/test.toml | 3 + .../language/match_expressions/test.toml | 3 + .../match_expressions_enums/test.toml | 3 + .../test.toml | 3 + .../match_expressions_mismatched/test.toml | 3 + .../match_expressions_nested/test.toml | 3 + .../language/match_expressions_rest/Forc.lock | 17 + .../language/match_expressions_rest/Forc.toml | 10 + .../json_abi_oracle.json | 14 + .../match_expressions_rest/src/main.sw | 64 + .../language/match_expressions_rest/test.toml | 3 + .../match_expressions_simple/test.toml | 3 + .../match_expressions_structs/test.toml | 3 + .../match_expressions_with_self/test.toml | 3 + .../language/method_on_empty_struct/test.toml | 3 + .../missing_type_parameters/test.toml | 1 + .../language/modulo_uint_test/test.toml | 3 + .../language/multi_impl_self/test.toml | 3 + .../language/multi_item_import/test.toml | 3 + .../language/nested_structs/test.toml | 3 + .../language/nested_while_and_if/test.toml | 3 + .../language/new_allocator_test/test.toml | 3 + .../language/non_literal_const_decl/test.toml | 3 + .../language/numeric_constants/test.toml | 3 + .../language/op_precedence/test.toml | 3 + .../language/out_of_order_decl/test.toml | 3 + .../primitive_type_argument/test.toml | 3 + .../language/raw_identifiers/Forc.lock | 9 + .../language/raw_identifiers/Forc.toml | 8 + .../raw_identifiers/json_abi_oracle.json | 14 + .../language/raw_identifiers/src/main.sw | 52 + .../language/raw_identifiers/test.toml | 3 + .../language/reassignment_operators/test.toml | 3 + .../language/ret_small_string/test.toml | 3 + .../language/ret_string_in_struct/test.toml | 3 + .../should_pass/language/retd_b256/test.toml | 3 + .../language/retd_small_array/test.toml | 3 + .../language/retd_struct/test.toml | 3 + .../language/retd_zero_len_array/test.toml | 3 + .../language/self_impl_reassignment/test.toml | 3 + .../should_pass/language/size_of/test.toml | 3 + .../language/storage_declaration/test.toml | 1 + .../language/struct_field_access/test.toml | 3 + .../struct_field_reassignment/test.toml | 3 + .../language/supertraits/test.toml | 3 + .../language/trait_import_with_star/test.toml | 3 + .../language/trait_override_bug/test.toml | 3 + .../language/tuple_access/test.toml | 3 + .../language/tuple_desugaring/test.toml | 3 + .../tuple_field_reassignment/test.toml | 3 + .../language/tuple_in_struct/test.toml | 3 + .../language/tuple_indexing/test.toml | 3 + .../language/tuple_single_element/test.toml | 3 + .../language/tuple_types/test.toml | 3 + .../should_pass/language/u64_ops/test.toml | 3 + .../language/unary_not_basic/test.toml | 3 + .../language/unary_not_basic_2/test.toml | 3 + .../language/unit_type_variants/test.toml | 3 + .../language/use_full_path_names/test.toml | 3 + .../language/valid_impurity/test.toml | 2 + .../language/while_loops/test.toml | 3 + .../should_pass/language/xos_opcode/test.toml | 1 + .../language/zero_field_types/test.toml | 3 + .../array_of_structs_caller/test.toml | 3 + .../bal_opcode/test.toml | 3 + .../call_abi_with_tuples/test.toml | 3 + .../call_basic_storage/test.toml | 3 + .../call_increment_contract/test.toml | 3 + .../caller_auth_test/test.toml | 3 + .../caller_context_test/src/main.sw | 8 +- .../caller_context_test/test.toml | 3 + .../get_storage_key_caller/test.toml | 3 + .../nested_struct_args_caller/test.toml | 1 + .../storage_access_caller/src/main.sw | 50 +- .../storage_access_caller/test.toml | 3 + .../token_ops_test/test.toml | 3 + .../should_pass/stdlib/address_test/test.toml | 3 + .../should_pass/stdlib/alloc/test.toml | 3 + .../should_pass/stdlib/assert_test/test.toml | 3 + .../stdlib/b512_struct_alignment/test.toml | 3 + .../should_pass/stdlib/b512_test/test.toml | 3 + .../should_pass/stdlib/block_height/test.toml | 3 + .../stdlib/contract_id_test/Forc.lock | 9 +- .../stdlib/contract_id_test/test.toml | 1 + .../stdlib/contract_id_type/src/main.sw | 4 +- .../stdlib/contract_id_type/test.toml | 3 + .../stdlib/ec_recover_test/test.toml | 3 + .../should_pass/stdlib/evm_ecr/test.toml | 3 + .../stdlib/exponentiation_test/test.toml | 3 + .../should_pass/stdlib/ge_test/test.toml | 3 + .../stdlib/identity_eq/src/main.sw | 2 +- .../should_pass/stdlib/identity_eq/test.toml | 3 + .../should_pass/stdlib/intrinsics/test.toml | 3 + .../should_pass/stdlib/mem/test.toml | 3 + .../should_pass/stdlib/option/test.toml | 3 + .../should_pass/stdlib/require/test.toml | 3 + .../should_pass/stdlib/result/src/main.sw | 2 +- .../should_pass/stdlib/result/test.toml | 3 + .../stdlib/u128_div_test/test.toml | 3 + .../stdlib/u128_mul_test/test.toml | 3 + .../should_pass/stdlib/u128_test/src/main.sw | 25 + .../should_pass/stdlib/u128_test/test.toml | 3 + .../should_pass/stdlib/u256_test/.gitignore | 2 + .../should_pass/stdlib/u256_test/Forc.lock | 14 + .../should_pass/stdlib/u256_test/Forc.toml | 8 + .../stdlib/u256_test/json_abi_oracle.json | 14 + .../should_pass/stdlib/u256_test/src/main.sw | 103 ++ .../should_pass/stdlib/u256_test/test.toml | 3 + .../should_pass/stdlib/vec/src/main.sw | 18 +- .../should_pass/stdlib/vec/test.toml | 3 + .../test_abis/abi_with_tuples/Forc.lock | 8 +- .../test_abis/storage_access_abi/src/main.sw | 2 + .../json_storage_slots_oracle.json | 1 + .../abi_with_tuples_contract/test.toml | 3 + .../json_storage_slots_oracle.json | 1 + .../array_of_structs_contract/test.toml | 3 + .../json_storage_slots_oracle.json | 1 + .../auth_testing_contract/test.toml | 3 + .../json_storage_slots_oracle.json | 1 + .../balance_test_contract/test.toml | 3 + .../json_storage_slots_oracle.json | 1 + .../test_contracts/basic_storage/test.toml | 3 + .../json_storage_slots_oracle.json | 1 + .../context_testing_contract/test.toml | 3 + .../json_storage_slots_oracle.json | 1 + .../get_storage_key_contract/test.toml | 3 + .../json_storage_slots_oracle.json | 1 + .../increment_contract/test.toml | 3 + .../json_storage_slots_oracle.json | 1 + .../test_contracts/issue_1512_repro/test.toml | 3 + .../json_storage_slots_oracle.json | 1 + .../test_contracts/multiple_impl/test.toml | 3 + .../json_storage_slots_oracle.json | 1 + .../nested_struct_args_contract/test.toml | 3 + .../json_abi_oracle.json | 59 + .../json_storage_slots_oracle.json | 106 ++ .../storage_access_contract/src/main.sw | 181 ++- .../storage_access_contract/test.toml | 3 + .../json_storage_slots_oracle.json | 1 + .../test_fuel_coin_contract/test.toml | 3 + test/src/sdk-harness/Cargo.toml | 9 +- .../context_testing_abi/src/main.sw | 2 +- .../test_artifacts/methods_abi/Forc.lock | 4 + .../test_artifacts/methods_abi/Forc.toml | 6 + .../test_artifacts/methods_abi/src/main.sw | 6 + .../test_artifacts/methods_contract/Forc.lock | 22 + .../test_artifacts/methods_contract/Forc.toml | 9 + .../methods_contract/src/main.sw | 41 + .../src/sdk-harness/test_projects/auth/mod.rs | 1 - .../test_projects/call_frames/mod.rs | 1 - .../sdk-harness/test_projects/context/mod.rs | 1 - .../test_projects/context/src/main.sw | 4 +- .../test_projects/exponentiation/mod.rs | 1 - test/src/sdk-harness/test_projects/harness.rs | 1 + .../sdk-harness/test_projects/hashing/mod.rs | 1 - .../sdk-harness/test_projects/logging/mod.rs | 4 +- .../sdk-harness/test_projects/methods/mod.rs | 27 + .../test_projects/reentrancy/mod.rs | 10 +- .../test_projects/registers/mod.rs | 1 - .../test_projects/script_data/mod.rs | 4 +- .../sdk-harness/test_projects/storage/mod.rs | 1 - .../test_projects/storage_map/mod.rs | 1 - .../test_projects/token_ops/mod.rs | 1 - .../test_projects/tx_fields/mod.rs | 15 +- 528 files changed, 8877 insertions(+), 4347 deletions(-) create mode 100644 docs/src/forc/commands/forc_check.md create mode 100644 examples/identity/Forc.lock create mode 100644 examples/identity/Forc.toml create mode 100644 examples/identity/src/abi.sw create mode 100644 examples/identity/src/errors.sw create mode 100644 examples/identity/src/main.sw create mode 100644 forc/src/cli/commands/check.rs create mode 100644 forc/src/ops/forc_check.rs create mode 100644 sway-core/src/ir_generation/storage.rs delete mode 100644 sway-core/src/parse_tree/expression/intrinsic_function.rs delete mode 100644 sway-core/src/semantic_analysis/ast_node/declaration/monomorphize.rs delete mode 100644 sway-core/src/semantic_analysis/type_check_arguments.rs create mode 100644 sway-core/src/semantic_analysis/type_check_context.rs create mode 100644 sway-core/src/type_engine/trait_constraint.rs rename sway-core/src/{parse_tree/declaration => type_engine}/type_argument.rs (100%) rename sway-core/src/{parse_tree/declaration => type_engine}/type_parameter.rs (88%) create mode 100644 sway-core/tests/sway_to_ir/eq_intrinsic.ir create mode 100644 sway-core/tests/sway_to_ir/eq_intrinsic.sw create mode 100644 sway-core/tests/sway_to_ir/local_const_init.ir create mode 100644 sway-core/tests/sway_to_ir/local_const_init.sw create mode 100644 sway-fmt-v2/src/utils/attribute.rs delete mode 100644 sway-fmt-v2/src/utils/attributes.rs create mode 100644 sway-fmt-v2/src/utils/generics.rs create mode 100644 sway-fmt-v2/src/utils/item.rs create mode 100644 sway-fmt-v2/src/utils/item_len.rs create mode 100644 sway-fmt-v2/src/utils/program_type.rs create mode 100644 sway-fmt-v2/src/utils/punctuated.rs create mode 100644 sway-lib-std/src/u256.sw create mode 100644 test/src/e2e_vm_tests/test_programs/README.md create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/abi_impl_purity_mismatch/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/abi_method_signature_mismatch/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/abi_pure_calls_impure/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/abort_control_flow_bad/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/array_bad_index/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/array_oob/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/asm_missing_return/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/asm_should_not_have_return/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/assign_to_field_of_non_mutable_struct/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/bad_generic_annotation/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/bad_generic_var_annotation/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/better_type_error_message/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/chained_if_let_missing_branch/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/contract_pure_calls_impure/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/cyclic_dependency/dependency_a/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/dependency_parsing_error/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/different_contract_caller_types/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/disallow_turbofish/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/disallowed_gm/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_enum/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_fn/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_impl_self_fn/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_struct/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_trait_fn/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_var/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/empty_impl/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/enum_bad_type_inference/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/enum_if_let_invalid_variable/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/excess_fn_arguments/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/generic_shadows_generic/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/generics_unhelpful_error/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/impl_with_bad_generic/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/.gitignore create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/impure_abi_read_calls_impure_write/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/impure_read_calls_impure_write/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/impure_trait_read_calls_impure_write/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/infinite_dependencies/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/insufficient_type_info/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/item_used_without_import/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/literal_too_large_for_type/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_empty_arms/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_non_exhaustive/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_wrong_struct/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/method_requires_mut_var/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/missing_fn_arguments/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/missing_func_from_supertrait_impl/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/missing_supertrait_impl/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/multiple_impl_abi/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/multiple_impl_fns/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/name_shadowing/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/nested_impure/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/predicate_calls_impure/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/primitive_type_argument/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/pure_calls_impure/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/recursive_calls/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/recursive_enum/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/recursive_struct/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/recursive_type_chain/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/repeated_enum_variant/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/repeated_storage_field/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/repeated_struct_field/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/script_calls_impure/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/shadow_import/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/star_import_alias/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/storage_conflict/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/storage_in_library/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/storage_in_predicate/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/storage_in_script/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/storage_ops_in_library/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/supertrait_does_not_exist/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/top_level_vars/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/trait_impl_purity_mismatch/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/trait_method_signature_mismatch/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/trait_pure_calls_impure/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/type_mismatch_error_message/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/unify_identical_unknowns/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/vec/.gitignore create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/vec/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/vec/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/vec/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/vec/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_package_field/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/abort_control_flow/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/abort_control_flow_good/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/aliased_imports/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/array_basics/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/array_dynamic_oob/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/array_generics/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/asm_expr_basic/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/asm_without_return/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/b256_bad_jumps/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/b256_bitwise_ops/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/b256_ops/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/basic_func_decl/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/basic_predicate/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/binary_and_hex_literals/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/bool_and_or/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/builtin_type_method_call/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/chained_if_let/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/const_decl/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/const_decl_in_library/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/const_inits/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/contract_caller_as_type/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/dependencies/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/doc_strings/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/empty_method_initializer/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/enum_destructuring/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/enum_if_let/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/enum_if_let_large_type/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/enum_in_fn_decl/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/enum_init_fn_call/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/enum_padding/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/enum_type_inference/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/eq_and_neq/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/fix_opcode_bug/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/funcs_with_generic_types/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/generic-type-inference/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/generic_enum/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/generic_functions/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/generic_impl_self/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/generic_inside_generic/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/generic_struct/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/generic_structs/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/if_elseif_enum/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/if_implicit_unit/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/implicit_return/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/import_method_from_other_file/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/import_trailing_comma/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/inline_if_expr_const/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/is_prime/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/is_reference_type/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/local_impl_for_ord/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/main_returns_unit/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/many_stack_variables/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_enums/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_inside_generic_functions/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_mismatched/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_nested/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_simple/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_structs/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_with_self/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/method_on_empty_struct/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/missing_type_parameters/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/modulo_uint_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/multi_impl_self/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/multi_item_import/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/nested_structs/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/nested_while_and_if/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/new_allocator_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/non_literal_const_decl/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/numeric_constants/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/op_precedence/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/out_of_order_decl/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/primitive_type_argument/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/reassignment_operators/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/ret_small_string/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/ret_string_in_struct/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/retd_b256/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/retd_small_array/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/retd_struct/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/retd_zero_len_array/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/self_impl_reassignment/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/size_of/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/storage_declaration/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/struct_field_access/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/struct_field_reassignment/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/supertraits/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/trait_import_with_star/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/trait_override_bug/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_access/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_desugaring/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_field_reassignment/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_in_struct/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_indexing/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_single_element/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_types/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/u64_ops/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/unary_not_basic/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/unary_not_basic_2/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/unit_type_variants/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/use_full_path_names/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/valid_impurity/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/while_loops/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/xos_opcode/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/zero_field_types/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/token_ops_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/address_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/alloc/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/assert_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/b512_struct_alignment/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/b512_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/block_height/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_type/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/ec_recover_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/evm_ecr/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/exponentiation_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/ge_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/identity_eq/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/intrinsics/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/mem/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/option/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/require/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/result/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_div_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_mul_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/.gitignore create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/abi_with_tuples_contract/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/abi_with_tuples_contract/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/array_of_structs_contract/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/array_of_structs_contract/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/auth_testing_contract/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/auth_testing_contract/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/balance_test_contract/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/balance_test_contract/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/context_testing_contract/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/context_testing_contract/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/issue_1512_repro/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/issue_1512_repro/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/multiple_impl/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/multiple_impl/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/nested_struct_args_contract/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/nested_struct_args_contract/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/test.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/test_fuel_coin_contract/json_storage_slots_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/test_fuel_coin_contract/test.toml create mode 100644 test/src/sdk-harness/test_artifacts/methods_abi/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/methods_abi/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/methods_abi/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/methods_contract/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/methods_contract/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/methods_contract/src/main.sw create mode 100644 test/src/sdk-harness/test_projects/methods/mod.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00cb018d29a..a1f5a7fe54a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -162,11 +162,6 @@ jobs: with: command: install args: --debug --path ./forc - - name: Install Forc fmt - uses: actions-rs/cargo@v1 - with: - command: install - args: --debug --path ./forc-plugins/forc-fmt - name: Initialize test project run: forc init test-proj - name: Update project forc manifest to use local sway-lib-std @@ -191,21 +186,6 @@ jobs: profile: minimal toolchain: stable - uses: Swatinem/rust-cache@v1 - - name: Install Forc - uses: actions-rs/cargo@v1 - with: - command: install - args: --debug --path ./forc - - name: Install Forc fmt - uses: actions-rs/cargo@v1 - with: - command: install - args: --debug --path ./forc-plugins/forc-fmt - - name: Build Sway examples - uses: actions-rs/cargo@v1 - with: - command: run - args: --bin examples-checker build --all-examples - uses: actions-rs/cargo@v1 name: Cargo Build Workspace with: @@ -223,21 +203,6 @@ jobs: with: toolchain: stable - uses: Swatinem/rust-cache@v1 - - name: Install Forc - uses: actions-rs/cargo@v1 - with: - command: install - args: --debug --path ./forc - - name: Install Forc fmt - uses: actions-rs/cargo@v1 - with: - command: install - args: --debug --path ./forc-plugins/forc-fmt - - name: Build Sway examples - uses: actions-rs/cargo@v1 - with: - command: run - args: --bin examples-checker build --all-examples - name: Check Clippy Linter uses: actions-rs/cargo@v1 with: @@ -311,21 +276,6 @@ jobs: profile: minimal toolchain: stable - uses: Swatinem/rust-cache@v1 - - name: Install Forc - uses: actions-rs/cargo@v1 - with: - command: install - args: --debug --path ./forc - - name: Install Forc fmt - uses: actions-rs/cargo@v1 - with: - command: install - args: --debug --path ./forc-plugins/forc-fmt - - name: Build Sway examples - uses: actions-rs/cargo@v1 - with: - command: run - args: --locked --bin examples-checker build --all-examples - name: Build All Tests run: cd test/src/sdk-harness && bash build.sh --locked && cd ../../../ - name: Cargo Test sway-lib-std @@ -344,21 +294,6 @@ jobs: profile: minimal toolchain: stable - uses: Swatinem/rust-cache@v1 - - name: Install Forc - uses: actions-rs/cargo@v1 - with: - command: install - args: --debug --path ./forc - - name: Install Forc fmt - uses: actions-rs/cargo@v1 - with: - command: install - args: --debug --path ./forc-plugins/forc-fmt - - name: Build Sway examples - uses: actions-rs/cargo@v1 - with: - command: run - args: --bin examples-checker build --all-examples - name: Run tests uses: actions-rs/cargo@v1 with: @@ -376,21 +311,6 @@ jobs: toolchain: nightly default: true - uses: Swatinem/rust-cache@v1 - - name: Install Forc - uses: actions-rs/cargo@v1 - with: - command: install - args: --debug --path ./forc - - name: Install Forc fmt - uses: actions-rs/cargo@v1 - with: - command: install - args: --debug --path ./forc-plugins/forc-fmt - - name: Build Sway examples - uses: actions-rs/cargo@v1 - with: - command: run - args: --locked --bin examples-checker build --all-examples - name: Install cargo-udeps uses: actions-rs/cargo@v1 with: diff --git a/.gitignore b/.gitignore index 3facbca8035..d8e9a544778 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # will have compiled files and executables **/*/target/ **/*/json_abi_output.json +**/*/json_storage_slots_output.json target # These are backup files generated by rustfmt diff --git a/Cargo.lock b/Cargo.lock index a1b1671c2c4..a15da9a2f34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" +checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" [[package]] name = "arrayref" @@ -118,12 +118,6 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" -[[package]] -name = "assert_matches" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" - [[package]] name = "async-channel" version = "1.6.1" @@ -161,17 +155,16 @@ dependencies = [ [[package]] name = "async-global-executor" -version = "2.0.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c290043c9a95b05d45e952fb6383c67bcb61471f60cfa21e890dba6654234f43" +checksum = "fd8b508d585e01084059b60f06ade4cb7415cd2e4084b71dd1cb44e7d3fb9880" dependencies = [ "async-channel", "async-executor", "async-io", - "async-mutex", + "async-lock", "blocking", "futures-lite", - "num_cpus", "once_cell", ] @@ -193,9 +186,9 @@ dependencies = [ [[package]] name = "async-io" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" +checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07" dependencies = [ "concurrent-queue", "futures-lite", @@ -219,15 +212,6 @@ dependencies = [ "event-listener", ] -[[package]] -name = "async-mutex" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" -dependencies = [ - "event-listener", -] - [[package]] name = "async-std" version = "1.11.0" @@ -276,9 +260,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.53" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" +checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" dependencies = [ "proc-macro2", "quote", @@ -331,9 +315,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base-x" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" +checksum = "dc19a4937b4fbd3fe3379793130e42060d10627a360f2127802b10b87e7baf74" [[package]] name = "base64" @@ -349,9 +333,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "beef" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bed554bd50246729a1ec158d08aa3235d1b69d94ad120ebe187e28894787e736" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" [[package]] name = "bitflags" @@ -469,9 +453,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "byte-tools" @@ -528,7 +512,7 @@ dependencies = [ "num-integer", "num-traits", "serde", - "time 0.1.43", + "time 0.1.44", "winapi", ] @@ -558,16 +542,16 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.8" +version = "3.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c" +checksum = "d53da17d37dba964b9b3ecb5c5a1f193a2762c700e6829201e645b9381c99dc7" dependencies = [ "atty", "bitflags", "clap_derive", + "clap_lex", "indexmap", - "lazy_static", - "os_str_bytes", + "once_cell", "strsim 0.10.0", "termcolor", "textwrap 0.15.0", @@ -575,18 +559,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "3.1.1" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25" +checksum = "0f6ebaab5f25e4f0312dfa07cb30a755204b96e6531457c2cfdecfdf5f2adf40" dependencies = [ - "clap 3.1.8", + "clap 3.2.5", ] [[package]] name = "clap_derive" -version = "3.1.7" +version = "3.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" +checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9" dependencies = [ "heck 0.4.0", "proc-macro-error", @@ -595,6 +579,15 @@ dependencies = [ "syn", ] +[[package]] +name = "clap_lex" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5538cd660450ebeb4234cfecf8f2284b844ffc4c50531e66d584ad5b91293613" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "cloudabi" version = "0.0.3" @@ -619,9 +612,9 @@ dependencies = [ [[package]] name = "combine" -version = "4.6.3" +version = "4.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062" +checksum = "2a604e93b79d1808327a6fca85a6f2d69de66461e7620f5a4cbf5fb4d1d7c948" dependencies = [ "bytes", "memchr", @@ -715,12 +708,12 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "8ff1f980957787286a554052d03c7aee98d99cc32e09f6d45f0a814133c87978" dependencies = [ "cfg-if 1.0.0", - "lazy_static", + "once_cell", ] [[package]] @@ -877,13 +870,14 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.2.0" +version = "5.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8858831f7781322e539ea39e72449c46b059638250c14344fec8d0aa6e539c" +checksum = "3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f" dependencies = [ "cfg-if 1.0.0", - "num_cpus", - "parking_lot 0.12.0", + "hashbrown 0.12.1", + "lock_api", + "parking_lot_core 0.9.3", ] [[package]] @@ -1038,7 +1032,7 @@ name = "examples-checker" version = "0.0.0" dependencies = [ "anyhow", - "clap 3.1.8", + "clap 3.2.5", ] [[package]] @@ -1077,11 +1071,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "filedescriptor" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7199d965852c3bac31f779ef99cbb4537f80e952e2d6aa0ffeb30cce00f4f46e" +dependencies = [ + "libc", + "thiserror", + "winapi", +] + [[package]] name = "filetime" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" dependencies = [ "cfg-if 1.0.0", "libc", @@ -1103,11 +1108,11 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "forc" -version = "0.16.1" +version = "0.16.2" dependencies = [ "annotate-snippets", "anyhow", - "clap 3.1.8", + "clap 3.2.5", "clap_complete", "forc-pkg", "forc-util", @@ -1137,10 +1142,10 @@ dependencies = [ [[package]] name = "forc-explore" -version = "0.16.1" +version = "0.16.2" dependencies = [ "anyhow", - "clap 3.1.8", + "clap 3.2.5", "forc-util", "reqwest", "serde", @@ -1152,10 +1157,10 @@ dependencies = [ [[package]] name = "forc-fmt" -version = "0.16.1" +version = "0.16.2" dependencies = [ "anyhow", - "clap 3.1.8", + "clap 3.2.5", "forc-util", "prettydiff", "sway-core", @@ -1167,10 +1172,10 @@ dependencies = [ [[package]] name = "forc-fmt-v2" -version = "0.16.1" +version = "0.16.2" dependencies = [ "anyhow", - "clap 3.1.8", + "clap 3.2.5", "forc-util", "prettydiff", "sway-core", @@ -1182,31 +1187,32 @@ dependencies = [ [[package]] name = "forc-gm" -version = "0.16.1" +version = "0.16.2" dependencies = [ - "clap 3.1.8", + "clap 3.2.5", ] [[package]] name = "forc-lsp" -version = "0.16.1" +version = "0.16.2" dependencies = [ "anyhow", - "clap 3.1.8", + "clap 3.2.5", "sway-lsp", "tokio", ] [[package]] name = "forc-pkg" -version = "0.16.1" +version = "0.16.2" dependencies = [ "anyhow", "forc-util", + "fuel-tx", "fuels-types", "git2", "petgraph", - "semver 1.0.7", + "semver 1.0.10", "serde", "serde_ignored", "sway-core", @@ -1219,7 +1225,7 @@ dependencies = [ [[package]] name = "forc-util" -version = "0.16.1" +version = "0.16.2" dependencies = [ "annotate-snippets", "anyhow", @@ -1257,9 +1263,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "fuel-asm" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaa9ef12093772c88ddee15a214826527ad09fead79105f352d15ab4f271d5b5" +checksum = "16628e172a06a411c57972c55a67404f1684118be3bbca79148bf5a00fff48f0" dependencies = [ "fuel-types", "serde", @@ -1282,13 +1288,13 @@ dependencies = [ [[package]] name = "fuel-gql-client" -version = "0.8.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c0fee7db300cc83ba25d492ecef577730bf0857c51f383c10d26ef59037be9f" +checksum = "2185998563c770e718e9537b790d3cf2772d04f55a87e939f2aa6da87ab2443c" dependencies = [ "anyhow", "chrono", - "clap 3.1.8", + "clap 3.2.5", "cynic", "derive_more", "fuel-tx", @@ -1347,9 +1353,9 @@ checksum = "34b9161e86d434a93088409530a4f71f42e074b3bbcbb7a27bfe666583f92fd7" [[package]] name = "fuel-tx" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f76a720b4e32c6a51f39f609a472b9dcae35bc20a4ce9569601f3c24718b3ae" +checksum = "43dbfcd95f2b6fb19e6272832b5d6ecf14f8283c3329994baa38a4faed65d437" dependencies = [ "fuel-asm", "fuel-crypto", @@ -1372,9 +1378,9 @@ dependencies = [ [[package]] name = "fuel-vm" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a70dffe9faeb81f9d9d202eb26af4742980f884fa3109c169819ac6b2c51d3" +checksum = "e5700e457c2c6139a3b671014fa0a3bd57afb74de56abb118487b8d56ed21862" dependencies = [ "fuel-asm", "fuel-crypto", @@ -1507,6 +1513,16 @@ dependencies = [ "slab", ] +[[package]] +name = "gag" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a713bee13966e9fbffdf7193af71d54a6b35a0bb34997cd6c9519ebeb5005972" +dependencies = [ + "filedescriptor", + "tempfile", +] + [[package]] name = "generational-arena" version = "0.2.8" @@ -1535,15 +1551,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - [[package]] name = "getrandom" version = "0.1.16" @@ -1557,13 +1564,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -1578,9 +1585,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.14.2" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3826a6e0e2215d7a41c2bfc7c9244123969273f3476b939a226aac0ab56e9e3c" +checksum = "d0155506aab710a86160ddb504a480d2964d7ab5b9e62419be69e0032bc5931c" dependencies = [ "bitflags", "libc", @@ -1599,9 +1606,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "gloo-timers" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e" +checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" dependencies = [ "futures-channel", "futures-core", @@ -1634,22 +1641,22 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.7.1", + "tokio-util 0.7.3", "tracing", ] [[package]] name = "handlebars" -version = "4.2.2" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d6a30320f094710245150395bc763ad23128d6a1ebbad7594dc4164b62c56b" +checksum = "b66d0c1b6e3abfd1e72818798925e16e02ed77e1b47f6c25a95a23b377ee4299" dependencies = [ "log", "pest", "pest_derive", - "quick-error 2.0.1", "serde", "serde_json", + "thiserror", ] [[package]] @@ -1658,6 +1665,12 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +[[package]] +name = "hashbrown" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" + [[package]] name = "headers" version = "0.3.7" @@ -1735,20 +1748,20 @@ dependencies = [ [[package]] name = "http" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa 1.0.2", ] [[package]] name = "http-body" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", @@ -1757,9 +1770,9 @@ dependencies = [ [[package]] name = "http-client" -version = "6.5.1" +version = "6.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea880b03c18a7e981d7fb3608b8904a98425d53c440758fcebf7d934aa56547c" +checksum = "e023af341b797ce2c039f7c6e1d347b68d0f7fd0bc7ac234fe69cfadcca1f89a" dependencies = [ "async-h1", "async-std", @@ -1798,9 +1811,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" [[package]] name = "httpdate" @@ -1814,14 +1827,14 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" dependencies = [ - "quick-error 1.2.3", + "quick-error", ] [[package]] name = "hyper" -version = "0.14.18" +version = "0.14.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" +checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" dependencies = [ "bytes", "futures-channel", @@ -1832,7 +1845,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.1", + "itoa 1.0.2", "pin-project-lite", "socket2", "tokio", @@ -1849,7 +1862,7 @@ checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" dependencies = [ "http", "hyper", - "rustls 0.20.4", + "rustls 0.20.6", "tokio", "tokio-rustls", ] @@ -1873,12 +1886,12 @@ dependencies = [ [[package]] name = "im" -version = "15.0.0" +version = "15.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "111c1983f3c5bb72732df25cddacee9b546d08325fb584b5ebd38148be7b0246" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" dependencies = [ "bitmaps", - "rand_core 0.5.1", + "rand_core 0.6.3", "rand_xoshiro", "sized-chunks", "typenum", @@ -1887,12 +1900,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +checksum = "6c6392766afd7964e2531940894cffe4bd8d7d17dbc3c1c4857040fd4b33bdb3" dependencies = [ "autocfg 1.1.0", - "hashbrown", + "hashbrown 0.12.1", ] [[package]] @@ -1912,9 +1925,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c" +checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" [[package]] name = "itertools" @@ -1933,9 +1946,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] name = "jobserver" @@ -1948,9 +1961,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" dependencies = [ "wasm-bindgen", ] @@ -1968,9 +1981,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" [[package]] name = "kstring" @@ -2011,15 +2024,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] name = "libgit2-sys" -version = "0.13.2+1.4.2" +version = "0.13.4+1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a42de9a51a5c12e00fc0e4ca6bc2ea43582fc6418488e8f615e905d886f258b" +checksum = "d0fa6563431ede25f5cc7f6d803c6afbc1c5d3ad3d4925d12c882bf2b526f5d1" dependencies = [ "cc", "libc", @@ -2045,9 +2058,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.5" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f35facd4a5673cb5a48822be2be1d4236c1c99cb4113cab7061ac720d5bf859" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" dependencies = [ "cc", "libc", @@ -2067,9 +2080,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if 1.0.0", "value-bag", @@ -2077,18 +2090,18 @@ dependencies = [ [[package]] name = "logos" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427e2abca5be13136da9afdbf874e6b34ad9001dd70f2b103b083a85daa7b345" +checksum = "bf8b031682c67a8e3d5446840f9573eb7fe26efe7ec8d195c9ac4c0647c502f1" dependencies = [ "logos-derive", ] [[package]] name = "logos-derive" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56a7d287fd2ac3f75b11f19a1c8a874a7d55744bd91f7a1b3e7cf87d4343c36d" +checksum = "a1d849148dbaf9661a6151d1ca82b13bb4c4c128146a88d05253b38d4e2f496c" dependencies = [ "beef", "fnv", @@ -2096,7 +2109,6 @@ dependencies = [ "quote", "regex-syntax", "syn", - "utf8-ranges", ] [[package]] @@ -2135,13 +2147,14 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "mdbook" -version = "0.4.15" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241f10687eb3b4e0634b3b4e423f97c5f1efbd69dc9522e24a8b94583eeec3c6" +checksum = "74612ae81a3e5ee509854049dfa4c7975ae033c06f5fc4735c7dfbe60ee2a39d" dependencies = [ "anyhow", "chrono", - "clap 2.34.0", + "clap 3.2.5", + "clap_complete", "env_logger", "handlebars", "lazy_static", @@ -2164,9 +2177,9 @@ name = "mdbook-forc-documenter" version = "0.0.0" dependencies = [ "anyhow", - "clap 3.1.8", + "clap 3.2.5", "mdbook", - "semver 1.0.7", + "semver 1.0.10", "serde", "serde_json", "toml", @@ -2174,9 +2187,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" @@ -2205,25 +2218,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" dependencies = [ "libc", "log", - "miow", - "ntapi", "wasi 0.11.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", + "windows-sys", ] [[package]] @@ -2237,7 +2239,7 @@ dependencies = [ "log", "mime", "mime_guess", - "quick-error 1.2.3", + "quick-error", "rand 0.8.5", "safemem", "tempfile", @@ -2255,15 +2257,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "ntapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" -dependencies = [ - "winapi", -] - [[package]] name = "num-bigint" version = "0.4.3" @@ -2277,9 +2270,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg 1.1.0", "num-traits", @@ -2287,9 +2280,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg 1.1.0", ] @@ -2306,9 +2299,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" [[package]] name = "opaque-debug" @@ -2349,9 +2342,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.72" +version = "0.9.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" dependencies = [ "autocfg 1.1.0", "cc", @@ -2363,12 +2356,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.0.0" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" -dependencies = [ - "memchr", -] +checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" [[package]] name = "owo-colors" @@ -2393,16 +2383,6 @@ dependencies = [ "parking_lot_core 0.8.5", ] -[[package]] -name = "parking_lot" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.2", -] - [[package]] name = "parking_lot_core" version = "0.8.5" @@ -2419,9 +2399,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" dependencies = [ "cfg-if 1.0.0", "libc", @@ -2508,9 +2488,9 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" +checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" dependencies = [ "fixedbitset", "indexmap", @@ -2518,6 +2498,50 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_macros", + "phf_shared", + "proc-macro-hack", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.0.10" @@ -2540,9 +2564,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -2643,11 +2667,11 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.37" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -2657,7 +2681,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6" dependencies = [ "bitflags", - "getopts", "memchr", "unicase", ] @@ -2668,12 +2691,6 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - [[package]] name = "quote" version = "1.0.18" @@ -2786,7 +2803,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", ] [[package]] @@ -2862,11 +2879,11 @@ dependencies = [ [[package]] name = "rand_xoshiro" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" dependencies = [ - "rand_core 0.5.1", + "rand_core 0.6.3", ] [[package]] @@ -2910,16 +2927,16 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", "redox_syscall 0.2.13", "thiserror", ] [[package]] name = "regex" -version = "1.5.5" +version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" dependencies = [ "aho-corasick", "memchr", @@ -2937,9 +2954,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" [[package]] name = "remove_dir_all" @@ -2952,9 +2969,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.10" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" +checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" dependencies = [ "base64 0.13.0", "bytes", @@ -2973,13 +2990,14 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rustls 0.20.4", + "rustls 0.20.6", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-rustls", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -3005,9 +3023,9 @@ dependencies = [ [[package]] name = "ropey" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0dd9b26e2a102b33d400b7b7d196c81a4014eb96eda90b1c5b48d7215d9633" +checksum = "bbd22239fafefc42138ca5da064f3c17726a80d2379d817a3521240e78dd0064" dependencies = [ "smallvec", "str_indices", @@ -3020,7 +3038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f77412a3d1f26af0c0783c23b3555a301b1a49805cba7bf9a7827a9e9e285f0" dependencies = [ "countme", - "hashbrown", + "hashbrown 0.11.2", "memoffset", "rustc-hash", "text-size", @@ -3059,7 +3077,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.7", + "semver 1.0.10", ] [[package]] @@ -3077,9 +3095,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.4" +version = "0.20.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" dependencies = [ "log", "ring", @@ -3089,18 +3107,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "0.3.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360" +checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" dependencies = [ "base64 0.13.0", ] [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" [[package]] name = "safemem" @@ -3205,9 +3223,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.7" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4" +checksum = "a41d061efea015927ac527063765e73601444cdc344ba855bc7bd44578b25e1c" dependencies = [ "serde", ] @@ -3220,18 +3238,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -3240,20 +3258,20 @@ dependencies = [ [[package]] name = "serde_ignored" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c2c7d39d14f2f2ea82239de71594782f186fd03501ac81f0ce08e674819ff2f" +checksum = "1940036ca2411651a40012009d062087dfe62817b2191a03750fb569e11fa633" dependencies = [ "serde", ] [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ - "itoa 1.0.1", + "itoa 1.0.2", "ryu", "serde", ] @@ -3271,9 +3289,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5" +checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed" dependencies = [ "proc-macro2", "quote", @@ -3287,7 +3305,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.1", + "itoa 1.0.2", "ryu", "serde", ] @@ -3422,6 +3440,12 @@ dependencies = [ "event-listener", ] +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + [[package]] name = "sized-chunks" version = "0.6.5" @@ -3526,9 +3550,9 @@ checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" [[package]] name = "str_indices" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfad63a1b47951101cd667a85b2959a62910cf03f814fff25df89c460b873f8" +checksum = "9d9199fa80c817e074620be84374a520062ebac833f358d74b37060ce4a0f2c0" [[package]] name = "strsim" @@ -3600,7 +3624,7 @@ dependencies = [ "async-trait", "cfg-if 1.0.0", "futures-util", - "getrandom 0.2.6", + "getrandom 0.2.7", "http-client", "http-types", "log", @@ -3614,14 +3638,15 @@ dependencies = [ [[package]] name = "sway-core" -version = "0.16.1" +version = "0.16.2" dependencies = [ - "clap 3.1.8", + "clap 3.2.5", "derivative", "dirs 3.0.2", "either", "fuel-asm", "fuel-crypto", + "fuel-tx", "fuel-types", "fuel-vm", "fuels-types", @@ -3646,7 +3671,7 @@ dependencies = [ [[package]] name = "sway-fmt" -version = "0.16.1" +version = "0.16.2" dependencies = [ "ropey", "sway-core", @@ -3655,7 +3680,7 @@ dependencies = [ [[package]] name = "sway-fmt-v2" -version = "0.16.1" +version = "0.16.2" dependencies = [ "anyhow", "forc-util", @@ -3670,7 +3695,7 @@ dependencies = [ [[package]] name = "sway-ir" -version = "0.16.1" +version = "0.16.2" dependencies = [ "filecheck", "generational-arena", @@ -3681,10 +3706,12 @@ dependencies = [ [[package]] name = "sway-lsp" -version = "0.16.1" +version = "0.16.2" dependencies = [ "async-trait", - "dashmap 4.0.2", + "dashmap 5.3.4", + "forc", + "forc-pkg", "forc-util", "futures", "ropey", @@ -3701,11 +3728,12 @@ dependencies = [ [[package]] name = "sway-parse" -version = "0.16.1" +version = "0.16.2" dependencies = [ "extension-trait", "num-bigint", "num-traits", + "phf", "sway-types", "thiserror", "unicode-xid", @@ -3713,7 +3741,7 @@ dependencies = [ [[package]] name = "sway-types" -version = "0.16.1" +version = "0.16.2" dependencies = [ "fuel-asm", "fuel-crypto", @@ -3724,17 +3752,17 @@ dependencies = [ [[package]] name = "sway-utils" -version = "0.16.1" +version = "0.16.2" [[package]] name = "syn" -version = "1.0.91" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" +checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -3748,7 +3776,7 @@ dependencies = [ "logos", "regex", "rowan", - "semver 1.0.7", + "semver 1.0.10", "smallvec", "toml", "wasm-bindgen", @@ -3815,16 +3843,19 @@ name = "test" version = "0.0.0" dependencies = [ "anyhow", - "assert_matches", + "filecheck", "forc", + "forc-pkg", "forc-util", "fuel-asm", "fuel-tx", "fuel-vm", + "gag", "rand 0.8.5", "regex", "serde_json", "tokio", + "toml", "tracing", ] @@ -3866,18 +3897,18 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ "proc-macro2", "quote", @@ -3895,11 +3926,12 @@ dependencies = [ [[package]] name = "time" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi", ] @@ -3943,9 +3975,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -3958,9 +3990,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.17.0" +version = "1.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" dependencies = [ "bytes", "libc", @@ -3977,9 +4009,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", @@ -3988,20 +4020,20 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.3" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4151fda0cf2798550ad0b34bcfc9b9dcc2a9d2471c895c68f3a8818e54f2389e" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ - "rustls 0.20.4", + "rustls 0.20.6", "tokio", "webpki 0.22.0", ] [[package]] name = "tokio-stream" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" dependencies = [ "futures-core", "pin-project-lite", @@ -4023,9 +4055,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ "bytes", "futures-core", @@ -4037,9 +4069,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" dependencies = [ "bytes", "futures-core", @@ -4051,9 +4083,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] @@ -4064,7 +4096,7 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "744e9ed5b352340aa47ce033716991b5589e23781acb97cad37d4ea70560f55b" dependencies = [ - "combine 4.6.3", + "combine 4.6.4", "indexmap", "itertools", "kstring", @@ -4078,9 +4110,9 @@ checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c" [[package]] name = "tower" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", @@ -4105,7 +4137,7 @@ dependencies = [ "async-trait", "auto_impl", "bytes", - "dashmap 5.2.0", + "dashmap 5.3.4", "futures", "httparse", "log", @@ -4114,7 +4146,7 @@ dependencies = [ "serde", "serde_json", "tokio", - "tokio-util 0.7.1", + "tokio-util 0.7.3", "tower", "tower-lsp-macros", ] @@ -4132,15 +4164,15 @@ dependencies = [ [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.33" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80b9fa4360528139bc96100c160b7ae879f5567f49f1782b0b02035b0358ebf3" +checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ "cfg-if 1.0.0", "log", @@ -4151,9 +4183,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" dependencies = [ "proc-macro2", "quote", @@ -4162,11 +4194,11 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee" +checksum = "7709595b8878a4965ce5e87ebf880a7d39c9afc6837721b21a5a816a8117d921" dependencies = [ - "lazy_static", + "once_cell", "valuable", ] @@ -4281,9 +4313,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" [[package]] name = "unicode-normalization" @@ -4308,9 +4346,9 @@ checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" [[package]] name = "universal-hash" @@ -4356,12 +4394,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf8-ranges" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" - [[package]] name = "uwuify" version = "0.2.2" @@ -4370,7 +4402,7 @@ checksum = "3db6840b7adcfd2e866c79157cc890ecdbbc1f739607134039ae64eaa6c07e24" dependencies = [ "clap 2.34.0", "owo-colors", - "parking_lot 0.11.2", + "parking_lot", "thiserror", ] @@ -4382,9 +4414,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.0.0-alpha.8" +version = "1.0.0-alpha.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f" +checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" dependencies = [ "ctor", "version_check", @@ -4466,7 +4498,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-tungstenite", - "tokio-util 0.6.9", + "tokio-util 0.6.10", "tower-service", "tracing", ] @@ -4479,9 +4511,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasi" @@ -4491,9 +4523,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" dependencies = [ "cfg-if 1.0.0", "serde", @@ -4503,9 +4535,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" dependencies = [ "bumpalo", "lazy_static", @@ -4518,9 +4550,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.30" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -4530,9 +4562,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4540,9 +4572,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" dependencies = [ "proc-macro2", "quote", @@ -4553,15 +4585,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" dependencies = [ "js-sys", "wasm-bindgen", @@ -4657,9 +4689,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ "windows_aarch64_msvc", "windows_i686_gnu", @@ -4670,33 +4702,33 @@ dependencies = [ [[package]] name = "windows_aarch64_msvc" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" [[package]] name = "windows_i686_gnu" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" [[package]] name = "windows_i686_msvc" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" [[package]] name = "windows_x86_64_gnu" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" [[package]] name = "windows_x86_64_msvc" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" [[package]] name = "winreg" @@ -4709,9 +4741,9 @@ dependencies = [ [[package]] name = "xattr" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" dependencies = [ "libc", ] diff --git a/README.md b/README.md index 2e5016b1cef..3e80e4d2153 100644 --- a/README.md +++ b/README.md @@ -49,4 +49,4 @@ cargo run --bin forc -- --help We welcome contributions to Sway! -Please see the [Contributing To Sway](https://fuellabs.github.io/sway/latest/reference/contributing_to_sway.html) section of the Sway book for guidelines and instructions to help you get started. +Please see the [Contributing To Sway](https://fuellabs.github.io/sway/master/reference/contributing_to_sway.html) section of the Sway book for guidelines and instructions to help you get started. diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 1b563884e9b..7398a95bd9b 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -56,6 +56,7 @@ - [Commands](./forc/commands/index.md) - [forc addr2line](./forc/commands/forc_addr2line.md) - [forc build](./forc/commands/forc_build.md) + - [forc check](./forc/commands/forc_check.md) - [forc clean](./forc/commands/forc_clean.md) - [forc completions](./forc/commands/forc_completions.md) - [forc deploy](./forc/commands/forc_deploy.md) diff --git a/docs/src/basics/blockchain_types.md b/docs/src/basics/blockchain_types.md index 0a17b542d49..bfbb0d59e88 100644 --- a/docs/src/basics/blockchain_types.md +++ b/docs/src/basics/blockchain_types.md @@ -43,3 +43,35 @@ let my_number: b256 = 0x00000000000000000000000000000000000000000000000000000000 let my_contract_id: ContractId = ~ContractId::from(my_number); let forty_two: b256 = my_contract_id.into(); ``` + +## `Identity` Type + +The `Identity` type is an enum that allows for the handling of both `Address` and `ContractId` types. This is useful in cases where either type is accepted, e.g. receiving funds from an identified sender, but not caring if the sender is an address or a contract. + +An `Identity` is implemented as follows. + +```sway +{{#include ../../../sway-lib-std/src/identity.sw:docs_identity}} +``` + +Casting to an `Identity` must be done explicitly: + +```sway +{{#include ../../../examples/identity/src/main.sw:cast_to_identity}} +``` + +A `match` statement can be used to return to an `Address` or `ContractId` as well as handle cases in which their execution differs. + +```sway +{{#include ../../../examples/identity/src/main.sw:identity_to_contract_id}} +``` + +```sway +{{#include ../../../examples/identity/src/main.sw:different_executions}} +``` + +A common use case for `Identity` is for access control. The use of `Identity` uniquely allows both `ContractId` and `Address` to have access control inclusively. + +```sway +{{#include ../../../examples/identity/src/main.sw:access_control_with_identity}} +``` diff --git a/docs/src/forc/commands/forc_check.md b/docs/src/forc/commands/forc_check.md new file mode 100644 index 00000000000..49f24c6bc70 --- /dev/null +++ b/docs/src/forc/commands/forc_check.md @@ -0,0 +1 @@ +# forc check diff --git a/docs/src/forc/manifest_reference.md b/docs/src/forc/manifest_reference.md index 30d2120aefa..47e0f20716a 100644 --- a/docs/src/forc/manifest_reference.md +++ b/docs/src/forc/manifest_reference.md @@ -17,6 +17,8 @@ The `Forc.toml` (the _manifest_ file) is a compulsory file for each package and * [`[build-profiles]`](#the-build-profiles--section) - Defines the build profiles. +* [`[patch]`](#the-patch-section) - Defines the patches. + ## The `[project]` section An example `Forc.toml` is shown below. Under `[project]` the following fields are optional: @@ -99,3 +101,47 @@ Note that providing the corresponding cli options (like `--print-finalized-asm`) * print-intermediate-asm - false * print-ir - false * silent - false + +## The `[patch]` section + +The [patch] section of `Forc.toml` can be used to override dependencies with other copies. The example provided below patches source with master branch of the same repo. + +```toml +[project] +authors = ["user"] +entry = "main.sw" +organization = "Fuel_Labs" +license = "Apache-2.0" +name = "wallet_contract" + +[dependencies] + +[patch.'https://github.com/fuellabs/sway'] +std = { git = "https://github.com/fuellabs/sway", branch = "test" } +``` + +In the example above, `std` is patched with the `test` branch from `std` repo. You can also patch git dependencies with dependencies defined with a path. + +```toml +[patch.'https://github.com/fuellabs/sway'] +std = { path = "/path/to/local_std_version" } +``` + +Just like `std` or `core` you can also patch dependencies you declared with a git repo. + +```toml +[project] +authors = ["user"] +entry = "main.sw" +organization = "Fuel_Labs" +license = "Apache-2.0" +name = "wallet_contract" + +[dependencies] +foo = { git = "https://github.com/foo/foo", branch = "master" } + +[patch.'https://github.com/foo'] +foo = { git = "https://github.com/foo/foo", branch = "test" } +``` + +Note that each key after the `[patch]` is a URL of the source that is being patched. diff --git a/docs/src/introduction/installation.md b/docs/src/introduction/installation.md index 8debcf7c659..31605a41d78 100644 --- a/docs/src/introduction/installation.md +++ b/docs/src/introduction/installation.md @@ -12,24 +12,26 @@ Start by installing `fuelup` with: ```sh curl --proto '=https' --tlsv1.2 -sSf \ - https://fuellabs.github.io/fuelup/fuelup-init.sh | sh -s install + https://fuellabs.github.io/fuelup/fuelup-init.sh | sh ``` -You may need to add `~/.fuelup/bin` to your PATH. For Bash: +`fuelup-init` will ask for permission to add `~/.fuelup/bin` to your PATH. Otherwise, you can also pass `--no-modify-path` so that `fuelup-init` does not modify your PATH: ```sh -export PATH="${HOME}/.fuelup/bin/:${PATH}" +curl --proto '=https' --tlsv1.2 -sSf \ + https://fuellabs.github.io/fuelup/fuelup-init.sh | sh -s -- --no-modify-path ``` -Then run +Once `fuelup` is installed, `fuelup-init` automatically runs the command below ```sh -fuelup install +fuelup toolchain install latest ``` -to install the latest Sway toolchain. +to install the latest Sway toolchain. + +You can run the same command at a later time to update the toolchain. -> **Note**: A `curl: (22) The requested URL returned error: 404` error when running any of the steps above is most likely an indication that a new release was published but binaries were not yet uploaded by CI. See: . Simply re-try the commands after binaries are uploaded. ## Installing from Source diff --git a/docs/src/reference/known_issues_and_workarounds.md b/docs/src/reference/known_issues_and_workarounds.md index 47d0ad399ee..741c8159875 100644 --- a/docs/src/reference/known_issues_and_workarounds.md +++ b/docs/src/reference/known_issues_and_workarounds.md @@ -2,11 +2,7 @@ ## Known Issues -* [#1663](https://github.com/FuelLabs/sway/issues/1663): Using an explicit `return` in all branches of an `if let` expression causes a compile error. The workaround is to use implicit returns instead. - -* [#1387](https://github.com/FuelLabs/sway/issues/1387): In order to use `unwrap()` from the `result` library, all symbols of `result` needs to be imported via `use::result::*;`. - -* [#870](https://github.com/FuelLabs/sway/issues/870): All `impl` blocks need to be defined before any of the functions they define can be called. +* [#870](https://github.com/FuelLabs/sway/issues/870): All `impl` blocks need to be defined before any of the functions they define can be called. This includes sibling functions in the same `impl` declaration, i.e., functions in an `impl` can't call each other yet. ## Missing Features @@ -14,7 +10,9 @@ * [#428](https://github.com/FuelLabs/sway/issues/428): Arrays are currently immutable which means that changing elements of an array once initialized is not yet possible. -* [#1077](https://github.com/FuelLabs/sway/issues/1077): Dynamic vectors, i.e. `Vec`, have not yet been implemented. +* [#2035](https://github.com/FuelLabs/sway/issues/2035): Dynamic vectors _in storage_ have not yet been implemented. Only [vectors in memory](https://github.com/FuelLabs/sway/blob/master/sway-lib-std/src/vec.sw) are available at the moment. + +* [#1188](https://github.com/FuelLabs/sway/issues/1188): Mutable function arguments are not yet allowed except for `self`. ## General diff --git a/docs/theme/highlight.js b/docs/theme/highlight.js index 54196c7cedd..b4285d3ebe8 100644 --- a/docs/theme/highlight.js +++ b/docs/theme/highlight.js @@ -303,7 +303,7 @@ anyNumberOfTimes:g};for(const e in A)"object"==typeof A[e]&&n(A[e]) grmr_sway:e=>{const t={className:"title.function.invoke",relevance:0, begin:b(/\b/,/(?!let\b)/,e.IDENT_RE,u(/\s*\(/))},n="([u](8|16|32|64))?";return{ name:"Sway",aliases:["sw"],keywords:{$pattern:e.IDENT_RE+"!?", -keyword:["abi","as","asm","const","contract","deref","enum","fn","if","impl","let","library","match","mut","else","predicate","ref","return","script","Self","self","str","struct","trait","use","where","while"], +keyword:["abi","as","asm","const","contract","deref","enum","fn","if","impl","let","library","match","mut","else","predicate","ref","return","script","Self","self","storage","str","struct","trait","use","where","while"], literal:["true","false"], built_in:["bool","char","u8","u16","u32","u64","b256","str","Self"]}, illegal:""] +entry = "main.sw" +license = "Apache-2.0" +name = "identity" + +[dependencies] +std = { path = "../../sway-lib-std" } diff --git a/examples/identity/src/abi.sw b/examples/identity/src/abi.sw new file mode 100644 index 00000000000..0f54e4428f5 --- /dev/null +++ b/examples/identity/src/abi.sw @@ -0,0 +1,10 @@ +library r#abi; + +use std::identity::Identity; + +abi IdentityExample { + #[storage(read)]fn access_control_with_identity(); + fn cast_to_identity(); + fn different_executions(my_identity: Identity); + fn identity_to_contract_id(my_identity: Identity); +} diff --git a/examples/identity/src/errors.sw b/examples/identity/src/errors.sw new file mode 100644 index 00000000000..a730411d47e --- /dev/null +++ b/examples/identity/src/errors.sw @@ -0,0 +1,5 @@ +library errors; + +pub enum MyError { + UnauthorizedUser: (), +} diff --git a/examples/identity/src/main.sw b/examples/identity/src/main.sw new file mode 100644 index 00000000000..e48827aa469 --- /dev/null +++ b/examples/identity/src/main.sw @@ -0,0 +1,68 @@ +contract; + +dep r#abi; +dep errors; + +use r#abi::IdentityExample; +use errors::MyError; + +use std::{ + address::Address, + assert::require, + chain::auth::{AuthError, msg_sender}, + constants::BASE_ASSET_ID, + contract_id::ContractId, + identity::*, + result::*, + revert::revert, + token::{force_transfer_to_contract, transfer_to_output} +}; + +storage { + owner: Identity, +} + +impl IdentityExample for Contract { + fn cast_to_identity() { + // ANCHOR: cast_to_identity + let raw_address: b256 = 0xddec0e7e6a9a4a4e3e57d08d080d71a299c628a46bc609aab4627695679421ca; + let my_identity: Identity = Identity::Address(~Address::from(raw_address)); + // ANCHOR_END: cast_to_identity + } + + fn identity_to_contract_id(my_identity: Identity) { + // ANCHOR: identity_to_contract_id + let my_contract_id: ContractId = match my_identity { + Identity::ContractId(identity) => { + identity + }, + _ => { + revert(0); + } + }; + // ANCHOR_END: identity_to_contract_ids + } + + fn different_executions(my_identity: Identity) { + let amount = 1; + let token_id = BASE_ASSET_ID; + + // ANCHOR: different_executions + match my_identity { + Identity::Address(identity) => { + transfer_to_output(amount, token_id, identity); + }, + Identity::ContractId(identity) => { + force_transfer_to_contract(amount, token_id, identity); + }, + }; + // ANCHOR_END: different_executions + } + + #[storage(read)]fn access_control_with_identity() { + // ANCHOR: access_control_with_identity + let sender: Result = msg_sender(); + require(sender.unwrap() == storage.owner, MyError::UnauthorizedUser); + // ANCHOR_END: access_control_with_identity + } +} diff --git a/examples/storage_map/src/main.sw b/examples/storage_map/src/main.sw index 75bb617cab3..2a8f538e30f 100644 --- a/examples/storage_map/src/main.sw +++ b/examples/storage_map/src/main.sw @@ -16,11 +16,11 @@ storage { abi StorageMapExample { #[storage(write)]fn insert_into_map1(key: u64, value: u64); - #[storage(write)]fn get_from_map1(key: u64, value: u64); + #[storage(read)]fn get_from_map1(key: u64, value: u64) -> u64; - #[storage(read)]fn insert_into_map2(key: (b256, bool), value: Data); + #[storage(write)]fn insert_into_map2(key: (b256, bool), value: Data); - #[storage(read)]fn get_from_map2(key: (b256, bool), value: Data); + #[storage(read)]fn get_from_map2(key: (b256, bool), value: Data) -> Data; } impl StorageMapExample for Contract { @@ -28,15 +28,15 @@ impl StorageMapExample for Contract { storage.map1.insert(key, value); } - #[storage(write)]fn get_from_map1(key: u64, value: u64) { - storage.map1.insert(key, value); + #[storage(read)]fn get_from_map1(key: u64, value: u64) -> u64 { + storage.map1.get(key) } - #[storage(read)]fn insert_into_map2(key: (b256, bool), value: Data) { - storage.map2.get(key); + #[storage(write)]fn insert_into_map2(key: (b256, bool), value: Data) { + storage.map2.insert(key, value); } - #[storage(read)]fn get_from_map2(key: (b256, bool), value: Data) { - storage.map2.get(key); + #[storage(read)]fn get_from_map2(key: (b256, bool), value: Data) -> Data { + storage.map2.get(key) } } diff --git a/examples/wallet_smart_contract/src/main.sw b/examples/wallet_smart_contract/src/main.sw index c3a6a290bb6..a12018ca526 100644 --- a/examples/wallet_smart_contract/src/main.sw +++ b/examples/wallet_smart_contract/src/main.sw @@ -26,8 +26,8 @@ abi Wallet { impl Wallet for Contract { #[storage(read, write)]fn receive_funds() { - if msg_asset_id() == ~ContractId::from(BASE_ASSET_ID) { - // If we received `NATIVE_ASSET_ID` then keep track of the balance. + if msg_asset_id() == BASE_ASSET_ID { + // If we received `BASE_ASSET_ID` then keep track of the balance. // Otherwise, we're receiving other native assets and don't care // about our balance of tokens. storage.balance = storage.balance + msg_amount(); @@ -54,6 +54,6 @@ impl Wallet for Contract { // Note: `transfer_to_output()` is not a call and thus not an // interaction. Regardless, this code conforms to // checks-effects-interactions to avoid re-entrancy. - transfer_to_output(amount_to_send, ~ContractId::from(BASE_ASSET_ID), recipient_address); + transfer_to_output(amount_to_send, BASE_ASSET_ID, recipient_address); } } diff --git a/forc-gm/Cargo.toml b/forc-gm/Cargo.toml index 6f6face4ff6..a715bb90274 100644 --- a/forc-gm/Cargo.toml +++ b/forc-gm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-gm" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" diff --git a/forc-pkg/Cargo.toml b/forc-pkg/Cargo.toml index 44d35dfb952..07ee117b2bd 100644 --- a/forc-pkg/Cargo.toml +++ b/forc-pkg/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-pkg" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -10,15 +10,16 @@ description = "Building, locking, fetching and updating Sway projects as Forc pa [dependencies] anyhow = "1" -forc-util = { version = "0.16.1", path = "../forc-util" } +forc-util = { version = "0.16.2", path = "../forc-util" } +fuel-tx = "0.13" fuels-types = "0.12" git2 = { version = "0.14", features = ["vendored-libgit2", "vendored-openssl"] } petgraph = { version = "0.6", features = ["serde-1"] } semver = { version = "1.0", features = ["serde"] } serde = { version = "1.0", features = ["derive"] } serde_ignored = "0.1" -sway-core = { version = "0.16.1", path = "../sway-core" } -sway-utils = { version = "0.16.1", path = "../sway-utils" } +sway-core = { version = "0.16.2", path = "../sway-core" } +sway-utils = { version = "0.16.2", path = "../sway-utils" } toml = "0.5" tracing = "0.1" url = { version = "2.2", features = ["serde"] } diff --git a/forc-pkg/src/lib.rs b/forc-pkg/src/lib.rs index 80afe2b5af3..0282d485e27 100644 --- a/forc-pkg/src/lib.rs +++ b/forc-pkg/src/lib.rs @@ -9,6 +9,9 @@ pub mod manifest; mod pkg; pub use lock::Lock; -pub use manifest::{Manifest, ManifestFile}; +pub use manifest::{BuildProfile, Manifest, ManifestFile}; #[doc(inline)] pub use pkg::*; + +const CORE: &str = "core"; +const STD: &str = "std"; diff --git a/forc-pkg/src/manifest.rs b/forc-pkg/src/manifest.rs index 61bdeaab19e..3ef4bd0715c 100644 --- a/forc-pkg/src/manifest.rs +++ b/forc-pkg/src/manifest.rs @@ -1,7 +1,4 @@ -use crate::{ - pkg::{manifest_file_missing, parsing_failed, wrong_program_type}, - BuildConfig, -}; +use crate::pkg::{manifest_file_missing, parsing_failed, wrong_program_type}; use anyhow::{anyhow, bail, Result}; use forc_util::{find_manifest_dir, println_yellow_err, validate_name}; use serde::{Deserialize, Serialize}; @@ -14,6 +11,8 @@ use std::{ use sway_core::{parse, TreeType}; use sway_utils::constants; +type PatchMap = BTreeMap; + /// A [Manifest] that was deserialized from a file at a particular path. #[derive(Debug)] pub struct ManifestFile { @@ -30,7 +29,8 @@ pub struct Manifest { pub project: Project, pub network: Option, pub dependencies: Option>, - pub build_profile: Option>, + pub patch: Option>, + build_profile: Option>, } #[derive(Serialize, Deserialize, Debug)] @@ -76,6 +76,17 @@ pub struct DependencyDetails { pub(crate) rev: Option, } +/// Parameters to pass through to the `sway_core::BuildConfig` during compilation. +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "kebab-case")] +pub struct BuildProfile { + pub print_ir: bool, + pub print_finalized_asm: bool, + pub print_intermediate_asm: bool, + pub silent: bool, + pub time_phases: bool, +} + impl Dependency { /// The string of the `package` field if specified. pub fn package(&self) -> Option<&str> { @@ -182,6 +193,13 @@ impl ManifestFile { Ok(()) } } + + /// Access the build profile associated with the given profile name. + pub fn build_profile(&self, profile_name: &str) -> Option<&BuildProfile> { + self.build_profile + .as_ref() + .and_then(|profiles| profiles.get(profile_name)) + } } impl Manifest { @@ -241,7 +259,7 @@ impl Manifest { } /// Produce an iterator yielding all listed build profiles. - pub fn build_profiles(&self) -> impl Iterator { + pub fn build_profiles(&self) -> impl Iterator { self.build_profile .as_ref() .into_iter() @@ -256,6 +274,14 @@ impl Manifest { }) } + /// Produce an iterator yielding all listed patches. + pub fn patches(&self) -> impl Iterator { + self.patch + .as_ref() + .into_iter() + .flat_map(|patches| patches.iter()) + } + /// Check for the `core` and `std` packages under `[dependencies]`. If both are missing, add /// `std` implicitly. /// @@ -265,8 +291,7 @@ impl Manifest { /// Note: If only `core` is specified, we are unable to implicitly add `std` as we cannot /// guarantee that the user's `core` is compatible with the implicit `std`. fn implicitly_include_std_if_missing(&mut self, sway_git_tag: &str) { - const CORE: &str = "core"; - const STD: &str = "std"; + use crate::{CORE, STD}; // Don't include `std` if: // - this *is* `core` or `std`. // - either `core` or `std` packages are already specified. @@ -291,32 +316,13 @@ impl Manifest { /// If they are provided, use the provided `debug` or `release` so that they override the default `debug` /// and `release`. fn implicitly_include_default_build_profiles_if_missing(&mut self) { - const DEBUG: &str = "debug"; - const RELEASE: &str = "release"; - let build_profiles = self.build_profile.get_or_insert_with(Default::default); - if build_profiles.get(DEBUG).is_none() { - build_profiles.insert( - DEBUG.to_string(), - BuildConfig { - print_ir: false, - print_finalized_asm: false, - print_intermediate_asm: false, - silent: false, - }, - ); + if build_profiles.get(BuildProfile::DEBUG).is_none() { + build_profiles.insert(BuildProfile::DEBUG.into(), BuildProfile::debug()); } - if build_profiles.get(RELEASE).is_none() { - build_profiles.insert( - RELEASE.to_string(), - BuildConfig { - print_ir: false, - print_finalized_asm: false, - print_intermediate_asm: false, - silent: false, - }, - ); + if build_profiles.get(BuildProfile::RELEASE).is_none() { + build_profiles.insert(BuildProfile::RELEASE.into(), BuildProfile::release()); } } @@ -341,6 +347,32 @@ impl Manifest { } } +impl BuildProfile { + pub const DEBUG: &'static str = "debug"; + pub const RELEASE: &'static str = "release"; + pub const DEFAULT: &'static str = Self::DEBUG; + + pub fn debug() -> Self { + Self { + print_ir: false, + print_finalized_asm: false, + print_intermediate_asm: false, + silent: false, + time_phases: false, + } + } + + pub fn release() -> Self { + Self { + print_ir: false, + print_finalized_asm: false, + print_intermediate_asm: false, + silent: false, + time_phases: false, + } + } +} + impl std::ops::Deref for ManifestFile { type Target = Manifest; fn deref(&self) -> &Self::Target { @@ -348,6 +380,12 @@ impl std::ops::Deref for ManifestFile { } } +impl Default for BuildProfile { + fn default() -> Self { + Self::debug() + } +} + /// The definition for the implicit `std` dependency. fn implicit_std_dep(sway_git_tag: String) -> Dependency { const SWAY_GIT_REPO_URL: &str = "https://github.com/fuellabs/sway"; diff --git a/forc-pkg/src/pkg.rs b/forc-pkg/src/pkg.rs index f77ebdbc60d..0d46b0fb61c 100644 --- a/forc-pkg/src/pkg.rs +++ b/forc-pkg/src/pkg.rs @@ -1,12 +1,14 @@ use crate::{ lock::Lock, - manifest::{Dependency, Manifest, ManifestFile}, + manifest::{BuildProfile, Dependency, Manifest, ManifestFile}, + CORE, STD, }; use anyhow::{anyhow, bail, Context, Error, Result}; use forc_util::{ find_file_name, git_checkouts_directory, kebab_to_snake_case, print_on_failure, print_on_success, print_on_success_library, println_yellow_err, }; +use fuel_tx::StorageSlot; use fuels_types::JsonABI; use petgraph::{ self, @@ -15,8 +17,8 @@ use petgraph::{ }; use serde::{Deserialize, Serialize}; use std::{ - collections::{hash_map, BTreeSet, HashMap, HashSet}, - fmt, + collections::{hash_map, BTreeSet, HashMap}, + fmt, fs, hash::{Hash, Hasher}, path::{Path, PathBuf}, str::FromStr, @@ -45,6 +47,7 @@ pub struct PinnedId(u64); /// The result of successfully compiling a package. pub struct Compiled { pub json_abi: JsonABI, + pub storage_slots: Vec, pub bytecode: Vec, pub tree_type: TreeType, } @@ -166,16 +169,6 @@ pub struct BuildPlan { compilation_order: Vec, } -/// Parameters to pass through to the `sway_core::BuildConfig` during compilation. -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all = "kebab-case")] -pub struct BuildConfig { - pub print_ir: bool, - pub print_finalized_asm: bool, - pub print_intermediate_asm: bool, - pub silent: bool, -} - /// Error returned upon failed parsing of `PinnedId::from_str`. #[derive(Clone, Debug)] pub struct PinnedIdParseError; @@ -235,6 +228,71 @@ impl BuildPlan { }) } + /// Create a new build plan taking into account the state of both the Manifest and the existing lock file if there is one. + /// + /// This will first attempt to load a build plan from the lock file and validate the resulting graph using the current state of the Manifest. + /// + /// This includes checking if the [dependencies] or [patch] tables have changed and checking the validity of the local path dependencies. + /// If any changes are detected, the graph is updated and any new packages that require fetching are fetched. + /// + /// The resulting build plan should always be in a valid state that is ready for building or checking. + pub fn load_from_manifest( + manifest: &ManifestFile, + locked: bool, + offline: bool, + sway_git_tag: &str, + ) -> Result { + let lock_path = forc_util::lock_path(manifest.dir()); + let plan_result = BuildPlan::from_lock_file(&lock_path, sway_git_tag); + + // Retrieve the old lock file state so we can produce a diff. + let old_lock = plan_result + .as_ref() + .ok() + .map(|plan| Lock::from_graph(plan.graph())) + .unwrap_or_default(); + + // Check if there are any errors coming from the BuildPlan generation from the lock file + // If there are errors we will need to create the BuildPlan from scratch, i.e fetch & pin everything + let mut new_lock_cause = None; + let mut plan = plan_result.or_else(|e| -> Result { + new_lock_cause = if e.to_string().contains("No such file or directory") { + Some(anyhow!("lock file did not exist")) + } else { + Some(e) + }; + let plan = BuildPlan::new(manifest, sway_git_tag, offline)?; + Ok(plan) + })?; + + // If there are no issues with the BuildPlan generated from the lock file + // Check and apply the diff. + if new_lock_cause.is_none() { + let diff = plan.validate(manifest, sway_git_tag)?; + if !diff.added.is_empty() || !diff.removed.is_empty() { + new_lock_cause = Some(anyhow!("lock file did not match manifest `diff`")); + plan = plan.apply_pkg_diff(diff, sway_git_tag, offline)?; + } + } + + if let Some(cause) = new_lock_cause { + if locked { + bail!( + "The lock file {} needs to be updated (Cause: {}) \ + but --locked was passed to prevent this.", + lock_path.to_string_lossy(), + cause, + ); + } + + info!(" Creating a new `Forc.lock` file. (Cause: {})", cause); + create_new_lock(&plan, &old_lock, manifest, &lock_path)?; + info!(" Created new lock file at {}", lock_path.display()); + } + + Ok(plan) + } + /// Create a new build plan from an existing one. Needs the difference with the existing plan with the lock. pub fn apply_pkg_diff( &self, @@ -333,7 +391,8 @@ impl BuildPlan { } let name = dep.package().unwrap_or(dep_name).to_string(); - let source = dep_to_source(proj_path, dep)?; + let source = + apply_patch(&name, &dep_to_source(proj_path, dep)?, manifest, proj_path)?; let dep_pkg = Pkg { name, source }; Ok((dep_name, dep_pkg)) }) @@ -827,10 +886,24 @@ pub fn graph_to_path_map( bail!("missing path info for dependency: {}", &dep_name); } })?; - let rel_dep_path = detailed - .path - .as_ref() - .ok_or_else(|| anyhow!("missing path info for dependency: {}", dep.name))?; + // Check if there is a patch for this dep + let patch = parent_manifest + .patches() + .find_map(|patches| patches.1.get(&dep_name)); + // If there is one fetch the details. + let patch_details = patch.and_then(|patch| match patch { + Dependency::Simple(_) => None, + Dependency::Detailed(detailed) => Some(detailed), + }); + // If there is a detail we should have the path. + // If not either we do not have a patch so we are checking dependencies of parent + // If we can't find the path there, either patch or dep is provided as a basic dependency, so we are missing the path info. + let rel_dep_path = if let Some(patch_details) = patch_details { + patch_details.path.as_ref() + } else { + detailed.path.as_ref() + } + .ok_or_else(|| anyhow!("missing path info for dep: {}", &dep_name))?; let path = parent_path.join(rel_dep_path); if !path.exists() { bail!("pinned `path` dependency \"{}\" source missing", dep.name); @@ -930,6 +1003,38 @@ pub(crate) fn fetch_deps( Ok((graph, path_map)) } +fn apply_patch( + name: &str, + source: &Source, + manifest: &Manifest, + parent_path: &Path, +) -> Result { + match source { + // Check if the patch is for a git dependency. + Source::Git(git) => { + // Check if we got a patch for the git dependency. + if let Some(source_patches) = manifest + .patch + .as_ref() + .and_then(|patches| patches.get(git.repo.as_str())) + { + if let Some(patch) = source_patches.get(name) { + Ok(dep_to_source(parent_path, patch)?) + } else { + bail!( + "Cannot find the patch for the {} for package {}", + git.repo, + name + ) + } + } else { + Ok(source.clone()) + } + } + _ => Ok(source.clone()), + } +} + /// Produce a unique ID for a particular fetch pass. /// /// This is used in the temporary git directory and allows for avoiding contention over the git repo directory. @@ -958,7 +1063,12 @@ fn fetch_children( let parent_path = path_map[&parent_id].clone(); for (dep_name, dep) in manifest.deps() { let name = dep.package().unwrap_or(dep_name).to_string(); - let source = dep_to_source(&parent_path, dep)?; + let source = apply_patch( + &name, + &dep_to_source(&parent_path, dep)?, + manifest, + &parent_path, + )?; if offline_mode && !matches!(source, Source::Path(_)) { bail!("Unable to fetch pkg {:?} in offline mode", source); } @@ -1237,7 +1347,9 @@ fn dep_to_source(pkg_path: &Path, dep: &Dependency) -> Result { Dependency::Detailed(ref det) => match (&det.path, &det.version, &det.git) { (Some(relative_path), _, _) => { let path = pkg_path.join(relative_path); - Source::Path(path.canonicalize()?) + Source::Path(path.canonicalize().map_err(|err| { + anyhow!("Cant apply patch from {}, cause: {}", relative_path, &err) + })?) } (_, _, Some(repo)) => { let reference = match (&det.branch, &det.tag, &det.rev) { @@ -1262,12 +1374,12 @@ fn dep_to_source(pkg_path: &Path, dep: &Dependency) -> Result { Ok(source) } -/// Given a `forc_pkg::BuildConfig`, produce the necessary `sway_core::BuildConfig` required for +/// Given a `forc_pkg::BuildProfile`, produce the necessary `sway_core::BuildConfig` required for /// compilation. pub fn sway_build_config( manifest_dir: &Path, entry_path: &Path, - build_conf: &BuildConfig, + build_profile: &BuildProfile, ) -> Result { // Prepare the build config to pass through to the compiler. let file_name = find_file_name(manifest_dir, entry_path)?; @@ -1275,45 +1387,98 @@ pub fn sway_build_config( file_name.to_path_buf(), manifest_dir.to_path_buf(), ) - .print_finalized_asm(build_conf.print_finalized_asm) - .print_intermediate_asm(build_conf.print_intermediate_asm) - .print_ir(build_conf.print_ir); + .print_finalized_asm(build_profile.print_finalized_asm) + .print_intermediate_asm(build_profile.print_intermediate_asm) + .print_ir(build_profile.print_ir); Ok(build_config) } /// Builds the dependency namespace for the package at the given node index within the graph. /// /// This function is designed to be called for each node in order of compilation. +/// +/// This function ensures that if `core` exists in the graph (the vastly common case) it is also +/// present within the namespace. This is a necessity for operators to work for example. pub fn dependency_namespace( namespace_map: &HashMap, graph: &Graph, - compilation_order: &[NodeIx], node: NodeIx, ) -> namespace::Module { + let mut namespace = namespace::Module::default(); + + // Add direct dependencies. + let mut core_added = false; + for edge in graph.edges_directed(node, Direction::Outgoing) { + let dep_node = edge.target(); + let dep_namespace = &namespace_map[&dep_node]; + let dep_name = kebab_to_snake_case(edge.weight()); + namespace.insert_submodule(dep_name, dep_namespace.clone()); + let dep = &graph[dep_node]; + if dep.name == CORE { + core_added = true; + } + } + + // Add `core` if not already added. + if !core_added { + if let Some(core_node) = find_core_dep(graph, node) { + let core_namespace = &namespace_map[&core_node]; + namespace.insert_submodule(CORE.to_string(), core_namespace.clone()); + } + } + + namespace +} + +/// Find the `core` dependency (whether direct or transitive) for the given node if it exists. +fn find_core_dep(graph: &Graph, node: NodeIx) -> Option { use petgraph::visit::{Dfs, Walker}; - // Find all nodes that are a dependency of this one with a depth-first search. - let deps: HashSet = Dfs::new(graph, node).iter(graph).collect(); + // If we are `core`, do nothing. + let pkg = &graph[node]; + if pkg.name == CORE { + return None; + } - // In order of compilation, accumulate dependency namespaces as submodules. - let mut namespace = namespace::Module::default(); - for &dep_node in compilation_order.iter().filter(|n| deps.contains(n)) { - if dep_node == node { - break; + // If we have `core` as a direct dep, use it. + let mut maybe_std = None; + for edge in graph.edges_directed(node, Direction::Outgoing) { + let dep_node = edge.target(); + let dep = &graph[dep_node]; + match &dep.name[..] { + CORE => return Some(dep_node), + STD => maybe_std = Some(dep_node), + _ => (), } - // Add the namespace once for each of its names. - let dep_namespace = &namespace_map[&dep_node]; - let dep_names: BTreeSet<_> = graph - .edges_directed(dep_node, Direction::Incoming) - .map(|e| e.weight()) - .collect(); - for dep_name in dep_names { - let dep_name = kebab_to_snake_case(dep_name); - namespace.insert_submodule(dep_name.to_string(), dep_namespace.clone()); + } + + // If we have `std`, select `core` via `std`. + if let Some(std) = maybe_std { + return find_core_dep(graph, std); + } + + // Otherwise, search from this node. + for dep_node in Dfs::new(graph, node).iter(graph) { + let dep = &graph[dep_node]; + if dep.name == CORE { + return Some(dep_node); } } - namespace + None +} + +/// Compiles the package to an AST. +pub fn compile_ast( + manifest: &ManifestFile, + build_profile: &BuildProfile, + namespace: namespace::Module, +) -> Result { + let source = manifest.entry_string()?; + let sway_build_config = + sway_build_config(manifest.dir(), &manifest.entry_path(), build_profile)?; + let ast_res = sway_core::compile_to_ast(source, namespace, Some(&sway_build_config)); + Ok(ast_res) } /// Compiles the given package. @@ -1337,17 +1502,40 @@ pub fn dependency_namespace( pub fn compile( pkg: &Pinned, manifest: &ManifestFile, - build_config: &BuildConfig, + build_profile: &BuildProfile, namespace: namespace::Module, source_map: &mut SourceMap, ) -> Result<(Compiled, Option)> { + // Time the given expression and print the result if `build_config.time_phases` is true. + macro_rules! time_expr { + ($description:expr, $expression:expr) => {{ + if build_profile.time_phases { + let expr_start = std::time::Instant::now(); + let output = { $expression }; + println!( + " Time elapsed to {}: {:?}", + $description, + expr_start.elapsed() + ); + output + } else { + $expression + } + }}; + } + let entry_path = manifest.entry_path(); - let source = manifest.entry_string()?; - let sway_build_config = sway_build_config(manifest.dir(), &entry_path, build_config)?; - let silent_mode = build_config.silent; + let sway_build_config = time_expr!( + "produce `sway_core::BuildConfig`", + sway_build_config(manifest.dir(), &entry_path, build_profile)? + ); + let silent_mode = build_profile.silent; // First, compile to an AST. We'll update the namespace and check for JSON ABI output. - let ast_res = sway_core::compile_to_ast(source, namespace, Some(&sway_build_config)); + let ast_res = time_expr!( + "compile to ast", + compile_ast(manifest, build_profile, namespace)? + ); match &ast_res { CompileAstResult::Failure { warnings, errors } => { print_on_failure(silent_mode, warnings, errors); @@ -1357,7 +1545,8 @@ pub fn compile( typed_program, warnings, } => { - let json_abi = typed_program.kind.generate_json_abi(); + let json_abi = time_expr!("generate JSON ABI", typed_program.kind.generate_json_abi()); + let storage_slots = typed_program.storage_slots.clone(); let tree_type = typed_program.kind.tree_type(); match tree_type { // If we're compiling a library, we don't need to compile any further. @@ -1368,6 +1557,7 @@ pub fn compile( let lib_namespace = typed_program.root.namespace.clone(); let compiled = Compiled { json_abi, + storage_slots, bytecode, tree_type, }; @@ -1376,14 +1566,21 @@ pub fn compile( // For all other program types, we'll compile the bytecode. TreeType::Contract | TreeType::Predicate | TreeType::Script => { - let asm_res = sway_core::ast_to_asm(ast_res, &sway_build_config); - let bc_res = sway_core::asm_to_bytecode(asm_res, source_map); + let asm_res = time_expr!( + "compile ast to asm", + sway_core::ast_to_asm(ast_res, &sway_build_config) + ); + let bc_res = time_expr!( + "compile asm to bytecode", + sway_core::asm_to_bytecode(asm_res, source_map) + ); match bc_res { BytecodeCompilationResult::Success { bytes, warnings } => { print_on_success(silent_mode, &pkg.name, &warnings, &tree_type); let bytecode = bytes; let compiled = Compiled { json_abi, + storage_slots, bytecode, tree_type, }; @@ -1410,26 +1607,27 @@ pub fn compile( /// Also returns the resulting `sway_core::SourceMap` which may be useful for debugging purposes. pub fn build( plan: &BuildPlan, - conf: &BuildConfig, + profile: &BuildProfile, sway_git_tag: &str, ) -> anyhow::Result<(Compiled, SourceMap)> { let mut namespace_map = Default::default(); let mut source_map = SourceMap::new(); let mut json_abi = vec![]; + let mut storage_slots = vec![]; let mut bytecode = vec![]; let mut tree_type = None; for &node in &plan.compilation_order { - let dep_namespace = - dependency_namespace(&namespace_map, &plan.graph, &plan.compilation_order, node); + let dep_namespace = dependency_namespace(&namespace_map, &plan.graph, node); let pkg = &plan.graph[node]; let path = &plan.path_map[&pkg.id()]; let manifest = ManifestFile::from_dir(path, sway_git_tag)?; - let res = compile(pkg, &manifest, conf, dep_namespace, &mut source_map)?; + let res = compile(pkg, &manifest, profile, dep_namespace, &mut source_map)?; let (compiled, maybe_namespace) = res; if let Some(namespace) = maybe_namespace { namespace_map.insert(node, namespace.into()); } json_abi.extend(compiled.json_abi); + storage_slots.extend(compiled.storage_slots); bytecode = compiled.bytecode; tree_type = Some(compiled.tree_type); source_map.insert_dependency(path.clone()); @@ -1439,11 +1637,46 @@ pub fn build( let compiled = Compiled { bytecode, json_abi, + storage_slots, tree_type, }; Ok((compiled, source_map)) } +/// Compile the entire forc package and return a CompileAstResult. +pub fn check( + plan: &BuildPlan, + silent_mode: bool, + sway_git_tag: &str, +) -> anyhow::Result { + let profile = BuildProfile { + silent: silent_mode, + ..BuildProfile::debug() + }; + + let mut namespace_map = Default::default(); + let mut source_map = SourceMap::new(); + for (i, &node) in plan.compilation_order.iter().enumerate() { + let dep_namespace = dependency_namespace(&namespace_map, &plan.graph, node); + let pkg = &plan.graph[node]; + let path = &plan.path_map[&pkg.id()]; + let manifest = ManifestFile::from_dir(path, sway_git_tag)?; + let ast_res = compile_ast(&manifest, &profile, dep_namespace)?; + if let CompileAstResult::Success { typed_program, .. } = &ast_res { + if let TreeType::Library { .. } = typed_program.kind.tree_type() { + namespace_map.insert(node, typed_program.root.namespace.clone()); + } + } + source_map.insert_dependency(path.clone()); + + // We only need to return the final CompileAstResult + if i == plan.compilation_order.len() - 1 { + return Ok(ast_res); + } + } + bail!("unable to check sway program: build plan contains no packages") +} + /// Attempt to find a `Forc.toml` with the given project name within the given directory. /// /// Returns the path to the package on success, or `None` in the case it could not be found. @@ -1565,3 +1798,18 @@ pub fn fuel_core_not_running(node_url: &str) -> anyhow::Error { let message = format!("could not get a response from node at the URL {}. Start a node with `fuel-core`. See https://github.com/FuelLabs/fuel-core#running for more information", node_url); Error::msg(message) } + +fn create_new_lock( + plan: &BuildPlan, + old_lock: &Lock, + manifest: &ManifestFile, + lock_path: &Path, +) -> Result<()> { + let lock = Lock::from_graph(plan.graph()); + let diff = lock.diff(old_lock); + super::lock::print_diff(&manifest.project.name, &diff); + let string = toml::ser::to_string_pretty(&lock) + .map_err(|e| anyhow!("failed to serialize lock file: {}", e))?; + fs::write(&lock_path, &string).map_err(|e| anyhow!("failed to write lock file: {}", e))?; + Ok(()) +} diff --git a/forc-plugins/forc-explore/Cargo.toml b/forc-plugins/forc-explore/Cargo.toml index 8fe0e61ec8c..4850c2dc859 100644 --- a/forc-plugins/forc-explore/Cargo.toml +++ b/forc-plugins/forc-explore/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-explore" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -11,7 +11,7 @@ description = "A `forc` plugin for running the fuel block explorer." [dependencies] anyhow = "1" clap = { version = "3", features = ["derive"] } -forc-util = { version = "0.16.1", path = "../../forc-util" } +forc-util = { version = "0.16.2", path = "../../forc-util" } reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls"] } serde = { version = "1.0", features = ["derive"] } tar = "0.4" diff --git a/forc-plugins/forc-fmt-v2/Cargo.toml b/forc-plugins/forc-fmt-v2/Cargo.toml index d6f23c178d4..3408d63f24e 100644 --- a/forc-plugins/forc-fmt-v2/Cargo.toml +++ b/forc-plugins/forc-fmt-v2/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-fmt-v2" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -12,10 +12,10 @@ description = "A `forc` plugin for running the Sway code formatter." [dependencies] anyhow = "1" clap = { version = "3", features = ["derive"] } -forc-util = { version = "0.16.1", path = "../../forc-util" } +forc-util = { version = "0.16.2", path = "../../forc-util" } prettydiff = "0.5" -sway-core = { version = "0.16.1", path = "../../sway-core" } -sway-fmt-v2 = { version = "0.16.1", path = "../../sway-fmt-v2" } -sway-utils = { version = "0.16.1", path = "../../sway-utils" } +sway-core = { version = "0.16.2", path = "../../sway-core" } +sway-fmt-v2 = { version = "0.16.2", path = "../../sway-fmt-v2" } +sway-utils = { version = "0.16.2", path = "../../sway-utils" } taplo = "0.7" tracing = "0.1" diff --git a/forc-plugins/forc-fmt/Cargo.toml b/forc-plugins/forc-fmt/Cargo.toml index 06188bcf4b3..00dabc3b507 100644 --- a/forc-plugins/forc-fmt/Cargo.toml +++ b/forc-plugins/forc-fmt/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-fmt" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -11,10 +11,10 @@ description = "A `forc` plugin for running the Sway code formatter." [dependencies] anyhow = "1" clap = { version = "3", features = ["derive"] } -forc-util = { version = "0.16.1", path = "../../forc-util" } +forc-util = { version = "0.16.2", path = "../../forc-util" } prettydiff = "0.5" -sway-core = { version = "0.16.1", path = "../../sway-core" } -sway-fmt = { version = "0.16.1", path = "../../sway-fmt" } -sway-utils = { version = "0.16.1", path = "../../sway-utils" } +sway-core = { version = "0.16.2", path = "../../sway-core" } +sway-fmt = { version = "0.16.2", path = "../../sway-fmt" } +sway-utils = { version = "0.16.2", path = "../../sway-utils" } taplo = "0.7" tracing = "0.1" diff --git a/forc-plugins/forc-lsp/Cargo.toml b/forc-plugins/forc-lsp/Cargo.toml index 64c47901d19..5c1614ba4c5 100644 --- a/forc-plugins/forc-lsp/Cargo.toml +++ b/forc-plugins/forc-lsp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-lsp" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -11,5 +11,5 @@ description = "A simple `forc` plugin for starting the sway language server." [dependencies] anyhow = "1" clap = { version = "3", features = ["derive"] } -sway-lsp = { version = "0.16.1", path = "../../sway-lsp" } +sway-lsp = { version = "0.16.2", path = "../../sway-lsp" } tokio = { version = "1.8" } diff --git a/forc-util/Cargo.toml b/forc-util/Cargo.toml index b71660fb188..731ed398ef6 100644 --- a/forc-util/Cargo.toml +++ b/forc-util/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc-util" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -12,9 +12,9 @@ description = "Utility items shared between forc crates." annotate-snippets = { version = "0.9", features = ["color"] } anyhow = "1" dirs = "3.0.2" -sway-core = { version = "0.16.1", path = "../sway-core" } -sway-types = { version = "0.16.1", path = "../sway-types" } -sway-utils = { version = "0.16.1", path = "../sway-utils" } +sway-core = { version = "0.16.2", path = "../sway-core" } +sway-types = { version = "0.16.2", path = "../sway-types" } +sway-utils = { version = "0.16.2", path = "../sway-utils" } termcolor = "1.1" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["ansi", "env-filter", "json"] } diff --git a/forc/Cargo.toml b/forc/Cargo.toml index 435a4919f78..45730610788 100644 --- a/forc/Cargo.toml +++ b/forc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forc" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -21,21 +21,21 @@ annotate-snippets = { version = "0.9", features = ["color"] } anyhow = "1.0.41" clap = { version = "3.1", features = ["cargo", "derive", "env"] } clap_complete = "3.1" -forc-pkg = { version = "0.16.1", path = "../forc-pkg" } -forc-util = { version = "0.16.1", path = "../forc-util" } +forc-pkg = { version = "0.16.2", path = "../forc-pkg" } +forc-util = { version = "0.16.2", path = "../forc-util" } fs_extra = "1.2" fuel-asm = "0.5" fuel-crypto = "0.5" -fuel-gql-client = { version = "0.8", default-features = false } -fuel-tx = "0.12" -fuel-vm = "0.11" +fuel-gql-client = { version = "0.9", default-features = false } +fuel-tx = "0.13" +fuel-vm = "0.12" futures = "0.3" hex = "0.4.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.73" -sway-core = { version = "0.16.1", path = "../sway-core" } -sway-types = { version = "0.16.1", path = "../sway-types" } -sway-utils = { version = "0.16.1", path = "../sway-utils" } +sway-core = { version = "0.16.2", path = "../sway-core" } +sway-types = { version = "0.16.2", path = "../sway-types" } +sway-utils = { version = "0.16.2", path = "../sway-utils" } term-table = "1.3" tokio = { version = "1.8.0", features = ["macros", "rt-multi-thread", "process"] } toml = "0.5" diff --git a/forc/src/cli/commands/build.rs b/forc/src/cli/commands/build.rs index eb7573f7413..6209bb45790 100644 --- a/forc/src/cli/commands/build.rs +++ b/forc/src/cli/commands/build.rs @@ -21,13 +21,18 @@ pub struct Command { /// Path to the project, if not specified, current working directory will be used. #[clap(short, long)] pub path: Option, - /// Whether to compile to bytecode (false) or to print out the generated ASM (true). + /// Print the finalized ASM. + /// + /// This is the state of the ASM with registers allocated and optimisations applied. #[clap(long)] pub print_finalized_asm: bool, - /// Whether to compile to bytecode (false) or to print out the generated ASM (true). + /// Print the generated ASM. + /// + /// This is the state of the ASM prior to performing register allocation and other ASM + /// optimisations. #[clap(long)] pub print_intermediate_asm: bool, - /// Whether to compile to bytecode (false) or to print out the generated IR (true). + /// Print the generated Sway IR (Intermediate Representation). #[clap(long)] pub print_ir: bool, /// If set, outputs a binary file representing the script bytes. @@ -52,6 +57,10 @@ pub struct Command { /// output will be "minified", i.e. all on one line without whitespace. #[clap(long)] pub minify_json_abi: bool, + /// By default the JSON for initial storage slots is formatted for human readability. By using + /// this option JSON output will be "minified", i.e. all on one line without whitespace. + #[clap(long)] + pub minify_json_storage_slots: bool, /// Requires that the Forc.lock file is up-to-date. If the lock file is missing, or it /// needs to be updated, Forc will exit with an error #[clap(long)] @@ -65,6 +74,9 @@ pub struct Command { /// If --build-profile is also provided, forc omits this flag and uses provided build-profile. #[clap(long)] pub release: bool, + /// Output the time elapsed over each part of the compilation process. + #[clap(long)] + pub time_phases: bool, } pub(crate) fn exec(command: Command) -> Result<()> { diff --git a/forc/src/cli/commands/check.rs b/forc/src/cli/commands/check.rs new file mode 100644 index 00000000000..94dc949b33b --- /dev/null +++ b/forc/src/cli/commands/check.rs @@ -0,0 +1,30 @@ +use crate::ops::forc_check; +use anyhow::Result; +use clap::Parser; + +/// Check the current or target project and all of its dependencies for errors. +/// +/// This will essentially compile the packages without performing the final step of code generation, +/// which is faster than running forc build. +#[derive(Debug, Default, Parser)] +pub struct Command { + /// Path to the project, if not specified, current working directory will be used. + #[clap(short, long)] + pub path: Option, + /// Offline mode, prevents Forc from using the network when managing dependencies. + /// Meaning it will only try to use previously downloaded dependencies. + #[clap(long = "offline")] + pub offline_mode: bool, + /// Silent mode. Don't output any warnings or errors to the command line. + #[clap(long = "silent", short = 's')] + pub silent_mode: bool, + /// Requires that the Forc.lock file is up-to-date. If the lock file is missing, or it + /// needs to be updated, Forc will exit with an error + #[clap(long)] + pub locked: bool, +} + +pub(crate) fn exec(command: Command) -> Result<()> { + forc_check::check(command)?; + Ok(()) +} diff --git a/forc/src/cli/commands/deploy.rs b/forc/src/cli/commands/deploy.rs index cc66e241d30..d778da1df23 100644 --- a/forc/src/cli/commands/deploy.rs +++ b/forc/src/cli/commands/deploy.rs @@ -9,13 +9,18 @@ pub struct Command { /// Path to the project, if not specified, current working directory will be used. #[clap(short, long)] pub path: Option, - /// Whether to compile to bytecode (false) or to print out the generated ASM (true). + /// Print the finalized ASM. + /// + /// This is the state of the ASM with registers allocated and optimisations applied. #[clap(long)] pub print_finalized_asm: bool, - /// Whether to compile to bytecode (false) or to print out the generated ASM (true). + /// Print the generated ASM. + /// + /// This is the state of the ASM prior to performing register allocation and other ASM + /// optimisations. #[clap(long)] pub print_intermediate_asm: bool, - /// Whether to compile to bytecode (false) or to print out the IR (true). + /// Print the generated Sway IR (Intermediate Representation). #[clap(long)] pub print_ir: bool, /// If set, outputs a binary file representing the script bytes. @@ -40,6 +45,10 @@ pub struct Command { /// output will be "minified", i.e. all on one line without whitespace. #[clap(long)] pub minify_json_abi: bool, + /// By default the JSON for initial storage slots is formatted for human readability. By using + /// this option JSON output will be "minified", i.e. all on one line without whitespace. + #[clap(long)] + pub minify_json_storage_slots: bool, /// Requires that the Forc.lock file is up-to-date. If the lock file is missing, or it /// needs to be updated, Forc will exit with an error #[clap(long)] @@ -57,6 +66,9 @@ pub struct Command { /// If --build-profile is also provided, forc omits this flag and uses provided build-profile. #[clap(long)] pub release: bool, + /// Output the time elapsed over each part of the compilation process. + #[clap(long)] + pub time_phases: bool, } pub(crate) async fn exec(command: Command) -> Result<()> { diff --git a/forc/src/cli/commands/mod.rs b/forc/src/cli/commands/mod.rs index 90e3bc394ba..987b2d27965 100644 --- a/forc/src/cli/commands/mod.rs +++ b/forc/src/cli/commands/mod.rs @@ -1,5 +1,6 @@ pub mod addr2line; pub mod build; +pub mod check; pub mod clean; pub mod completions; pub mod deploy; diff --git a/forc/src/cli/commands/plugins.rs b/forc/src/cli/commands/plugins.rs index 61bb7aa5687..f8d1c450279 100644 --- a/forc/src/cli/commands/plugins.rs +++ b/forc/src/cli/commands/plugins.rs @@ -1,7 +1,7 @@ use crate::cli::PluginsCommand; use anyhow::{anyhow, Result}; use clap::Parser; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use tracing::info; /// Find all forc plugins available via `PATH`. @@ -32,9 +32,9 @@ pub(crate) fn exec(command: PluginsCommand) -> Result<()> { /// Find a plugin's description /// -/// Given a plugin name, returns the description included in the `-h` opt. Returns -/// a generic description if a description cannot be found -fn parse_description_for_plugin(plugin: &str) -> String { +/// Given a cannonical plugin path, returns the description included in the `-h` opt. +/// Returns a generic description if a description cannot be found +fn parse_description_for_plugin(plugin: &Path) -> String { use std::process::Command; let default_description = "No description found for this plugin."; let proc = Command::new(plugin) @@ -78,7 +78,7 @@ fn format_print_description( .to_string() }; - let description = parse_description_for_plugin(&display); + let description = parse_description_for_plugin(&path); if describe { Ok(format!(" {} \t\t{}", display, description)) diff --git a/forc/src/cli/commands/run.rs b/forc/src/cli/commands/run.rs index bc23a87da39..bc70505f980 100644 --- a/forc/src/cli/commands/run.rs +++ b/forc/src/cli/commands/run.rs @@ -31,15 +31,20 @@ pub struct Command { #[clap(short, long)] pub kill_node: bool, - /// Whether to compile to bytecode (false) or to print out the generated ASM (true). + /// Print the finalized ASM. + /// + /// This is the state of the ASM with registers allocated and optimisations applied. #[clap(long)] pub print_finalized_asm: bool, - /// Whether to compile to bytecode (false) or to print out the generated ASM (true). + /// Print the generated ASM. + /// + /// This is the state of the ASM prior to performing register allocation and other ASM + /// optimisations. #[clap(long)] pub print_intermediate_asm: bool, - /// Whether to compile to bytecode (false) or to print out the IR (true). + /// Print the generated Sway IR (Intermediate Representation). #[clap(long)] pub print_ir: bool, @@ -55,6 +60,10 @@ pub struct Command { #[clap(long = "silent", short = 's')] pub silent_mode: bool, + /// Output the time elapsed over each part of the compilation process. + #[clap(long)] + pub time_phases: bool, + /// Pretty-print the outputs from the node. #[clap(long = "pretty-print", short = 'r')] pub pretty_print: bool, @@ -74,6 +83,11 @@ pub struct Command { #[clap(long)] pub minify_json_abi: bool, + /// By default the JSON for initial storage slots is formatted for human readability. By using + /// this option JSON output will be "minified", i.e. all on one line without whitespace. + #[clap(long)] + pub minify_json_storage_slots: bool, + /// Set the transaction byte price. Defaults to 0. #[clap(long)] pub byte_price: Option, diff --git a/forc/src/cli/mod.rs b/forc/src/cli/mod.rs index c4e6139014d..2a4fddce2cb 100644 --- a/forc/src/cli/mod.rs +++ b/forc/src/cli/mod.rs @@ -1,10 +1,11 @@ use self::commands::{ - addr2line, build, clean, completions, deploy, init, json_abi, parse_bytecode, plugins, run, - template, test, update, + addr2line, build, check, clean, completions, deploy, init, json_abi, parse_bytecode, plugins, + run, template, test, update, }; use addr2line::Command as Addr2LineCommand; use anyhow::{anyhow, Result}; pub use build::Command as BuildCommand; +pub use check::Command as CheckCommand; use clap::Parser; pub use clean::Command as CleanCommand; pub use completions::Command as CompletionsCommand; @@ -35,6 +36,7 @@ enum Forc { Addr2Line(Addr2LineCommand), #[clap(visible_alias = "b")] Build(BuildCommand), + Check(CheckCommand), Clean(CleanCommand), Completions(CompletionsCommand), Deploy(DeployCommand), @@ -64,6 +66,7 @@ pub async fn run_cli() -> Result<()> { match opt.command { Forc::Addr2Line(command) => addr2line::exec(command), Forc::Build(command) => build::exec(command), + Forc::Check(command) => check::exec(command), Forc::Clean(command) => clean::exec(command), Forc::Completions(command) => completions::exec(command), Forc::Deploy(command) => deploy::exec(command).await, diff --git a/forc/src/lib.rs b/forc/src/lib.rs index 61e0bf2f81a..3bd176db218 100644 --- a/forc/src/lib.rs +++ b/forc/src/lib.rs @@ -1,6 +1,6 @@ pub mod cli; mod ops; -mod utils; +pub mod utils; #[cfg(feature = "test")] pub mod test { diff --git a/forc/src/ops/forc_build.rs b/forc/src/ops/forc_build.rs index de910ef738a..00f9da19158 100644 --- a/forc/src/ops/forc_build.rs +++ b/forc/src/ops/forc_build.rs @@ -2,13 +2,13 @@ use crate::{ cli::BuildCommand, utils::{SWAY_BIN_HASH_SUFFIX, SWAY_BIN_ROOT_SUFFIX, SWAY_GIT_TAG}, }; -use anyhow::{anyhow, bail, Result}; -use forc_pkg::{self as pkg, lock, Lock, ManifestFile}; -use forc_util::{default_output_directory, lock_path}; +use anyhow::Result; +use forc_pkg::{self as pkg, ManifestFile}; +use forc_util::default_output_directory; use fuel_tx::Contract; use std::{ fs::{self, File}, - path::{Path, PathBuf}, + path::PathBuf, }; use sway_core::TreeType; use tracing::{info, warn}; @@ -25,9 +25,11 @@ pub fn build(command: BuildCommand) -> Result { silent_mode, output_directory, minify_json_abi, + minify_json_storage_slots, locked, build_profile, release, + time_phases, } = command; let key_debug: String = "debug".to_string(); @@ -56,78 +58,28 @@ pub fn build(command: BuildCommand) -> Result { let manifest = ManifestFile::from_dir(&this_dir, SWAY_GIT_TAG)?; - // If any cli parameter is passed by the user it overrides the selected build profile. - let mut config = &pkg::BuildConfig { - print_ir, - print_finalized_asm, - print_intermediate_asm, - silent: silent_mode, - }; - - // Check if any cli parameter is passed by the user if not fetch the build profile from manifest. - if !print_ir && !print_intermediate_asm && !print_finalized_asm && !silent_mode { - config = manifest - .build_profile - .as_ref() - .and_then(|profiles| profiles.get(&selected_build_profile)) - .unwrap_or_else(|| { - warn!( - "provided profile option {} is not present in the manifest file. \ - Using default config.", - selected_build_profile - ); - config - }); - } - - let lock_path = lock_path(manifest.dir()); - - let plan_result = pkg::BuildPlan::from_lock_file(&lock_path, SWAY_GIT_TAG); - - // Retrieve the old lock file state so we can produce a diff. - let old_lock = plan_result - .as_ref() - .ok() - .map(|plan| Lock::from_graph(plan.graph())) - .unwrap_or_default(); - - // Check if there are any errors coming from the BuildPlan generation from the lock file - // If there are errors we will need to create the BuildPlan from scratch, i.e fetch & pin everything - let mut new_lock_cause = None; - let mut plan = plan_result.or_else(|e| -> Result { - if locked { - bail!( - "The lock file {} needs to be updated but --locked was passed to prevent this.", - lock_path.to_string_lossy() + let plan = pkg::BuildPlan::load_from_manifest(&manifest, locked, offline, SWAY_GIT_TAG)?; + + // Retrieve the specified build profile + let mut profile = manifest + .build_profile(&selected_build_profile) + .cloned() + .unwrap_or_else(|| { + warn!( + "provided profile option {} is not present in the manifest file. \ + Using default profile.", + selected_build_profile ); - } - new_lock_cause = if e.to_string().contains("No such file or directory") { - Some(anyhow!("lock file did not exist")) - } else { - Some(e) - }; - let plan = pkg::BuildPlan::new(&manifest, SWAY_GIT_TAG, offline)?; - Ok(plan) - })?; - - // If there are no issues with the BuildPlan generated from the lock file - // Check and apply the diff. - if new_lock_cause.is_none() { - let diff = plan.validate(&manifest, SWAY_GIT_TAG)?; - if !diff.added.is_empty() || !diff.removed.is_empty() { - new_lock_cause = Some(anyhow!("lock file did not match manifest `diff`")); - plan = plan.apply_pkg_diff(diff, SWAY_GIT_TAG, offline)?; - } - } - - if let Some(cause) = new_lock_cause { - info!(" Creating a new `Forc.lock` file. (Cause: {})", cause); - create_new_lock(&plan, &old_lock, &manifest, &lock_path)?; - info!(" Created new lock file at {}", lock_path.display()); - } + Default::default() + }); + profile.print_ir |= print_ir; + profile.print_finalized_asm |= print_finalized_asm; + profile.print_intermediate_asm |= print_intermediate_asm; + profile.silent |= silent_mode; + profile.time_phases |= time_phases; // Build it! - let (compiled, source_map) = pkg::build(&plan, config, SWAY_GIT_TAG)?; + let (compiled, source_map) = pkg::build(&plan, &profile, SWAY_GIT_TAG)?; if let Some(outfile) = binary_outfile { fs::write(&outfile, &compiled.bytecode)?; @@ -165,14 +117,21 @@ pub fn build(command: BuildCommand) -> Result { info!(" Bytecode size is {} bytes.", compiled.bytecode.len()); + // Additional ops required depending on the program type match compiled.tree_type { - TreeType::Script => { - // hash the bytecode for scripts and store the result in a file in the output directory - let bytecode_hash = format!("0x{}", fuel_crypto::Hasher::hash(&compiled.bytecode)); - let hash_file_name = format!("{}{}", &manifest.project.name, SWAY_BIN_HASH_SUFFIX); - let hash_path = output_dir.join(hash_file_name); - fs::write(hash_path, &bytecode_hash)?; - info!(" Script bytecode hash: {}", bytecode_hash); + TreeType::Contract => { + // For contracts, emit a JSON file with all the initialized storage slots. + let json_storage_slots_stem = format!("{}-storage_slots", manifest.project.name); + let json_storage_slots_path = output_dir + .join(&json_storage_slots_stem) + .with_extension("json"); + let file = File::create(json_storage_slots_path)?; + let res = if minify_json_storage_slots { + serde_json::to_writer(&file, &compiled.storage_slots) + } else { + serde_json::to_writer_pretty(&file, &compiled.storage_slots) + }; + res?; } TreeType::Predicate => { // get the root hash of the bytecode for predicates and store the result in a file in the output directory @@ -182,23 +141,16 @@ pub fn build(command: BuildCommand) -> Result { fs::write(root_path, &root)?; info!(" Predicate root: {}", root); } + TreeType::Script => { + // hash the bytecode for scripts and store the result in a file in the output directory + let bytecode_hash = format!("0x{}", fuel_crypto::Hasher::hash(&compiled.bytecode)); + let hash_file_name = format!("{}{}", &manifest.project.name, SWAY_BIN_HASH_SUFFIX); + let hash_path = output_dir.join(hash_file_name); + fs::write(hash_path, &bytecode_hash)?; + info!(" Script bytecode hash: {}", bytecode_hash); + } _ => (), } Ok(compiled) } - -fn create_new_lock( - plan: &pkg::BuildPlan, - old_lock: &Lock, - manifest: &ManifestFile, - lock_path: &Path, -) -> Result<()> { - let lock = Lock::from_graph(plan.graph()); - let diff = lock.diff(old_lock); - lock::print_diff(&manifest.project.name, &diff); - let string = toml::ser::to_string_pretty(&lock) - .map_err(|e| anyhow!("failed to serialize lock file: {}", e))?; - fs::write(&lock_path, &string).map_err(|e| anyhow!("failed to write lock file: {}", e))?; - Ok(()) -} diff --git a/forc/src/ops/forc_check.rs b/forc/src/ops/forc_check.rs new file mode 100644 index 00000000000..be39de30508 --- /dev/null +++ b/forc/src/ops/forc_check.rs @@ -0,0 +1,23 @@ +use crate::{cli::CheckCommand, utils::SWAY_GIT_TAG}; +use anyhow::Result; +use forc_pkg::{self as pkg, ManifestFile}; +use std::path::PathBuf; + +pub fn check(command: CheckCommand) -> Result { + let CheckCommand { + path, + offline_mode: offline, + silent_mode, + locked, + } = command; + + let this_dir = if let Some(ref path) = path { + PathBuf::from(path) + } else { + std::env::current_dir()? + }; + let manifest = ManifestFile::from_dir(&this_dir, SWAY_GIT_TAG)?; + let plan = pkg::BuildPlan::load_from_manifest(&manifest, locked, offline, SWAY_GIT_TAG)?; + + pkg::check(&plan, silent_mode, SWAY_GIT_TAG) +} diff --git a/forc/src/ops/forc_deploy.rs b/forc/src/ops/forc_deploy.rs index 89ac3de6af0..ef2e67ec853 100644 --- a/forc/src/ops/forc_deploy.rs +++ b/forc/src/ops/forc_deploy.rs @@ -6,7 +6,7 @@ use crate::{ use anyhow::{bail, Result}; use forc_pkg::ManifestFile; use fuel_gql_client::client::FuelClient; -use fuel_tx::{Output, Salt, Transaction}; +use fuel_tx::{Output, Salt, StorageSlot, Transaction}; use fuel_vm::prelude::*; use std::path::PathBuf; use sway_core::TreeType; @@ -33,10 +33,12 @@ pub async fn deploy(command: DeployCommand) -> Result { silent_mode, output_directory, minify_json_abi, + minify_json_storage_slots, locked, url, build_profile, release, + time_phases, } = command; let build_command = BuildCommand { @@ -50,9 +52,11 @@ pub async fn deploy(command: DeployCommand) -> Result { silent_mode, output_directory, minify_json_abi, + minify_json_storage_slots, locked, build_profile, release, + time_phases, }; let compiled = forc_build::build(build_command)?; @@ -60,6 +64,7 @@ pub async fn deploy(command: DeployCommand) -> Result { compiled.bytecode, Vec::::new(), Vec::::new(), + compiled.storage_slots, ); let node_url = match &manifest.network { @@ -87,9 +92,10 @@ fn create_contract_tx( compiled_contract: Vec, inputs: Vec, outputs: Vec, + storage_slots: Vec, ) -> (Transaction, fuel_tx::ContractId) { let gas_price = 0; - let gas_limit = fuel_tx::default_parameters::MAX_GAS_PER_TX; + let gas_limit = fuel_tx::ConsensusParameters::default().max_gas_per_tx; let byte_price = 0; let maturity = 0; let bytecode_witness_index = 0; @@ -97,11 +103,16 @@ fn create_contract_tx( let salt = Salt::new([0; 32]); let static_contracts = vec![]; - let storage_slots = vec![]; let contract = Contract::from(compiled_contract); let root = contract.root(); - let state_root = Contract::default_state_root(); + + // The VM currently requires that storage slots are sorted but this shouldn't be neessary. + // Downstream tooling should do the sorting themselves. + // Ref: https://github.com/FuelLabs/fuel-tx/issues/153 + let mut storage_slots = storage_slots; + storage_slots.sort(); + let state_root = Contract::initial_state_root(storage_slots.iter()); let id = contract.id(&salt, &root, &state_root); info!("Contract id: 0x{}", hex::encode(id)); let outputs = [ diff --git a/forc/src/ops/forc_run.rs b/forc/src/ops/forc_run.rs index 413c95f63b0..2e770a3fa8f 100644 --- a/forc/src/ops/forc_run.rs +++ b/forc/src/ops/forc_run.rs @@ -37,9 +37,11 @@ pub async fn run(command: RunCommand) -> Result> { silent_mode: command.silent_mode, output_directory: command.output_directory, minify_json_abi: command.minify_json_abi, + minify_json_storage_slots: command.minify_json_storage_slots, locked: command.locked, build_profile: None, release: false, + time_phases: command.time_phases, }; let compiled = forc_build::build(build_command)?; diff --git a/forc/src/ops/mod.rs b/forc/src/ops/mod.rs index 1d5acc42f28..2f5f87527db 100644 --- a/forc/src/ops/mod.rs +++ b/forc/src/ops/mod.rs @@ -1,5 +1,6 @@ pub mod forc_abi_json; pub mod forc_build; +pub mod forc_check; pub mod forc_clean; pub mod forc_deploy; pub mod forc_init; diff --git a/forc/src/utils/defaults.rs b/forc/src/utils/defaults.rs index 8d5e28ad684..a6f4161ccbe 100644 --- a/forc/src/utils/defaults.rs +++ b/forc/src/utils/defaults.rs @@ -30,8 +30,7 @@ edition = "2021" license = "Apache-2.0" [dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" +fuels = {{ version = "0.16", features = ["fuel-core-lib"] }} tokio = {{ version = "1.12", features = ["rt", "macros"] }} [[test]] @@ -93,7 +92,6 @@ pub(crate) fn default_test_program(project_name: &str) -> String { format!( "{}{}{}{}{}", r#"use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; // Load abi from json abigen!(MyContract, "out/debug/"#, diff --git a/forc/src/utils/parameters.rs b/forc/src/utils/parameters.rs index 03f268c7536..25da3deadf9 100644 --- a/forc/src/utils/parameters.rs +++ b/forc/src/utils/parameters.rs @@ -8,7 +8,7 @@ pub(crate) struct TxParameters { impl TxParameters { pub const DEFAULT: Self = Self { byte_price: 0, - gas_limit: fuel_tx::default_parameters::MAX_GAS_PER_TX, + gas_limit: fuel_tx::ConsensusParameters::DEFAULT.max_gas_per_tx, gas_price: 0, }; diff --git a/scripts/highlightjs/sway.js b/scripts/highlightjs/sway.js index d089bd81b9f..2158faec472 100644 --- a/scripts/highlightjs/sway.js +++ b/scripts/highlightjs/sway.js @@ -43,6 +43,7 @@ export default function(hljs) { "script", "Self", "self", + "storage", "str", "struct", "trait", diff --git a/sway-core/Cargo.toml b/sway-core/Cargo.toml index 12c4a0eedd3..a9e5bbc8e23 100644 --- a/sway-core/Cargo.toml +++ b/sway-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sway-core" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -15,8 +15,9 @@ dirs = "3.0" either = "1.6" fuel-asm = "0.5" fuel-crypto = "0.5" +fuel-tx = "0.13" fuel-types = "0.5" -fuel-vm = "0.11" +fuel-vm = "0.12" fuels-types = "0.12" hex = { version = "0.4", optional = true } im = "15.0" @@ -28,10 +29,10 @@ regex = "1" serde = { version = "1.0", features = ["derive"] } sha2 = "0.9" smallvec = "1.7" -sway-ir = { version = "0.16.1", path = "../sway-ir" } -sway-parse = { version = "0.16.1", path = "../sway-parse" } -sway-types = { version = "0.16.1", path = "../sway-types" } -sway-utils = { version = "0.16.1", path = "../sway-utils" } +sway-ir = { version = "0.16.2", path = "../sway-ir" } +sway-parse = { version = "0.16.2", path = "../sway-parse" } +sway-types = { version = "0.16.2", path = "../sway-types" } +sway-utils = { version = "0.16.2", path = "../sway-utils" } thiserror = "1.0" tracing = "0.1" uint = "0.9" diff --git a/sway-core/src/constants.rs b/sway-core/src/constants.rs index e80e434b366..6b1d315e485 100644 --- a/sway-core/src/constants.rs +++ b/sway-core/src/constants.rs @@ -7,9 +7,6 @@ pub const LANGUAGE_NAME: &str = "Sway"; /// The size, in bytes, of a single word in the FuelVM. pub const VM_WORD_SIZE: u64 = 8; -// Keywords -pub const INVALID_NAMES: &[&str] = &["storage"]; - pub const CONTRACT_CALL_GAS_PARAMETER_NAME: &str = "gas"; pub const CONTRACT_CALL_COINS_PARAMETER_NAME: &str = "coins"; diff --git a/sway-core/src/control_flow_analysis/dead_code_analysis.rs b/sway-core/src/control_flow_analysis/dead_code_analysis.rs index 548f4aae180..c1e4b8fca80 100644 --- a/sway-core/src/control_flow_analysis/dead_code_analysis.rs +++ b/sway-core/src/control_flow_analysis/dead_code_analysis.rs @@ -16,29 +16,33 @@ use crate::{ type_engine::{resolve_type, TypeInfo}, CompileError, CompileWarning, Ident, TreeType, Warning, }; +use std::collections::BTreeSet; use sway_types::{span::Span, Spanned}; use crate::semantic_analysis::TypedStorageDeclaration; -use petgraph::algo::has_path_connecting; use petgraph::prelude::NodeIndex; +use petgraph::visit::Dfs; impl ControlFlowGraph { pub(crate) fn find_dead_code(&self) -> Vec { - // dead code is code that has no path to the entry point - let mut dead_nodes = vec![]; - for destination in self.graph.node_indices() { - let mut is_connected = false; - for entry in &self.entry_points { - if has_path_connecting(&self.graph, *entry, destination, None) { - is_connected = true; - break; - } - } - if !is_connected { - dead_nodes.push(destination); + // Dead code is code that has no path to the entry point. + // Collect all connected nodes by traversing from the entries. + // The dead nodes are those we did not collect. + let mut connected = BTreeSet::new(); + let mut dfs = Dfs::empty(&self.graph); + for &entry in &self.entry_points { + dfs.move_to(entry); + while let Some(node) = dfs.next(&self.graph) { + connected.insert(node); } } + let dead_nodes: Vec<_> = self + .graph + .node_indices() + .filter(|n| !connected.contains(n)) + .collect(); + let dead_enum_variant_warnings = dead_nodes .iter() .filter_map(|x| match &self.graph[*x] { @@ -1029,44 +1033,32 @@ fn connect_expression( } fn connect_intrinsic_function( - kind: &TypedIntrinsicFunctionKind, + TypedIntrinsicFunctionKind { + kind, arguments, .. + }: &TypedIntrinsicFunctionKind, graph: &mut ControlFlowGraph, leaves: &[NodeIndex], exit_node: Option, tree_type: &TreeType, ) -> Result, CompileError> { - let result = match kind { - TypedIntrinsicFunctionKind::SizeOfVal { exp } => connect_expression( + let node = graph.add_node(kind.to_string().into()); + for leaf in leaves { + graph.add_edge(*leaf, node, "".into()); + } + let mut result = vec![node]; + let _ = arguments.iter().try_fold(&mut result, |accum, exp| { + let mut res = connect_expression( &(*exp).expression, graph, leaves, exit_node, - "size_of", + "intrinsic", tree_type, exp.span.clone(), - )?, - TypedIntrinsicFunctionKind::SizeOfType { .. } => { - let node = graph.add_node("size of type".into()); - for leaf in leaves { - graph.add_edge(*leaf, node, "".into()); - } - vec![node] - } - TypedIntrinsicFunctionKind::IsRefType { .. } => { - let node = graph.add_node("is ref type".into()); - for leaf in leaves { - graph.add_edge(*leaf, node, "".into()); - } - vec![node] - } - TypedIntrinsicFunctionKind::GetStorageKey => { - let node = graph.add_node("Get storage key".into()); - for leaf in leaves { - graph.add_edge(*leaf, node, "".into()); - } - vec![node] - } - }; + )?; + accum.append(&mut res); + Ok::<_, CompileError>(accum) + })?; Ok(result) } diff --git a/sway-core/src/convert_parse_tree.rs b/sway-core/src/convert_parse_tree.rs index 6eec94e9008..d7874f2ee3b 100644 --- a/sway-core/src/convert_parse_tree.rs +++ b/sway-core/src/convert_parse_tree.rs @@ -1,3 +1,5 @@ +use crate::type_engine::{TraitConstraint, TypeArgument, TypeParameter}; + use { crate::{ constants::{ @@ -8,12 +10,11 @@ use { AbiDeclaration, AsmExpression, AsmOp, AsmRegister, AsmRegisterDeclaration, AstNode, AstNodeContent, CallPath, CodeBlock, ConstantDeclaration, Declaration, EnumDeclaration, EnumVariant, Expression, FunctionDeclaration, FunctionParameter, ImplSelf, ImplTrait, - ImportType, IncludeStatement, IntrinsicFunctionKind, LazyOp, Literal, MatchBranch, - MethodName, ParseTree, Purity, Reassignment, ReassignmentTarget, ReturnStatement, - Scrutinee, StorageDeclaration, StorageField, StructDeclaration, StructExpressionField, - StructField, StructScrutineeField, Supertrait, TraitConstraint, TraitDeclaration, TraitFn, - TreeType, TypeArgument, TypeInfo, TypeParameter, UseStatement, VariableDeclaration, - Visibility, WhileLoop, + ImportType, IncludeStatement, LazyOp, Literal, MatchBranch, MethodName, ParseTree, Purity, + Reassignment, ReassignmentTarget, ReturnStatement, Scrutinee, StorageDeclaration, + StorageField, StructDeclaration, StructExpressionField, StructField, StructScrutineeField, + Supertrait, TraitDeclaration, TraitFn, TreeType, TypeInfo, UseStatement, + VariableDeclaration, Visibility, WhileLoop, }, std::{ collections::HashMap, @@ -101,16 +102,6 @@ pub enum ConvertParseTreeError { GenericsNotSupportedHere { span: Span }, #[error("fully qualified paths are not supported here")] FullyQualifiedPathsNotSupportedHere { span: Span }, - #[error("__size_of does not take arguments")] - SizeOfTooManyArgs { span: Span }, - #[error("__size_of requires exactly one generic argument")] - SizeOfOneGenericArg { span: Span }, - #[error("__is_reference_type does not take arguments")] - IsReferenceTypeTooManyArgs { span: Span }, - #[error("__is_reference_type requires exactly one generic argument")] - IsReferenceTypeOneGenericArg { span: Span }, - #[error("__size_of_val requires exactly one argument")] - SizeOfValOneArg { span: Span }, #[error("tuple index out of range")] TupleIndexOutOfRange { span: Span }, #[error("shift-left expressions are not implemented")] @@ -198,11 +189,6 @@ impl Spanned for ConvertParseTreeError { ConvertParseTreeError::FunctionArbitraryExpression { span } => span.clone(), ConvertParseTreeError::GenericsNotSupportedHere { span } => span.clone(), ConvertParseTreeError::FullyQualifiedPathsNotSupportedHere { span } => span.clone(), - ConvertParseTreeError::SizeOfTooManyArgs { span } => span.clone(), - ConvertParseTreeError::SizeOfOneGenericArg { span } => span.clone(), - ConvertParseTreeError::IsReferenceTypeTooManyArgs { span } => span.clone(), - ConvertParseTreeError::IsReferenceTypeOneGenericArg { span } => span.clone(), - ConvertParseTreeError::SizeOfValOneArg { span } => span.clone(), ConvertParseTreeError::TupleIndexOutOfRange { span } => span.clone(), ConvertParseTreeError::ShlNotImplemented { span } => span.clone(), ConvertParseTreeError::ShrNotImplemented { span } => span.clone(), @@ -1441,118 +1427,38 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - if call_path.prefixes.is_empty() - && !call_path.is_absolute - && Intrinsic::try_from_str(call_path.suffix.as_str()) - == Some(Intrinsic::SizeOf) - { - if !arguments.is_empty() { - let error = ConvertParseTreeError::SizeOfTooManyArgs { span }; - return Err(ec.error(error)); - } - let ty = match { - generics_opt.and_then(|(_double_colon_token, generic_args)| { - iter_to_array(generic_args.parameters.into_inner()) - }) - } { - Some([ty]) => ty, - None => { - let error = ConvertParseTreeError::SizeOfOneGenericArg { span }; - return Err(ec.error(error)); - } - }; - let type_span = ty.span(); - let type_name = ty_to_type_info(ec, ty)?; - Expression::IntrinsicFunction { - kind: IntrinsicFunctionKind::SizeOfType { - type_name, - type_span, - }, - span, - } - } else if call_path.prefixes.is_empty() - && !call_path.is_absolute - && Intrinsic::try_from_str(call_path.suffix.as_str()) - == Some(Intrinsic::GetStorageKey) - { - if !arguments.is_empty() { - let error = ConvertParseTreeError::GetStorageKeyTooManyArgs { span }; - return Err(ec.error(error)); - } - if generics_opt.is_some() { - let error = ConvertParseTreeError::GenericsNotSupportedHere { span }; - return Err(ec.error(error)); - } - Expression::IntrinsicFunction { - kind: IntrinsicFunctionKind::GetStorageKey, - span, - } - } else if call_path.prefixes.is_empty() - && !call_path.is_absolute - && Intrinsic::try_from_str(call_path.suffix.as_str()) - == Some(Intrinsic::IsReferenceType) - { - if !arguments.is_empty() { - let error = ConvertParseTreeError::IsReferenceTypeTooManyArgs { span }; - return Err(ec.error(error)); - } - let ty = match { - generics_opt.and_then(|(_double_colon_token, generic_args)| { - iter_to_array(generic_args.parameters.into_inner()) - }) - } { - Some([ty]) => ty, - None => { - let error = - ConvertParseTreeError::IsReferenceTypeOneGenericArg { span }; - return Err(ec.error(error)); - } - }; - let type_span = ty.span(); - let type_name = ty_to_type_info(ec, ty)?; - Expression::IntrinsicFunction { - kind: IntrinsicFunctionKind::IsRefType { - type_name, - type_span, - }, - span, - } - } else if call_path.prefixes.is_empty() - && !call_path.is_absolute - && Intrinsic::try_from_str(call_path.suffix.as_str()) - == Some(Intrinsic::SizeOfVal) - { - let exp = match <[_; 1]>::try_from(arguments) { - Ok([exp]) => Box::new(exp), - Err(..) => { - let error = ConvertParseTreeError::SizeOfValOneArg { span }; - return Err(ec.error(error)); - } - }; - Expression::IntrinsicFunction { - kind: IntrinsicFunctionKind::SizeOfVal { exp }, - span, + let type_arguments = match generics_opt { + Some((_double_colon_token, generic_args)) => { + generic_args_to_type_arguments(ec, generic_args)? } - } else { - let type_arguments = match generics_opt { - Some((_double_colon_token, generic_args)) => { - generic_args_to_type_arguments(ec, generic_args)? - } - None => Vec::new(), - }; - if call_path.prefixes.is_empty() { - Expression::FunctionApplication { - name: call_path, + None => Vec::new(), + }; + match Intrinsic::try_from_str(call_path.suffix.as_str()) { + Some(intrinsic) + if call_path.prefixes.is_empty() && !call_path.is_absolute => + { + Expression::IntrinsicFunction { + kind: intrinsic, arguments, type_arguments, span, } - } else { - Expression::DelineatedPath { - call_path, - args: arguments, - type_arguments, - span, + } + _ => { + if call_path.prefixes.is_empty() { + Expression::FunctionApplication { + name: call_path, + arguments, + type_arguments, + span, + } + } else { + Expression::DelineatedPath { + call_path, + args: arguments, + type_arguments, + span, + } } } } @@ -1866,7 +1772,10 @@ fn storage_field_to_storage_field( let storage_field = StorageField { name: storage_field.name, type_info: ty_to_type_info(ec, storage_field.ty)?, - //initializer: expr_to_expression(storage_field.expr), + initializer: storage_field + .initializer + .map(|initializer| expr_to_expression(ec, initializer.1)) + .transpose()?, }; Ok(storage_field) } @@ -2704,10 +2613,10 @@ fn asm_register_declaration_to_asm_register_declaration( ) -> Result { Ok(AsmRegisterDeclaration { name: asm_register_declaration.register, - initializer: match asm_register_declaration.value_opt { - None => None, - Some((_colon_token, expr)) => Some(expr_to_expression(ec, *expr)?), - }, + initializer: asm_register_declaration + .value_opt + .map(|(_colon_token, expr)| expr_to_expression(ec, *expr)) + .transpose()?, }) } @@ -2759,17 +2668,42 @@ fn pattern_to_scrutinee( span, } } - Pattern::Struct { path, fields } => Scrutinee::StructScrutinee { - struct_name: path_expr_to_ident(ec, path)?, - fields: { - fields - .into_inner() - .into_iter() - .map(|field| pattern_struct_field_to_struct_scrutinee_field(ec, field)) - .collect::>()? - }, - span, - }, + Pattern::Struct { path, fields } => { + let mut errors = Vec::new(); + let fields = fields.into_inner(); + + // Make sure each struct field is declared once + let mut names_of_fields = std::collections::HashSet::new(); + fields.clone().into_iter().for_each(|v| { + if let PatternStructField::Field { + field_name, + pattern_opt: _, + } = v + { + if !names_of_fields.insert(field_name.clone()) { + errors.push(ConvertParseTreeError::DuplicateStructField { + name: field_name.clone(), + span: field_name.span(), + }); + } + } + }); + + if let Some(errors) = ec.errors(errors) { + return Err(errors); + } + + let scrutinee_fields = fields + .into_iter() + .map(|field| pattern_struct_field_to_struct_scrutinee_field(ec, field)) + .collect::>()?; + + Scrutinee::StructScrutinee { + struct_name: path_expr_to_ident(ec, path)?, + fields: { scrutinee_fields }, + span, + } + } Pattern::Tuple(pat_tuple) => Scrutinee::Tuple { elems: { pat_tuple @@ -2841,15 +2775,25 @@ fn pattern_struct_field_to_struct_scrutinee_field( pattern_struct_field: PatternStructField, ) -> Result { let span = pattern_struct_field.span(); - let struct_scrutinee_field = StructScrutineeField { - field: pattern_struct_field.field_name, - scrutinee: match pattern_struct_field.pattern_opt { - Some((_colon_token, pattern)) => Some(pattern_to_scrutinee(ec, *pattern)?), - None => None, - }, - span, - }; - Ok(struct_scrutinee_field) + match pattern_struct_field { + PatternStructField::Rest { token } => { + let struct_scrutinee_field = StructScrutineeField::Rest { span: token.span() }; + Ok(struct_scrutinee_field) + } + PatternStructField::Field { + field_name, + pattern_opt, + } => { + let struct_scrutinee_field = StructScrutineeField::Field { + field: field_name, + scrutinee: pattern_opt + .map(|(_colon_token, pattern)| pattern_to_scrutinee(ec, *pattern)) + .transpose()?, + span, + }; + Ok(struct_scrutinee_field) + } + } } fn assignable_to_expression( diff --git a/sway-core/src/error.rs b/sway-core/src/error.rs index ef8da7a4414..ba8a071cee5 100644 --- a/sway-core/src/error.rs +++ b/sway-core/src/error.rs @@ -883,6 +883,13 @@ pub enum CompileError { missing_patterns: String, span: Span, }, + #[error("Pattern does not mention {}: {}", + if missing_fields.len() == 1 { "field" } else { "fields" }, + missing_fields.join(", "))] + MatchStructPatternMissingFields { + missing_fields: Vec, + span: Span, + }, #[error( "Storage attribute access mismatch. Try giving the surrounding function more access by \ adding \"#[{STORAGE_PURITY_ATTRIBUTE_NAME}({attrs})]\" to the function declaration." @@ -988,6 +995,20 @@ pub enum CompileError { NonConstantDeclValue { span: Span }, #[error("Declaring storage in a {program_kind} is not allowed.")] StorageDeclarationInNonContract { program_kind: String, span: Span }, + #[error("Unsupported argument type to intrinsic \"{name}\".")] + IntrinsicUnsupportedArgType { name: String, span: Span }, + #[error("Call to \"{name}\" expects {expected} arguments")] + IntrinsicIncorrectNumArgs { + name: String, + expected: u64, + span: Span, + }, + #[error("Call to \"{name}\" expects {expected} type arguments")] + IntrinsicIncorrectNumTArgs { + name: String, + expected: u64, + span: Span, + }, } impl std::convert::From for CompileError { @@ -1107,6 +1128,7 @@ impl Spanned for CompileError { StarImportShadowsOtherSymbol { name } => name.span(), MatchWrongType { span, .. } => span.clone(), MatchExpressionNonExhaustive { span, .. } => span.clone(), + MatchStructPatternMissingFields { span, .. } => span.clone(), NotAnEnum { span, .. } => span.clone(), StorageAccessMismatch { span, .. } => span.clone(), TraitDeclPureImplImpure { span, .. } => span.clone(), @@ -1143,6 +1165,9 @@ impl Spanned for CompileError { TupleIndexOutOfBounds { span, .. } => span.clone(), NonConstantDeclValue { span } => span.clone(), StorageDeclarationInNonContract { span, .. } => span.clone(), + IntrinsicUnsupportedArgType { span, .. } => span.clone(), + IntrinsicIncorrectNumArgs { span, .. } => span.clone(), + IntrinsicIncorrectNumTArgs { span, .. } => span.clone(), } } } diff --git a/sway-core/src/ir_generation.rs b/sway-core/src/ir_generation.rs index a54be627950..b8254f1b612 100644 --- a/sway-core/src/ir_generation.rs +++ b/sway-core/src/ir_generation.rs @@ -1,9 +1,10 @@ mod compile; -mod const_eval; +pub mod const_eval; mod convert; mod function; mod lexical_map; mod purity; +pub mod storage; mod types; use crate::{ @@ -17,7 +18,7 @@ use sway_types::span::Span; pub(crate) use purity::PurityChecker; pub(crate) fn compile_program(program: TypedProgram) -> Result { - let TypedProgram { kind, root } = program; + let TypedProgram { kind, root, .. } = program; let mut ctx = Context::default(); match kind { diff --git a/sway-core/src/ir_generation/compile.rs b/sway-core/src/ir_generation/compile.rs index bd8598449a2..8affe521be5 100644 --- a/sway-core/src/ir_generation/compile.rs +++ b/sway-core/src/ir_generation/compile.rs @@ -1,7 +1,7 @@ use crate::{ error::CompileError, parse_tree::{Purity, Visibility}, - semantic_analysis::{ast_node::*, *}, + semantic_analysis::{ast_node::*, namespace}, }; use super::{ @@ -63,14 +63,6 @@ fn compile_constants( None } } - - TypedDeclaration::VariableDeclaration(TypedVariableDeclaration { - name, - body, - const_decl_origin, - .. - }) if *const_decl_origin => Some((name, body)), - _otherwise => None, }; @@ -230,6 +222,8 @@ fn compile_fn_with_args( ret_val = Constant::get_unit(context, None); } + let already_returns = compiler.current_block.is_terminated_by_ret(context); + // Another special case: if the last expression in a function is a return then we don't want to // add another implicit return instruction here, as `ret_val` will be unit regardless of the // function return type actually is. This new RET will be going into an unreachable block @@ -239,9 +233,10 @@ fn compile_fn_with_args( // To tell if this is the case we can check that the current block is empty and has no // predecessors (and isn't the entry block which has none by definition), implying the most // recent instruction was a RET. - if compiler.current_block.num_instructions(context) > 0 - || compiler.current_block == compiler.function.get_entry_block(context) - || compiler.current_block.num_predecessors(context) > 0 + if !already_returns + && (compiler.current_block.num_instructions(context) > 0 + || compiler.current_block == compiler.function.get_entry_block(context) + || compiler.current_block.num_predecessors(context) > 0) { if ret_type.eq(context, &Type::Unit) { ret_val = Constant::get_unit(context, None); diff --git a/sway-core/src/ir_generation/const_eval.rs b/sway-core/src/ir_generation/const_eval.rs index 81f704dfdeb..97b9eeb834d 100644 --- a/sway-core/src/ir_generation/const_eval.rs +++ b/sway-core/src/ir_generation/const_eval.rs @@ -6,7 +6,7 @@ use crate::{ }, }; -use super::types::*; +use super::{convert::convert_literal_to_constant, types::*}; use sway_ir::{ constant::{Constant, ConstantValue}, @@ -26,6 +26,20 @@ pub(super) fn compile_constant_expression( const_expr: &TypedExpression, ) -> Result { let span_id_idx = MetadataIndex::from_span(context, &const_expr.span); + + let constant_evaluated = compile_constant_expression_to_constant(context, module, const_expr)?; + Ok(Value::new_constant( + context, + constant_evaluated, + span_id_idx, + )) +} + +pub(crate) fn compile_constant_expression_to_constant( + context: &mut Context, + module: Module, + const_expr: &TypedExpression, +) -> Result { let err = match &const_expr.expression { // Special case functions because the span in `const_expr` is to the inlined function // definition, rather than the actual call site. @@ -39,8 +53,8 @@ pub(super) fn compile_constant_expression( }), }; let mut known_consts = MappedStack::::new(); - const_eval_typed_expr(context, module, &mut known_consts, const_expr) - .map_or(err, |c| Ok(Value::new_constant(context, c, span_id_idx))) + + const_eval_typed_expr(context, module, &mut known_consts, const_expr).map_or(err, Ok) } // A HashMap that can hold multiple values and @@ -97,7 +111,7 @@ fn const_eval_typed_expr( expr: &TypedExpression, ) -> Option { match &expr.expression { - TypedExpressionVariant::Literal(l) => Some(super::convert::convert_literal_to_constant(l)), + TypedExpressionVariant::Literal(l) => Some(convert_literal_to_constant(l)), TypedExpressionVariant::FunctionApplication { arguments, function_body, @@ -148,7 +162,7 @@ fn const_eval_typed_expr( TypedExpressionVariant::StructExpression { fields, .. } => { let (field_typs, field_vals): (Vec<_>, Vec<_>) = fields .iter() - .filter_map(|TypedStructExpressionField { name: _, value }| { + .filter_map(|TypedStructExpressionField { name: _, value, .. }| { const_eval_typed_expr(context, module, known_consts, value) .map(|cv| (value.return_type, cv)) }) diff --git a/sway-core/src/ir_generation/convert.rs b/sway-core/src/ir_generation/convert.rs index e79ec305e3a..f29b981f90c 100644 --- a/sway-core/src/ir_generation/convert.rs +++ b/sway-core/src/ir_generation/convert.rs @@ -140,20 +140,3 @@ fn convert_resolved_type( TypeInfo::Storage { .. } => reject_type!("Storage"), }) } - -use uint::construct_uint; - -#[allow( -// These two warnings are generated by the `construct_uint!()` macro below. - clippy::assign_op_pattern, - clippy::ptr_offset_with_cast -)] -pub(super) fn add_to_b256(x: fuel_types::Bytes32, y: u64) -> fuel_types::Bytes32 { - construct_uint! { - struct U256(4); - } - let x = U256::from(*x); - let y = U256::from(y); - let res: [u8; 32] = (x + y).into(); - fuel_types::Bytes32::from(res) -} diff --git a/sway-core/src/ir_generation/function.rs b/sway-core/src/ir_generation/function.rs index dd39a964c07..5a49b8c7947 100644 --- a/sway-core/src/ir_generation/function.rs +++ b/sway-core/src/ir_generation/function.rs @@ -1,16 +1,21 @@ +use super::{ + compile::compile_function, + convert::*, + lexical_map::LexicalMap, + storage::{add_to_b256, get_storage_key}, + types::*, +}; use crate::{ asm_generation::from_ir::ir_type_size_in_bytes, constants, error::CompileError, + ir_generation::const_eval::compile_constant_expression, parse_tree::{AsmOp, AsmRegister, LazyOp, Literal, Purity, Visibility}, semantic_analysis::*, type_engine::{insert_type, resolve_type, TypeId, TypeInfo}, }; - -use super::{compile::compile_function, convert::*, lexical_map::LexicalMap, types::*}; - -use fuel_crypto::Hasher; -use sway_ir::*; +use sway_ir::{Context, *}; +use sway_parse::intrinsics::Intrinsic; use sway_types::{ ident::Ident, span::{Span, Spanned}, @@ -315,14 +320,22 @@ impl FnCompiler { fn compile_intrinsic_function( &mut self, context: &mut Context, - kind: TypedIntrinsicFunctionKind, + TypedIntrinsicFunctionKind { + kind, + arguments, + type_arguments, + span: _, + }: TypedIntrinsicFunctionKind, span: Span, ) -> Result { + // We safely index into arguments and type_arguments arrays below + // because the type-checker ensures that the arguments are all there. match kind { - TypedIntrinsicFunctionKind::SizeOfVal { exp } => { + Intrinsic::SizeOfVal => { + let exp = arguments[0].clone(); // Compile the expression in case of side-effects but ignore its value. let ir_type = convert_resolved_typeid(context, &exp.return_type, &exp.span)?; - self.compile_expression(context, *exp)?; + self.compile_expression(context, exp)?; Ok(Constant::get_uint( context, 64, @@ -330,8 +343,9 @@ impl FnCompiler { None, )) } - TypedIntrinsicFunctionKind::SizeOfType { type_id, type_span } => { - let ir_type = convert_resolved_typeid(context, &type_id, &type_span)?; + Intrinsic::SizeOfType => { + let targ = type_arguments[0].clone(); + let ir_type = convert_resolved_typeid(context, &targ.type_id, &targ.span)?; Ok(Constant::get_uint( context, 64, @@ -339,17 +353,30 @@ impl FnCompiler { None, )) } - TypedIntrinsicFunctionKind::IsRefType { type_id, type_span } => { - let ir_type = convert_resolved_typeid(context, &type_id, &type_span)?; + Intrinsic::IsReferenceType => { + let targ = type_arguments[0].clone(); + let ir_type = convert_resolved_typeid(context, &targ.type_id, &targ.span)?; Ok(Constant::get_bool(context, !ir_type.is_copy_type(), None)) } - TypedIntrinsicFunctionKind::GetStorageKey => { + Intrinsic::GetStorageKey => { let span_md_idx = MetadataIndex::from_span(context, &span); Ok(self .current_block .ins(context) .get_storage_key(span_md_idx, None)) } + Intrinsic::Eq => { + let lhs = arguments[0].clone(); + let rhs = arguments[1].clone(); + let lhs_value = self.compile_expression(context, lhs)?; + let rhs_value = self.compile_expression(context, rhs)?; + Ok(self.current_block.ins(context).cmp( + Predicate::Equal, + lhs_value, + rhs_value, + None, + )) + } } } @@ -369,9 +396,6 @@ impl FnCompiler { self.current_block .ins(context) .ret(ret_value, ret_ty, span_md_idx); - // RET is a terminator so we must create a new block here. If anything is added to - // it then it'll almost certainly be dead code. - self.current_block = self.function.create_block(context, None); Ok(Constant::get_unit(context, span_md_idx)) } } @@ -724,14 +748,15 @@ impl FnCompiler { if codeblock.contents.is_empty() { Some(insert_type(TypeInfo::Tuple(Vec::new()))) } else { - codeblock - .contents - .iter() - .find_map(|node| match &node.content { - TypedAstNodeContent::ReturnStatement(trs) => Some(trs.expr.return_type), - TypedAstNodeContent::ImplicitReturnExpression(te) => Some(te.return_type), - _otherwise => None, - }) + codeblock.contents.iter().find_map(|node| { + match node.gather_return_statements().first() { + Some(TypedReturnStatement { expr }) => Some(expr.return_type), + None => match &node.content { + TypedAstNodeContent::ImplicitReturnExpression(te) => Some(te.return_type), + _otherwise => None, + }, + } + }) } } @@ -765,6 +790,7 @@ impl FnCompiler { self.current_block = true_block_begin; let true_value = self.compile_expression(context, ast_then)?; let true_block_end = self.current_block; + let then_returns = true_block_end.is_terminated_by_ret(context); let false_block_begin = self.function.create_block(context, None); self.current_block = false_block_begin; @@ -773,6 +799,7 @@ impl FnCompiler { Some(expr) => self.compile_expression(context, *expr)?, }; let false_block_end = self.current_block; + let else_returns = false_block_end.is_terminated_by_ret(context); entry_block.ins(context).conditional_branch( cond_value, @@ -782,16 +809,28 @@ impl FnCompiler { cond_span_md_idx, ); + if then_returns && else_returns { + return Ok(Constant::get_unit(context, None)); + } + let merge_block = self.function.create_block(context, None); - true_block_end - .ins(context) - .branch(merge_block, Some(true_value), None); - false_block_end - .ins(context) - .branch(merge_block, Some(false_value), None); + if !then_returns { + true_block_end + .ins(context) + .branch(merge_block, Some(true_value), None); + } + if !else_returns { + false_block_end + .ins(context) + .branch(merge_block, Some(false_value), None); + } self.current_block = merge_block; - Ok(merge_block.get_phi(context)) + if !then_returns || !else_returns { + Ok(merge_block.get_phi(context)) + } else { + Ok(Constant::get_unit(context, None)) + } } fn compile_unsafe_downcast( @@ -982,29 +1021,33 @@ impl FnCompiler { // This is local to the function, so we add it to the locals, rather than the module // globals like other const decls. let TypedConstantDeclaration { name, value, .. } = ast_const_decl; + let const_expr_val = compile_constant_expression(context, self.module, &value)?; + let local_name = self.lexical_map.insert(name.as_str().to_owned()); + let return_type = convert_resolved_typeid(context, &value.return_type, &value.span)?; - if let TypedExpressionVariant::Literal(literal) = &value.expression { - let initialiser = convert_literal_to_constant(literal); - let return_type = convert_resolved_typeid(context, &value.return_type, &value.span)?; - let name = name.as_str().to_owned(); - self.function - .new_local_ptr(context, name.clone(), return_type, false, Some(initialiser)) - .map_err(|ir_error| { - CompileError::InternalOwned(ir_error.to_string(), Span::dummy()) - })?; - - // We still insert this into the symbol table, as itself... can they be shadowed? - // (Hrmm, name resolution in the variable expression code could be smarter about var - // decls vs const decls, for now they're essentially the same...) - self.lexical_map.insert(name); + // We compile consts the same as vars are compiled. This is because ASM generation + // cannot handle + // 1. initializing aggregates + // 2. get_ptr() + // into the data section. + let ptr = self + .function + .new_local_ptr(context, local_name, return_type, false, None) + .map_err(|ir_error| CompileError::InternalOwned(ir_error.to_string(), Span::dummy()))?; - Ok(Constant::get_unit(context, span_md_idx)) - } else { - Err(CompileError::Internal( - "Unsupported constant declaration type, expecting a literal.", - name.span(), - )) + // We can have empty aggregates, especially arrays, which shouldn't be initialised, but + // otherwise use a store. + let ptr_ty = *ptr.get_type(context); + if ir_type_size_in_bytes(context, &ptr_ty) > 0 { + let ptr_val = self + .current_block + .ins(context) + .get_ptr(ptr, ptr_ty, 0, span_md_idx); + self.current_block + .ins(context) + .store(ptr_val, const_expr_val, span_md_idx); } + Ok(const_expr_val) } fn compile_reassignment( @@ -1597,16 +1640,7 @@ impl FnCompiler { Ok(struct_val) } _ => { - // Calculate the storage location hash for the given field - let mut storage_slot_to_hash = format!( - "{}{}", - sway_utils::constants::STORAGE_DOMAIN_SEPARATOR, - ix.to_usize() - ); - for ix in &indices { - storage_slot_to_hash = format!("{}_{}", storage_slot_to_hash, ix); - } - let hashed_storage_slot = Hasher::hash(storage_slot_to_hash); + let storage_key = get_storage_key(ix, &indices); // New name for the key let mut key_name = format!("{}{}", "key_for_", ix.to_usize()); @@ -1626,7 +1660,7 @@ impl FnCompiler { // Const value for the key from the hash let const_key = convert_literal_to_value( context, - &Literal::B256(hashed_storage_slot.into()), + &Literal::B256(storage_key.into()), span_md_idx, ); @@ -1672,7 +1706,7 @@ impl FnCompiler { &indices, &mut key_ptr_val, &key_ptr, - &hashed_storage_slot, + &storage_key, r#type, rhs, span_md_idx, @@ -1792,7 +1826,7 @@ impl FnCompiler { indices: &[u64], key_ptr_val: &mut Value, key_ptr: &Pointer, - hashed_storage_slot: &fuel_types::Bytes32, + storage_key: &fuel_types::Bytes32, r#type: &Type, rhs: &Option, span_md_idx: Option, @@ -1850,7 +1884,7 @@ impl FnCompiler { // Const value for the key from the initial hash + array_index let const_key = convert_literal_to_value( context, - &Literal::B256(*add_to_b256(*hashed_storage_slot, array_index)), + &Literal::B256(*add_to_b256(*storage_key, array_index)), span_md_idx, ); diff --git a/sway-core/src/ir_generation/storage.rs b/sway-core/src/ir_generation/storage.rs new file mode 100644 index 00000000000..31621995bc6 --- /dev/null +++ b/sway-core/src/ir_generation/storage.rs @@ -0,0 +1,234 @@ +use crate::asm_generation::from_ir::ir_type_size_in_bytes; +use fuel_crypto::Hasher; +use fuel_tx::StorageSlot; +use fuel_types::{Bytes32, Bytes8}; +use sway_ir::{ + constant::{Constant, ConstantValue}, + context::Context, + irtype::{AggregateContent, Type}, +}; +use sway_types::state::StateIndex; + +/// Hands out storage keys using a state index and a list of subfield indices. +/// Basically returns sha256("storage____..") +/// +pub(super) fn get_storage_key(ix: &StateIndex, indices: &[T]) -> Bytes32 +where + T: std::fmt::Display, +{ + Hasher::hash(indices.iter().fold( + format!( + "{}{}", + sway_utils::constants::STORAGE_DOMAIN_SEPARATOR, + ix.to_usize() + ), + |acc, i| format!("{}_{}", acc, i), + )) +} + +use uint::construct_uint; + +#[allow( +// These two warnings are generated by the `construct_uint!()` macro below. + clippy::assign_op_pattern, + clippy::ptr_offset_with_cast +)] +pub(super) fn add_to_b256(x: fuel_types::Bytes32, y: u64) -> fuel_types::Bytes32 { + construct_uint! { + struct U256(4); + } + let x = U256::from(*x); + let y = U256::from(y); + let res: [u8; 32] = (x + y).into(); + fuel_types::Bytes32::from(res) +} + +/// Given a constant value `constant`, a type `ty`, a state index, and a vector of subfield +/// indices, serialize the constant into a vector of storage slots. The keys (slots) are +/// generated using the state index and the subfield indices which are recursively built. The +/// values are generated such that each subfield gets its own storage slot except for enums and +/// strings which are spread over successive storage slots (use `serialize_to_words` in this case). +/// +/// This behavior matches the behavior of how storage slots are assigned for storage reads and +/// writes (i.e. how `state_read_*` and `state_write_*` instructions are generated). +/// +pub fn serialize_to_storage_slots( + constant: &Constant, + context: &Context, + ix: &StateIndex, + ty: &Type, + indices: &[usize], +) -> Vec { + match (&ty, &constant.value) { + (_, ConstantValue::Undef) => vec![], + (Type::Unit, ConstantValue::Unit) => vec![StorageSlot::new( + get_storage_key(ix, indices), + Bytes32::new([0; 32]), + )], + (Type::Bool, ConstantValue::Bool(b)) => { + vec![StorageSlot::new( + get_storage_key(ix, indices), + Bytes32::new( + [0; 7] + .iter() + .cloned() + .chain([if *b { 0x01 } else { 0x00 }].iter().cloned()) + .chain([0; 24].iter().cloned()) + .collect::>() + .try_into() + .unwrap(), + ), + )] + } + (Type::Uint(_), ConstantValue::Uint(n)) => { + vec![StorageSlot::new( + get_storage_key(ix, indices), + Bytes32::new( + n.to_be_bytes() + .iter() + .cloned() + .chain([0; 24].iter().cloned()) + .collect::>() + .try_into() + .unwrap(), + ), + )] + } + (Type::B256, ConstantValue::B256(b)) => { + vec![StorageSlot::new( + get_storage_key(ix, indices), + Bytes32::new(*b), + )] + } + (Type::Array(_), ConstantValue::Array(_a)) => { + unimplemented!("Arrays in storage have not been implemented yet.") + } + (Type::Struct(aggregate), ConstantValue::Struct(vec)) => { + match &context.aggregates[aggregate.0] { + AggregateContent::FieldTypes(field_tys) => vec + .iter() + .zip(field_tys.iter()) + .enumerate() + .flat_map(|(i, (f, ty))| { + serialize_to_storage_slots( + f, + context, + ix, + ty, + &indices + .iter() + .cloned() + .chain(vec![i].iter().cloned()) + .collect::>(), + ) + }) + .collect(), + _ => unreachable!("Wrong content for struct."), + } + } + (Type::Union(_), _) | (Type::String(_), _) => { + // Serialize the constant data in words and add zero words until the number of words + // is a multiple of 4. This is useful because each storage slot is 4 words. + let mut packed = serialize_to_words(constant, context, ty); + packed.extend(vec![ + Bytes8::new([0; 8]); + ((packed.len() + 3) / 4) * 4 - packed.len() + ]); + + assert!(packed.len() % 4 == 0); + + // Return a list of `StorageSlot`s + // First get the keys then get the values + (0..(ir_type_size_in_bytes(context, ty) + 31) / 32) + .into_iter() + .map(|i| add_to_b256(get_storage_key(ix, indices), i)) + .zip((0..packed.len() / 4).into_iter().map(|i| { + Bytes32::new( + Vec::from_iter((0..4).into_iter().flat_map(|j| *packed[4 * i + j])) + .try_into() + .unwrap(), + ) + })) + .map(|(k, r)| StorageSlot::new(k, r)) + .collect() + } + _ => vec![], + } +} + +/// Given a constant value `constant` and a type `ty`, serialize the constant into a vector of +/// words and add left padding up to size of `ty`. +/// +pub fn serialize_to_words(constant: &Constant, context: &Context, ty: &Type) -> Vec { + match (&ty, &constant.value) { + (_, ConstantValue::Undef) => vec![], + (Type::Unit, ConstantValue::Unit) => vec![Bytes8::new([0; 8])], + (Type::Bool, ConstantValue::Bool(b)) => { + vec![Bytes8::new( + [0; 7] + .iter() + .cloned() + .chain([if *b { 0x01 } else { 0x00 }].iter().cloned()) + .collect::>() + .try_into() + .unwrap(), + )] + } + (Type::Uint(_), ConstantValue::Uint(n)) => { + vec![Bytes8::new(n.to_be_bytes())] + } + (Type::B256, ConstantValue::B256(b)) => Vec::from_iter( + (0..4) + .into_iter() + .map(|i| Bytes8::new(b[8 * i..8 * i + 8].try_into().unwrap())), + ), + (Type::String(_), ConstantValue::String(s)) => { + // Turn the serialized words (Bytes8) into seriliazed storage slots (Bytes32) + // Pad to word alignment + let mut s = s.clone(); + s.extend(vec![0; ((s.len() + 3) / 4) * 4 - s.len()]); + + assert!(s.len() % 8 == 0); + + // Group into words + Vec::from_iter((0..s.len() / 8).into_iter().map(|i| { + Bytes8::new( + Vec::from_iter((0..8).into_iter().map(|j| s[8 * i + j])) + .try_into() + .unwrap(), + ) + })) + } + (Type::Array(_), ConstantValue::Array(_)) => { + unimplemented!("Arrays in storage have not been implemented yet.") + } + (Type::Struct(aggregate), ConstantValue::Struct(vec)) => { + match &context.aggregates[aggregate.0] { + AggregateContent::FieldTypes(field_tys) => vec + .iter() + .zip(field_tys.iter()) + .flat_map(|(f, ty)| serialize_to_words(f, context, ty)) + .collect(), + _ => unreachable!("Wrong content for struct."), + } + } + (Type::Union(_), _) => { + let value_size_in_words = ir_type_size_in_bytes(context, ty) / 8; + let constant_size_in_words = ir_type_size_in_bytes(context, &constant.ty) / 8; + assert!(value_size_in_words >= constant_size_in_words); + + // Add enough left padding to satisfy the actual size of the union + let padding_size_in_words = value_size_in_words - constant_size_in_words; + vec![Bytes8::new([0; 8]); padding_size_in_words as usize] + .iter() + .cloned() + .chain( + serialize_to_words(constant, context, &constant.ty) + .iter() + .cloned(), + ) + .collect() + } + _ => vec![], + } +} diff --git a/sway-core/src/lib.rs b/sway-core/src/lib.rs index b965cf771fa..ac12974c364 100644 --- a/sway-core/src/lib.rs +++ b/sway-core/src/lib.rs @@ -255,8 +255,25 @@ pub fn compile_to_ast( return CompileAstResult::Failure { errors, warnings }; } + // Check that all storage initializers can be evaluated at compile time. + let CompileResult { + value: typed_program_with_storage_slots_result, + warnings: new_warnings, + errors: new_errors, + } = typed_program.get_typed_program_with_initialized_storage_slots(); + warnings.extend(new_warnings); + errors.extend(new_errors); + let typed_program_with_storage_slots = match typed_program_with_storage_slots_result { + Some(typed_program_with_storage_slots) => typed_program_with_storage_slots, + None => { + errors = dedup_unsorted(errors); + warnings = dedup_unsorted(warnings); + return CompileAstResult::Failure { errors, warnings }; + } + }; + CompileAstResult::Success { - typed_program: Box::new(typed_program), + typed_program: Box::new(typed_program_with_storage_slots), warnings, } } diff --git a/sway-core/src/parse_tree/declaration.rs b/sway-core/src/parse_tree/declaration.rs index e4bf3ab1cdc..b3dca0f4b61 100644 --- a/sway-core/src/parse_tree/declaration.rs +++ b/sway-core/src/parse_tree/declaration.rs @@ -7,8 +7,6 @@ mod reassignment; mod storage; mod r#struct; mod r#trait; -mod type_argument; -mod type_parameter; mod variable; pub(crate) use abi::*; @@ -20,8 +18,6 @@ pub use r#struct::*; pub use r#trait::*; pub(crate) use reassignment::*; pub use storage::*; -pub(crate) use type_argument::*; -pub(crate) use type_parameter::*; pub use variable::*; #[derive(Debug, Clone)] diff --git a/sway-core/src/parse_tree/declaration/enum.rs b/sway-core/src/parse_tree/declaration/enum.rs index d7d4be0cdf5..5dea55b894b 100644 --- a/sway-core/src/parse_tree/declaration/enum.rs +++ b/sway-core/src/parse_tree/declaration/enum.rs @@ -1,7 +1,4 @@ -use crate::{ - parse_tree::{declaration::TypeParameter, Visibility}, - type_engine::*, -}; +use crate::{parse_tree::Visibility, type_engine::*}; use sway_types::{ident::Ident, span::Span}; diff --git a/sway-core/src/parse_tree/declaration/impl_trait.rs b/sway-core/src/parse_tree/declaration/impl_trait.rs index 010177e347a..14fb70d84c2 100644 --- a/sway-core/src/parse_tree/declaration/impl_trait.rs +++ b/sway-core/src/parse_tree/declaration/impl_trait.rs @@ -1,5 +1,8 @@ -use super::{FunctionDeclaration, TypeParameter}; -use crate::{parse_tree::CallPath, type_engine::TypeInfo}; +use super::FunctionDeclaration; +use crate::{ + parse_tree::CallPath, + type_engine::{TypeInfo, TypeParameter}, +}; use sway_types::span::Span; diff --git a/sway-core/src/parse_tree/declaration/storage.rs b/sway-core/src/parse_tree/declaration/storage.rs index c452e33825e..a70b280e237 100644 --- a/sway-core/src/parse_tree/declaration/storage.rs +++ b/sway-core/src/parse_tree/declaration/storage.rs @@ -1,4 +1,4 @@ -use crate::type_engine::*; +use crate::{parse_tree::Expression, type_engine::*}; use sway_types::{ident::Ident, span::Span}; @@ -18,4 +18,5 @@ pub struct StorageDeclaration { pub struct StorageField { pub name: Ident, pub type_info: TypeInfo, + pub initializer: Option, } diff --git a/sway-core/src/parse_tree/declaration/struct.rs b/sway-core/src/parse_tree/declaration/struct.rs index 1faea405c96..73e39183054 100644 --- a/sway-core/src/parse_tree/declaration/struct.rs +++ b/sway-core/src/parse_tree/declaration/struct.rs @@ -1,6 +1,6 @@ use crate::{ - parse_tree::{declaration::TypeParameter, Visibility}, - type_engine::TypeInfo, + parse_tree::Visibility, + type_engine::{TypeInfo, TypeParameter}, }; use sway_types::{ident::Ident, span::Span}; diff --git a/sway-core/src/parse_tree/expression/intrinsic_function.rs b/sway-core/src/parse_tree/expression/intrinsic_function.rs deleted file mode 100644 index a6568ad8d0f..00000000000 --- a/sway-core/src/parse_tree/expression/intrinsic_function.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{type_engine::TypeInfo, Expression}; -use sway_types::Span; - -#[derive(Debug, Clone)] -pub enum IntrinsicFunctionKind { - SizeOfVal { - exp: Box, - }, - SizeOfType { - type_name: TypeInfo, - type_span: Span, - }, - IsRefType { - type_name: TypeInfo, - type_span: Span, - }, - GetStorageKey, -} diff --git a/sway-core/src/parse_tree/expression/mod.rs b/sway-core/src/parse_tree/expression/mod.rs index fe099fc83cb..e2b9c3600e1 100644 --- a/sway-core/src/parse_tree/expression/mod.rs +++ b/sway-core/src/parse_tree/expression/mod.rs @@ -1,19 +1,19 @@ use crate::{ parse_tree::{CallPath, Literal}, - CodeBlock, TypeArgument, + type_engine::TypeArgument, + CodeBlock, }; use sway_types::{ident::Ident, Span, Spanned}; mod asm; -mod intrinsic_function; mod match_branch; mod method_name; mod scrutinee; pub(crate) use asm::*; -pub use intrinsic_function::*; pub(crate) use match_branch::MatchBranch; pub use method_name::MethodName; pub use scrutinee::*; +use sway_parse::intrinsics::Intrinsic; /// Represents a parsed, but not yet type checked, [Expression](https://en.wikipedia.org/wiki/Expression_(computer_science)). #[derive(Debug, Clone)] @@ -138,7 +138,9 @@ pub enum Expression { span: Span, }, IntrinsicFunction { - kind: IntrinsicFunctionKind, + kind: Intrinsic, + arguments: Vec, + type_arguments: Vec, span: Span, }, } diff --git a/sway-core/src/parse_tree/expression/scrutinee.rs b/sway-core/src/parse_tree/expression/scrutinee.rs index 620ae2bba4a..cb75b74fe54 100644 --- a/sway-core/src/parse_tree/expression/scrutinee.rs +++ b/sway-core/src/parse_tree/expression/scrutinee.rs @@ -36,10 +36,16 @@ pub enum Scrutinee { } #[derive(Debug, Clone)] -pub struct StructScrutineeField { - pub field: Ident, - pub scrutinee: Option, - pub span: Span, +#[allow(clippy::large_enum_variant)] +pub enum StructScrutineeField { + Rest { + span: Span, + }, + Field { + field: Ident, + scrutinee: Option, + span: Span, + }, } impl Spanned for Scrutinee { @@ -122,9 +128,12 @@ impl Scrutinee { }]; let fields = fields .iter() - .flat_map(|StructScrutineeField { scrutinee, .. }| match scrutinee { - Some(scrutinee) => scrutinee.gather_approximate_typeinfo_dependencies(), - None => vec![], + .flat_map(|f| match f { + StructScrutineeField::Field { + scrutinee: Some(scrutinee), + .. + } => scrutinee.gather_approximate_typeinfo_dependencies(), + _ => vec![], }) .collect::>(); vec![name, fields].concat() diff --git a/sway-core/src/semantic_analysis.rs b/sway-core/src/semantic_analysis.rs index 2594feda433..53802ba85e2 100644 --- a/sway-core/src/semantic_analysis.rs +++ b/sway-core/src/semantic_analysis.rs @@ -4,10 +4,10 @@ mod module; pub mod namespace; mod node_dependencies; mod program; -pub(crate) mod type_check_arguments; +mod type_check_context; pub(crate) use ast_node::*; pub use ast_node::{TypedConstantDeclaration, TypedDeclaration, TypedFunctionDeclaration}; pub use module::{TypedModule, TypedSubmodule}; pub use namespace::Namespace; pub use program::{TypedProgram, TypedProgramKind}; -pub use type_check_arguments::*; +pub(crate) use type_check_context::TypeCheckContext; diff --git a/sway-core/src/semantic_analysis/ast_node/code_block.rs b/sway-core/src/semantic_analysis/ast_node/code_block.rs index 34a02f5c18f..bcc8caf34c8 100644 --- a/sway-core/src/semantic_analysis/ast_node/code_block.rs +++ b/sway-core/src/semantic_analysis/ast_node/code_block.rs @@ -1,5 +1,4 @@ use super::*; -use crate::semantic_analysis::{ast_node::Mode, TypeCheckArguments}; use crate::CodeBlock; #[derive(Clone, Debug, Eq, PartialEq)] @@ -23,41 +22,24 @@ impl DeterministicallyAborts for TypedCodeBlock { impl TypedCodeBlock { pub(crate) fn type_check( - arguments: TypeCheckArguments<'_, CodeBlock>, + mut ctx: TypeCheckContext, + code_block: CodeBlock, ) -> CompileResult<(Self, TypeId)> { let mut warnings = Vec::new(); let mut errors = Vec::new(); - let TypeCheckArguments { - checkee: other, - namespace, - return_type_annotation: type_annotation, - help_text, - self_type, - opts, - .. - } = arguments; - // Create a temp namespace for checking within the code block scope. - let mut code_block_namespace = namespace.clone(); - let evaluated_contents = other + let mut code_block_namespace = ctx.namespace.clone(); + let evaluated_contents = code_block .contents .iter() .filter_map(|node| { - TypedAstNode::type_check(TypeCheckArguments { - checkee: node.clone(), - namespace: &mut code_block_namespace, - return_type_annotation: type_annotation, - help_text, - self_type, - mode: Mode::NonAbi, - opts, - }) - .ok(&mut warnings, &mut errors) + let ctx = ctx.by_ref().scoped(&mut code_block_namespace); + TypedAstNode::type_check(ctx, node.clone()).ok(&mut warnings, &mut errors) }) .collect::>(); - let implicit_return_span = other + let implicit_return_span = code_block .contents .iter() .find_map(|x| match &x.content { @@ -76,32 +58,22 @@ impl TypedCodeBlock { .. }), .. - } => Some(*return_type), + } if !x.deterministically_aborts() => Some(*return_type), _ => None, }); if let Some(return_type) = return_type { - let (mut new_warnings, new_errors) = unify_with_self( - return_type, - type_annotation, - self_type, - &implicit_return_span.unwrap_or_else(|| other.whole_block_span.clone()), - help_text, - ); + let span = implicit_return_span.unwrap_or_else(|| code_block.whole_block_span.clone()); + let (mut new_warnings, new_errors) = ctx.unify_with_self(return_type, &span); warnings.append(&mut new_warnings); errors.append(&mut new_errors.into_iter().map(|x| x.into()).collect()); // The annotation will result in a cast, so set the return type accordingly. } - ok( - ( - TypedCodeBlock { - contents: evaluated_contents, - }, - return_type.unwrap_or_else(|| insert_type(TypeInfo::Tuple(Vec::new()))), - ), - warnings, - errors, - ) + let typed_code_block = TypedCodeBlock { + contents: evaluated_contents, + }; + let type_id = return_type.unwrap_or_else(|| insert_type(TypeInfo::Tuple(Vec::new()))); + ok((typed_code_block, type_id), warnings, errors) } } diff --git a/sway-core/src/semantic_analysis/ast_node/declaration.rs b/sway-core/src/semantic_analysis/ast_node/declaration.rs index 87344b68dc9..80ba1a40d35 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration.rs @@ -2,7 +2,6 @@ mod abi; mod r#enum; mod function; mod impl_trait; -mod monomorphize; mod storage; mod r#struct; mod r#trait; @@ -11,7 +10,6 @@ mod variable; pub use abi::*; pub use function::*; pub use impl_trait::*; -pub(crate) use monomorphize::*; pub use r#enum::*; pub use r#struct::*; pub use r#trait::*; @@ -178,6 +176,14 @@ impl UnresolvedTypeCheck for TypedDeclaration { .flat_map(UnresolvedTypeCheck::check_for_unresolved_types) .collect(), ); + body.append( + &mut decl + .parameters + .iter() + .map(|x| &x.type_id) + .flat_map(UnresolvedTypeCheck::check_for_unresolved_types) + .collect(), + ); body } ConstantDeclaration(TypedConstantDeclaration { value, .. }) => { @@ -381,6 +387,7 @@ impl TypedDeclaration { ) } TypedDeclaration::StructDeclaration(decl) => decl.create_type_id(), + TypedDeclaration::EnumDeclaration(decl) => decl.create_type_id(), TypedDeclaration::Reassignment(TypedReassignment { rhs, .. }) => rhs.return_type, TypedDeclaration::StorageDeclaration(decl) => insert_type(TypeInfo::Storage { fields: decl.fields_as_typed_struct_fields(), diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs b/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs index ce85974b14f..3a21f315060 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs @@ -3,9 +3,12 @@ use sway_types::{Ident, Span}; use crate::{ error::{err, ok}, - semantic_analysis::ast_node::{type_check_interface_surface, type_check_trait_methods}, + semantic_analysis::{ + ast_node::{type_check_interface_surface, type_check_trait_methods}, + TypeCheckContext, + }, type_engine::{insert_type, AbiName, TypeId}, - AbiDeclaration, CompileResult, FunctionDeclaration, Namespace, TypeInfo, + AbiDeclaration, CompileResult, FunctionDeclaration, TypeInfo, }; use super::{CreateTypeId, TypedTraitFn}; @@ -40,10 +43,9 @@ impl CreateTypeId for TypedAbiDeclaration { impl TypedAbiDeclaration { pub(crate) fn type_check( + ctx: TypeCheckContext, abi_decl: AbiDeclaration, - namespace: &mut Namespace, - self_type: TypeId, - ) -> CompileResult { + ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; @@ -60,7 +62,7 @@ impl TypedAbiDeclaration { // so we don't support the case of calling a contract's own interface // from itself. This is by design. let interface_surface = check!( - type_check_interface_surface(interface_surface, namespace), + type_check_interface_surface(interface_surface, ctx.namespace), return err(warnings, errors), warnings, errors @@ -68,7 +70,7 @@ impl TypedAbiDeclaration { // type check these for errors but don't actually use them yet -- the real // ones will be type checked with proper symbols when the ABI is implemented let _methods = check!( - type_check_trait_methods(methods.clone(), namespace, self_type,), + type_check_trait_methods(ctx, methods.clone()), vec![], warnings, errors diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs b/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs index fc0895b8459..c1351efc472 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs @@ -1,10 +1,10 @@ use crate::{ error::*, - namespace::*, parse_tree::*, semantic_analysis::*, type_engine::{ - insert_type, look_up_type_id, CopyTypes, CreateTypeId, ReplaceSelfType, TypeId, TypeMapping, + insert_type, look_up_type_id, CopyTypes, CreateTypeId, EnforceTypeArguments, + MonomorphizeHelper, ReplaceSelfType, TypeId, TypeMapping, TypeParameter, }, types::{JsonAbiString, ToJsonAbi}, TypeInfo, @@ -62,8 +62,6 @@ impl Spanned for TypedEnumDeclaration { } impl MonomorphizeHelper for TypedEnumDeclaration { - type Output = TypedEnumDeclaration; - fn type_parameters(&self) -> &[TypeParameter] { &self.type_parameters } @@ -71,18 +69,10 @@ impl MonomorphizeHelper for TypedEnumDeclaration { fn name(&self) -> &Ident { &self.name } - - fn monomorphize_inner(self, type_mapping: &TypeMapping, namespace: &mut Items) -> Self::Output { - monomorphize_inner(self, type_mapping, namespace) - } } impl TypedEnumDeclaration { - pub fn type_check( - decl: EnumDeclaration, - namespace: &mut Namespace, - self_type: TypeId, - ) -> CompileResult { + pub fn type_check(ctx: TypeCheckContext, decl: EnumDeclaration) -> CompileResult { let mut errors = vec![]; let mut warnings = vec![]; @@ -95,14 +85,15 @@ impl TypedEnumDeclaration { } = decl; // create a namespace for the decl, used to create a scope for generics - let mut namespace = namespace.clone(); + let mut decl_namespace = ctx.namespace.clone(); + let mut ctx = ctx.scoped(&mut decl_namespace); // type check the type parameters // insert them into the namespace let mut new_type_parameters = vec![]; for type_parameter in type_parameters.into_iter() { new_type_parameters.push(check!( - TypeParameter::type_check(type_parameter, &mut namespace), + TypeParameter::type_check(ctx.by_ref(), type_parameter), return err(warnings, errors), warnings, errors @@ -113,12 +104,7 @@ impl TypedEnumDeclaration { let mut variants_buf = vec![]; for variant in variants { variants_buf.push(check!( - TypedEnumVariant::type_check( - variant.clone(), - &mut namespace, - self_type, - variant.span, - ), + TypedEnumVariant::type_check(ctx.by_ref(), variant.clone()), continue, warnings, errors @@ -216,18 +202,15 @@ impl ReplaceSelfType for TypedEnumVariant { impl TypedEnumVariant { pub(crate) fn type_check( + mut ctx: TypeCheckContext, variant: EnumVariant, - namespace: &mut Namespace, - self_type: TypeId, - span: Span, - ) -> CompileResult { + ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; let enum_variant_type = check!( - namespace.resolve_type_with_self( - variant.type_info.clone(), - self_type, - &span, + ctx.resolve_type_with_self( + insert_type(variant.type_info), + &variant.span, EnforceTypeArguments::Yes ), insert_type(TypeInfo::ErrorRecovery), diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/function.rs b/sway-core/src/semantic_analysis/ast_node/declaration/function.rs index 9fd29ec44f6..3a6aeeef018 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/function.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/function.rs @@ -1,9 +1,7 @@ mod function_parameter; pub use function_parameter::*; -use crate::{ - error::*, namespace::*, parse_tree::*, semantic_analysis::*, style::*, type_engine::*, types::*, -}; +use crate::{error::*, parse_tree::*, semantic_analysis::*, style::*, type_engine::*, types::*}; use fuels_types::{Function, Property}; use sha2::{Digest, Sha256}; use sway_types::{Ident, Span, Spanned}; @@ -74,8 +72,6 @@ impl Spanned for TypedFunctionDeclaration { } impl MonomorphizeHelper for TypedFunctionDeclaration { - type Output = TypedFunctionDeclaration; - fn type_parameters(&self) -> &[TypeParameter] { &self.type_parameters } @@ -83,16 +79,6 @@ impl MonomorphizeHelper for TypedFunctionDeclaration { fn name(&self) -> &Ident { &self.name } - - fn monomorphize_inner( - self, - type_mapping: &TypeMapping, - _namespace: &mut Items, - ) -> Self::Output { - let mut new_decl = self; - new_decl.copy_types(type_mapping); - new_decl - } } impl ToJsonAbi for TypedFunctionDeclaration { @@ -121,19 +107,10 @@ impl ToJsonAbi for TypedFunctionDeclaration { } impl TypedFunctionDeclaration { - pub fn type_check( - arguments: TypeCheckArguments<'_, FunctionDeclaration>, - ) -> CompileResult { + pub fn type_check(ctx: TypeCheckContext, fn_decl: FunctionDeclaration) -> CompileResult { let mut warnings = Vec::new(); let mut errors = Vec::new(); - let TypeCheckArguments { - checkee: fn_decl, - namespace, - self_type, - mode, - mut opts, - .. - } = arguments; + let FunctionDeclaration { name, body, @@ -147,17 +124,18 @@ impl TypedFunctionDeclaration { .. } = fn_decl; is_snake_case(&name).ok(&mut warnings, &mut errors); - opts.purity = purity; // create a namespace for the function - let mut namespace = namespace.clone(); + let mut fn_namespace = ctx.namespace.clone(); + + let mut ctx = ctx.scoped(&mut fn_namespace).with_purity(purity); // type check the type parameters // insert them into the namespace let mut new_type_parameters = vec![]; for type_parameter in type_parameters.into_iter() { new_type_parameters.push(check!( - TypeParameter::type_check(type_parameter, &mut namespace), + TypeParameter::type_check(ctx.by_ref(), type_parameter), return err(warnings, errors), warnings, errors @@ -169,7 +147,7 @@ impl TypedFunctionDeclaration { let mut new_parameters = vec![]; for parameter in parameters.into_iter() { new_parameters.push(check!( - TypedFunctionParameter::type_check(parameter, &mut namespace, self_type), + TypedFunctionParameter::type_check(ctx.by_ref(), parameter), continue, warnings, errors @@ -178,9 +156,8 @@ impl TypedFunctionDeclaration { // type check the return type let return_type = check!( - namespace.resolve_type_with_self( - return_type, - self_type, + ctx.resolve_type_with_self( + insert_type(return_type), &return_type_span, EnforceTypeArguments::Yes ), @@ -193,24 +170,21 @@ impl TypedFunctionDeclaration { // // If there are no implicit block returns, then we do not want to type check them, so we // stifle the errors. If there _are_ implicit block returns, we want to type_check them. - let (body, _implicit_block_return) = check!( - TypedCodeBlock::type_check(TypeCheckArguments { - checkee: body, - namespace: &mut namespace, - return_type_annotation: return_type, - help_text: - "Function body's return type does not match up with its return type annotation.", - self_type, - mode: Mode::NonAbi, - opts, - }), - ( - TypedCodeBlock { contents: vec![] }, - insert_type(TypeInfo::ErrorRecovery) - ), - warnings, - errors - ); + let (body, _implicit_block_return) = { + let ctx = ctx + .by_ref() + .with_help_text("Function body's return type does not match up with its return type annotation.") + .with_type_annotation(return_type); + check!( + TypedCodeBlock::type_check(ctx, body), + ( + TypedCodeBlock { contents: vec![] }, + insert_type(TypeInfo::ErrorRecovery) + ), + warnings, + errors + ) + }; // gather the return statements let return_statements: Vec<&TypedExpression> = body @@ -222,13 +196,11 @@ impl TypedFunctionDeclaration { // unify the types of the return statements with the function return type for stmt in return_statements { - let (mut new_warnings, new_errors) = unify_with_self( - stmt.return_type, - return_type, - self_type, - &stmt.span, - "Return statement must return the declared function return type.", - ); + let (mut new_warnings, new_errors) = ctx + .by_ref() + .with_type_annotation(return_type) + .with_help_text("Return statement must return the declared function return type.") + .unify_with_self(stmt.return_type, &stmt.span); warnings.append(&mut new_warnings); errors.append(&mut new_errors.into_iter().map(|x| x.into()).collect()); } @@ -243,7 +215,7 @@ impl TypedFunctionDeclaration { return_type_span, visibility, // if this is for a contract, then it is a contract call - is_contract_call: mode == Mode::ImplAbiFn, + is_contract_call: ctx.mode() == Mode::ImplAbiFn, purity, }; diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs b/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs index 4b940621782..7d917d0552e 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs @@ -1,11 +1,11 @@ use crate::{ error::ok, semantic_analysis::{ - EnforceTypeArguments, IsConstant, TypedExpression, TypedExpressionVariant, + IsConstant, TypeCheckContext, TypedExpression, TypedExpressionVariant, TypedVariableDeclaration, VariableMutability, }, type_engine::*, - CompileResult, FunctionParameter, Ident, Namespace, TypedDeclaration, + CompileResult, FunctionParameter, Ident, TypedDeclaration, }; use sway_types::{span::Span, Spanned}; @@ -37,16 +37,14 @@ impl CopyTypes for TypedFunctionParameter { impl TypedFunctionParameter { pub(crate) fn type_check( + mut ctx: TypeCheckContext, parameter: FunctionParameter, - namespace: &mut Namespace, - self_type: TypeId, - ) -> CompileResult { + ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; let type_id = check!( - namespace.resolve_type_with_self( - look_up_type_id(parameter.type_id), - self_type, + ctx.resolve_type_with_self( + parameter.type_id, ¶meter.type_span, EnforceTypeArguments::Yes ), @@ -54,7 +52,7 @@ impl TypedFunctionParameter { warnings, errors, ); - namespace.insert_symbol( + ctx.namespace.insert_symbol( parameter.name.clone(), TypedDeclaration::VariableDeclaration(TypedVariableDeclaration { name: parameter.name.clone(), @@ -69,7 +67,6 @@ impl TypedFunctionParameter { } else { VariableMutability::Immutable }, - const_decl_origin: false, type_ascription: type_id, }), ); diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs b/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs index 325255ebe41..c663935e884 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs @@ -4,12 +4,13 @@ use sway_types::{Ident, Span, Spanned}; use crate::{ error::{err, ok}, - semantic_analysis::{Mode, TCOpts, TypeCheckArguments}, + semantic_analysis::{Mode, TypeCheckContext}, type_engine::{ - insert_type, look_up_type_id, resolve_type, unify_with_self, CopyTypes, TypeId, TypeMapping, + insert_type, look_up_type_id, resolve_type, unify_with_self, CopyTypes, TypeId, + TypeMapping, TypeParameter, }, - CallPath, CompileError, CompileResult, FunctionDeclaration, ImplSelf, ImplTrait, Namespace, - Purity, TypeInfo, TypeParameter, TypedDeclaration, TypedFunctionDeclaration, + CallPath, CompileError, CompileResult, FunctionDeclaration, ImplSelf, ImplTrait, Purity, + TypeInfo, TypedDeclaration, TypedFunctionDeclaration, }; use super::TypedTraitFn; @@ -32,10 +33,9 @@ impl CopyTypes for TypedImplTrait { impl TypedImplTrait { pub(crate) fn type_check_impl_trait( + ctx: TypeCheckContext, impl_trait: ImplTrait, - namespace: &mut Namespace, - opts: TCOpts, - ) -> CompileResult<(TypedImplTrait, TypeId)> { + ) -> CompileResult<(Self, TypeId)> { let mut errors = vec![]; let mut warnings = vec![]; @@ -49,7 +49,8 @@ impl TypedImplTrait { } = impl_trait; // create a namespace for the impl - let mut namespace = namespace.clone(); + let mut impl_namespace = ctx.namespace.clone(); + let mut ctx = ctx.scoped(&mut impl_namespace); // type check the type parameters // insert them into the namespace @@ -57,7 +58,7 @@ impl TypedImplTrait { let mut new_type_parameters = vec![]; for type_parameter in type_parameters.into_iter() { new_type_parameters.push(check!( - TypeParameter::type_check(type_parameter, &mut namespace), + TypeParameter::type_check(ctx.by_ref(), type_parameter), return err(warnings, errors), warnings, errors @@ -66,7 +67,10 @@ impl TypedImplTrait { // type check the type that we are implementing for let implementing_for_type_id = check!( - namespace.resolve_type_without_self(type_implementing_for), + ctx.namespace.resolve_type_without_self( + insert_type(type_implementing_for), + &type_implementing_for_span + ), return err(warnings, errors), warnings, errors @@ -84,7 +88,11 @@ impl TypedImplTrait { errors ); - let impl_trait = match namespace + // Update the context with the new `self` type. + let ctx = ctx.with_self_type(implementing_for_type_id); + + let impl_trait = match ctx + .namespace .resolve_call_path(&trait_name) .ok(&mut warnings, &mut errors) .cloned() @@ -92,16 +100,13 @@ impl TypedImplTrait { Some(TypedDeclaration::TraitDeclaration(tr)) => { let functions_buf = check!( type_check_trait_implementation( + ctx, &tr.interface_surface, &tr.methods, &functions, &trait_name, - &mut namespace, - implementing_for_type_id, &type_implementing_for_span, &block_span, - Mode::NonAbi, - opts, ), return err(warnings, errors), warnings, @@ -136,18 +141,17 @@ impl TypedImplTrait { }); } + let ctx = ctx.with_mode(Mode::ImplAbiFn); + let functions_buf = check!( type_check_trait_implementation( + ctx, &abi.interface_surface, &abi.methods, &functions, &trait_name, - &mut namespace, - implementing_for_type_id, &type_implementing_for_span, &block_span, - Mode::ImplAbiFn, - opts, ), return err(warnings, errors), warnings, @@ -173,10 +177,9 @@ impl TypedImplTrait { } pub(crate) fn type_check_impl_self( + ctx: TypeCheckContext, impl_self: ImplSelf, - namespace: &mut Namespace, - opts: TCOpts, - ) -> CompileResult { + ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; @@ -189,7 +192,8 @@ impl TypedImplTrait { } = impl_self; // create the namespace for the impl - let mut namespace = namespace.clone(); + let mut impl_namespace = ctx.namespace.clone(); + let mut ctx = ctx.scoped(&mut impl_namespace); // create the trait name let trait_name = CallPath { @@ -206,7 +210,7 @@ impl TypedImplTrait { let mut new_type_parameters = vec![]; for type_parameter in type_parameters.into_iter() { new_type_parameters.push(check!( - TypeParameter::type_check(type_parameter, &mut namespace), + TypeParameter::type_check(ctx.by_ref(), type_parameter), return err(warnings, errors), warnings, errors @@ -215,7 +219,10 @@ impl TypedImplTrait { // type check the type that we are implementing for let implementing_for_type_id = check!( - namespace.resolve_type_without_self(type_implementing_for), + ctx.namespace.resolve_type_without_self( + insert_type(type_implementing_for), + &type_implementing_for_span + ), return err(warnings, errors), warnings, errors @@ -233,19 +240,16 @@ impl TypedImplTrait { errors ); + let mut ctx = ctx + .with_self_type(implementing_for_type_id) + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); + // type check the methods inside of the impl block let mut methods = vec![]; for fn_decl in functions.into_iter() { methods.push(check!( - TypedFunctionDeclaration::type_check(TypeCheckArguments { - checkee: fn_decl, - namespace: &mut namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: "", - self_type: implementing_for_type_id, - mode: Mode::NonAbi, - opts, - }), + TypedFunctionDeclaration::type_check(ctx.by_ref(), fn_decl), continue, warnings, errors @@ -264,16 +268,13 @@ impl TypedImplTrait { #[allow(clippy::too_many_arguments)] fn type_check_trait_implementation( + mut ctx: TypeCheckContext, trait_interface_surface: &[TypedTraitFn], trait_methods: &[FunctionDeclaration], functions: &[FunctionDeclaration], trait_name: &CallPath, - namespace: &mut Namespace, - self_type: TypeId, self_type_span: &Span, block_span: &Span, - mode: Mode, - opts: TCOpts, ) -> CompileResult> { let mut errors = vec![]; let mut warnings = vec![]; @@ -289,17 +290,14 @@ fn type_check_trait_implementation( .map(|decl| (&decl.name, decl)) .collect(); for fn_decl in functions { + let mut ctx = ctx + .by_ref() + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); + // type check the function declaration let fn_decl = check!( - TypedFunctionDeclaration::type_check(TypeCheckArguments { - checkee: fn_decl.clone(), - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode, - opts, - }), + TypedFunctionDeclaration::type_check(ctx.by_ref(), fn_decl.clone()), continue, warnings, errors @@ -353,9 +351,9 @@ fn type_check_trait_implementation( let (mut new_warnings, new_errors) = unify_with_self( fn_decl_param_type, fn_signature_param_type, - self_type, + ctx.self_type(), &fn_signature_param.type_span, - "", + ctx.help_text(), ); warnings.append(&mut new_warnings); if !new_errors.is_empty() { @@ -393,9 +391,9 @@ fn type_check_trait_implementation( let (mut new_warnings, new_errors) = unify_with_self( fn_decl.return_type, fn_signature.return_type, - self_type, + ctx.self_type(), &fn_decl.return_type_span, - "", + ctx.help_text(), ); warnings.append(&mut new_warnings); if !new_errors.is_empty() { @@ -412,7 +410,8 @@ fn type_check_trait_implementation( // This name space is temporary! It is used only so that the below methods // can reference functions from the interface - let mut impl_trait_namespace = namespace.clone(); + let mut impl_trait_namespace = ctx.namespace.clone(); + let ctx = ctx.scoped(&mut impl_trait_namespace); // A trait impl needs access to everything that the trait methods have access to, which is // basically everything in the path where the trait is declared. @@ -420,42 +419,39 @@ fn type_check_trait_implementation( // in the symbols map and the path stored in the CallPath. let trait_path = [ &trait_name.prefixes[..], - impl_trait_namespace.get_canonical_path(&trait_name.suffix), + ctx.namespace.get_canonical_path(&trait_name.suffix), ] .concat(); - impl_trait_namespace.star_import(&trait_path); + ctx.namespace.star_import(&trait_path); - impl_trait_namespace.insert_trait_implementation( + let self_type_id = insert_type(match resolve_type(ctx.self_type(), self_type_span) { + Ok(o) => o, + Err(e) => { + errors.push(e.into()); + return err(warnings, errors); + } + }); + ctx.namespace.insert_trait_implementation( CallPath { prefixes: vec![], suffix: trait_name.suffix.clone(), is_absolute: false, }, - insert_type(match resolve_type(self_type, self_type_span) { - Ok(o) => o, - Err(e) => { - errors.push(e.into()); - return err(warnings, errors); - } - }), + self_type_id, functions_buf.clone(), ); + let mut ctx = ctx + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); + // type check the methods now that the interface // they depends upon has been implemented // use a local namespace which has the above interface inserted // into it as a trait implementation for this for method in trait_methods { let method = check!( - TypedFunctionDeclaration::type_check(TypeCheckArguments { - checkee: method.clone(), - namespace: &mut impl_trait_namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode, - opts, - }), + TypedFunctionDeclaration::type_check(ctx.by_ref(), method.clone()), continue, warnings, errors diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/monomorphize.rs b/sway-core/src/semantic_analysis/ast_node/declaration/monomorphize.rs deleted file mode 100644 index d38e781c2d1..00000000000 --- a/sway-core/src/semantic_analysis/ast_node/declaration/monomorphize.rs +++ /dev/null @@ -1,203 +0,0 @@ -use sway_types::{Ident, Span, Spanned}; - -use crate::{ - error::*, namespace::*, type_engine::*, CompileError, CompileResult, TypeArgument, TypeInfo, - TypeParameter, -}; - -use super::CreateTypeId; - -/// This type is used to denote if, during monomorphization, the compiler -/// should enforce that type arguments be provided. An example of that -/// might be this: -/// -/// ```ignore -/// struct Point { -/// x: u64, -/// y: u64 -/// } -/// -/// fn add(p1: Point, p2: Point) -> Point { -/// Point { -/// x: p1.x + p2.x, -/// y: p1.y + p2.y -/// } -/// } -/// ``` -/// -/// `EnforeTypeArguments` would require that the type annotations -/// for `p1` and `p2` contain `<...>`. This is to avoid ambiguous definitions: -/// -/// ```ignore -/// fn add(p1: Point, p2: Point) -> Point { -/// Point { -/// x: p1.x + p2.x, -/// y: p1.y + p2.y -/// } -/// } -/// ``` -#[derive(Clone, Copy)] -pub(crate) enum EnforceTypeArguments { - Yes, - No, -} - -pub(crate) trait Monomorphize { - type Output; - - fn monomorphize( - self, - type_arguments: Vec, - enforce_type_arguments: EnforceTypeArguments, - self_type: Option, - call_site_span: Option<&Span>, - namespace: &mut Root, - module_path: &Path, - ) -> CompileResult; -} - -impl Monomorphize for T -where - T: MonomorphizeHelper + Spanned, -{ - type Output = T; - - fn monomorphize( - self, - type_arguments: Vec, - enforce_type_arguments: EnforceTypeArguments, - self_type: Option, - call_site_span: Option<&Span>, - namespace: &mut Root, - module_path: &Path, - ) -> CompileResult { - let mut warnings = vec![]; - let mut errors = vec![]; - match (self.type_parameters().is_empty(), type_arguments.is_empty()) { - (true, true) => ok(self, warnings, errors), - (false, true) => { - if let EnforceTypeArguments::Yes = enforce_type_arguments { - let name_span = self.name().span(); - errors.push(CompileError::NeedsTypeArguments { - name: self.name().clone(), - span: call_site_span.unwrap_or(&name_span).clone(), - }); - return err(warnings, errors); - } - let type_mapping = insert_type_parameters(self.type_parameters()); - let module = check!( - namespace.check_submodule_mut(module_path), - return err(warnings, errors), - warnings, - errors - ); - let new_decl = self.monomorphize_inner(&type_mapping, module); - ok(new_decl, warnings, errors) - } - (true, false) => { - let type_arguments_span = type_arguments - .iter() - .map(|x| x.span.clone()) - .reduce(Span::join) - .unwrap_or_else(|| self.span()); - errors.push(CompileError::DoesNotTakeTypeArguments { - name: self.name().clone(), - span: type_arguments_span, - }); - err(warnings, errors) - } - (false, false) => { - let mut type_arguments = type_arguments; - for type_argument in type_arguments.iter_mut() { - let type_id = match self_type { - Some(self_type) => namespace.resolve_type_with_self( - look_up_type_id(type_argument.type_id), - self_type, - &type_argument.span, - enforce_type_arguments, - module_path, - ), - None => namespace.resolve_type_without_self( - look_up_type_id(type_argument.type_id), - module_path, - ), - }; - type_argument.type_id = check!( - type_id, - insert_type(TypeInfo::ErrorRecovery), - warnings, - errors - ); - } - let type_arguments_span = type_arguments - .iter() - .map(|x| x.span.clone()) - .reduce(Span::join) - .unwrap_or_else(|| self.span()); - if self.type_parameters().len() != type_arguments.len() { - errors.push(CompileError::IncorrectNumberOfTypeArguments { - given: type_arguments.len(), - expected: self.type_parameters().len(), - span: type_arguments_span, - }); - return err(warnings, errors); - } - let type_mapping = insert_type_parameters(self.type_parameters()); - for ((_, interim_type), type_argument) in - type_mapping.iter().zip(type_arguments.iter()) - { - match self_type { - Some(self_type) => { - let (mut new_warnings, new_errors) = unify_with_self( - *interim_type, - type_argument.type_id, - self_type, - &type_argument.span, - "Type argument is not assignable to generic type parameter.", - ); - warnings.append(&mut new_warnings); - errors.append(&mut new_errors.into_iter().map(|x| x.into()).collect()); - } - None => { - let (mut new_warnings, new_errors) = unify( - *interim_type, - type_argument.type_id, - &type_argument.span, - "Type argument is not assignable to generic type parameter.", - ); - warnings.append(&mut new_warnings); - errors.append(&mut new_errors.into_iter().map(|x| x.into()).collect()); - } - } - } - let module = check!( - namespace.check_submodule_mut(module_path), - return err(warnings, errors), - warnings, - errors - ); - let new_decl = self.monomorphize_inner(&type_mapping, module); - ok(new_decl, warnings, errors) - } - } - } -} - -pub(crate) trait MonomorphizeHelper { - type Output; - - fn type_parameters(&self) -> &[TypeParameter]; - fn name(&self) -> &Ident; - fn monomorphize_inner(self, type_mapping: &TypeMapping, namespace: &mut Items) -> Self::Output; -} - -pub(crate) fn monomorphize_inner(decl: T, type_mapping: &TypeMapping, namespace: &mut Items) -> T -where - T: CopyTypes + CreateTypeId, -{ - let old_type_id = decl.create_type_id(); - let mut new_decl = decl; - new_decl.copy_types(type_mapping); - namespace.copy_methods_to_type(old_type_id, new_decl.create_type_id(), type_mapping); - new_decl -} diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs b/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs index a410c787f95..6aa55ea6d34 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs @@ -1,16 +1,19 @@ -use crate::semantic_analysis::{ - TypeCheckedStorageAccess, TypeCheckedStorageAccessDescriptor, TypedStructField, -}; -use crate::type_engine::look_up_type_id; use crate::{ error::*, - type_engine::{TypeId, TypeInfo}, + ir_generation::{ + const_eval::compile_constant_expression_to_constant, storage::serialize_to_storage_slots, + }, + semantic_analysis::{ + TypeCheckedStorageAccess, TypeCheckedStorageAccessDescriptor, TypedExpression, + TypedStructField, + }, + type_engine::{look_up_type_id, TypeId, TypeInfo}, Ident, }; -use sway_types::Spanned; -use sway_types::{state::StateIndex, Span}; - use derivative::Derivative; +use fuel_tx::StorageSlot; +use sway_ir::{Context, Kind, Module}; +use sway_types::{state::StateIndex, Span, Spanned}; #[derive(Clone, Debug, Derivative)] #[derivative(PartialEq, Eq)] @@ -134,6 +137,7 @@ impl TypedStorageDeclaration { ref name, type_id: ref r#type, ref span, + .. }| TypedStructField { name: name.clone(), type_id: *r#type, @@ -142,12 +146,30 @@ impl TypedStorageDeclaration { ) .collect() } + + pub(crate) fn get_initialized_storage_slots(&self) -> CompileResult> { + let mut errors = vec![]; + let storage_slots = self + .fields + .iter() + .enumerate() + .map(|(i, f)| f.get_initialized_storage_slots(&StateIndex::new(i))) + .filter_map(|s| s.map_err(|e| errors.push(e)).ok()) + .flatten() + .collect::>(); + + match errors.is_empty() { + true => ok(storage_slots, vec![], vec![]), + false => err(vec![], errors), + } + } } #[derive(Clone, Debug, Eq)] pub struct TypedStorageField { pub name: Ident, pub type_id: TypeId, + pub initializer: Option, pub(crate) span: Span, } @@ -156,16 +178,41 @@ pub struct TypedStorageField { // https://doc.rust-lang.org/std/collections/struct.HashMap.html impl PartialEq for TypedStorageField { fn eq(&self, other: &Self) -> bool { - self.name == other.name && look_up_type_id(self.type_id) == look_up_type_id(other.type_id) + self.name == other.name + && look_up_type_id(self.type_id) == look_up_type_id(other.type_id) + && self.initializer == other.initializer } } impl TypedStorageField { - pub fn new(name: Ident, r#type: TypeId, span: Span) -> Self { + pub fn new( + name: Ident, + r#type: TypeId, + initializer: Option, + span: Span, + ) -> Self { TypedStorageField { name, type_id: r#type, + initializer, span, } } + + pub fn get_initialized_storage_slots( + &self, + ix: &StateIndex, + ) -> Result, CompileError> { + let mut context = Context::default(); + let module = Module::new(&mut context, Kind::Contract); + match &self.initializer { + None => Ok(vec![]), + Some(initializer) => compile_constant_expression_to_constant( + &mut context, + module, + initializer, + ) + .map(|constant| serialize_to_storage_slots(&constant, &context, ix, &constant.ty, &[])), + } + } } diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs b/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs index 4306f5ffc88..0e56fd372f9 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs @@ -1,6 +1,4 @@ -use crate::{ - error::*, namespace::*, parse_tree::*, semantic_analysis::*, type_engine::*, types::*, -}; +use crate::{error::*, parse_tree::*, semantic_analysis::*, type_engine::*, types::*}; use fuels_types::Property; use std::hash::{Hash, Hasher}; use sway_types::{Ident, Span, Spanned}; @@ -54,8 +52,6 @@ impl Spanned for TypedStructDeclaration { } impl MonomorphizeHelper for TypedStructDeclaration { - type Output = TypedStructDeclaration; - fn type_parameters(&self) -> &[TypeParameter] { &self.type_parameters } @@ -63,18 +59,13 @@ impl MonomorphizeHelper for TypedStructDeclaration { fn name(&self) -> &Ident { &self.name } - - fn monomorphize_inner(self, type_mapping: &TypeMapping, namespace: &mut Items) -> Self::Output { - monomorphize_inner(self, type_mapping, namespace) - } } impl TypedStructDeclaration { pub(crate) fn type_check( + ctx: TypeCheckContext, decl: StructDeclaration, - namespace: &mut Namespace, - self_type: TypeId, - ) -> CompileResult { + ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; @@ -87,14 +78,15 @@ impl TypedStructDeclaration { } = decl; // create a namespace for the decl, used to create a scope for generics - let mut namespace = namespace.clone(); + let mut decl_namespace = ctx.namespace.clone(); + let mut ctx = ctx.scoped(&mut decl_namespace); // type check the type parameters // insert them into the namespace let mut new_type_parameters = vec![]; for type_parameter in type_parameters.into_iter() { new_type_parameters.push(check!( - TypeParameter::type_check(type_parameter, &mut namespace), + TypeParameter::type_check(ctx.by_ref(), type_parameter), return err(warnings, errors), warnings, errors @@ -105,7 +97,7 @@ impl TypedStructDeclaration { let mut new_fields = vec![]; for field in fields.into_iter() { new_fields.push(check!( - TypedStructField::type_check(field, &mut namespace, self_type), + TypedStructField::type_check(ctx.by_ref(), field), return err(warnings, errors), warnings, errors @@ -201,17 +193,12 @@ impl ReplaceSelfType for TypedStructField { } impl TypedStructField { - pub(crate) fn type_check( - field: StructField, - namespace: &mut Namespace, - self_type: TypeId, - ) -> CompileResult { + pub(crate) fn type_check(mut ctx: TypeCheckContext, field: StructField) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; let r#type = check!( - namespace.resolve_type_with_self( - field.type_info, - self_type, + ctx.resolve_type_with_self( + insert_type(field.type_info), &field.type_span, EnforceTypeArguments::Yes ), diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs b/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs index c0e1a9d1e31..64936e9d860 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs @@ -5,10 +5,10 @@ use crate::{ error::{err, ok}, semantic_analysis::{ ast_node::{type_check_interface_surface, type_check_trait_methods}, - Mode, TypedCodeBlock, + Mode, TypeCheckContext, TypedCodeBlock, }, style::is_upper_camel_case, - type_engine::{insert_type, look_up_type_id, CopyTypes, TypeMapping}, + type_engine::{insert_type, CopyTypes, TypeMapping}, CallPath, CompileError, CompileResult, FunctionDeclaration, FunctionParameter, Namespace, Supertrait, TraitDeclaration, TypeInfo, TypedDeclaration, TypedFunctionDeclaration, Visibility, }; @@ -41,9 +41,9 @@ impl CopyTypes for TypedTraitDeclaration { impl TypedTraitDeclaration { pub(crate) fn type_check( + ctx: TypeCheckContext, trait_decl: TraitDeclaration, - namespace: &mut Namespace, - ) -> CompileResult { + ) -> CompileResult { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -51,18 +51,19 @@ impl TypedTraitDeclaration { // type check the interface surface let interface_surface = check!( - type_check_interface_surface(trait_decl.interface_surface.to_vec(), namespace), + type_check_interface_surface(trait_decl.interface_surface.to_vec(), ctx.namespace), return err(warnings, errors), warnings, errors ); // A temporary namespace for checking within the trait's scope. - let mut namespace = namespace.clone(); + let mut trait_namespace = ctx.namespace.clone(); + let ctx = ctx.scoped(&mut trait_namespace); // Recursively handle supertraits: make their interfaces and methods available to this trait check!( - handle_supertraits(&trait_decl.supertraits, &mut namespace), + handle_supertraits(&trait_decl.supertraits, ctx.namespace), return err(warnings, errors), warnings, errors @@ -70,7 +71,7 @@ impl TypedTraitDeclaration { // insert placeholder functions representing the interface surface // to allow methods to use those functions - namespace.insert_trait_implementation( + ctx.namespace.insert_trait_implementation( CallPath { prefixes: vec![], suffix: trait_decl.name.clone(), @@ -83,12 +84,9 @@ impl TypedTraitDeclaration { .collect(), ); // check the methods for errors but throw them away and use vanilla [FunctionDeclaration]s + let ctx = ctx.with_self_type(insert_type(TypeInfo::SelfType)); let _methods = check!( - type_check_trait_methods( - trait_decl.methods.clone(), - &mut namespace, - insert_type(TypeInfo::SelfType), - ), + type_check_trait_methods(ctx, trait_decl.methods.clone()), vec![], warnings, errors @@ -205,7 +203,7 @@ fn convert_trait_methods_to_dummy_funcs( is_mutable: *is_mutable, type_id: check!( trait_namespace.resolve_type_with_self( - look_up_type_id(*type_id), + *type_id, insert_type(TypeInfo::SelfType), type_span, EnforceTypeArguments::Yes @@ -221,7 +219,7 @@ fn convert_trait_methods_to_dummy_funcs( span: name.span(), return_type: check!( trait_namespace.resolve_type_with_self( - return_type.clone(), + insert_type(return_type.clone()), insert_type(TypeInfo::SelfType), return_type_span, EnforceTypeArguments::Yes diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/variable.rs b/sway-core/src/semantic_analysis/ast_node/declaration/variable.rs index 43017159b81..8219279cb57 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/variable.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/variable.rs @@ -1,4 +1,4 @@ -use crate::{constants::*, error::*, semantic_analysis::*, type_engine::*, Ident, Visibility}; +use crate::{semantic_analysis::*, type_engine::*, Ident, Visibility}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum VariableMutability { @@ -52,7 +52,6 @@ pub struct TypedVariableDeclaration { pub body: TypedExpression, pub(crate) is_mutable: VariableMutability, pub type_ascription: TypeId, - pub(crate) const_decl_origin: bool, } // NOTE: Hash and PartialEq must uphold the invariant: @@ -64,7 +63,6 @@ impl PartialEq for TypedVariableDeclaration { && self.body == other.body && self.is_mutable == other.is_mutable && look_up_type_id(self.type_ascription) == look_up_type_id(other.type_ascription) - && self.const_decl_origin == other.const_decl_origin } } @@ -75,21 +73,3 @@ impl CopyTypes for TypedVariableDeclaration { self.body.copy_types(type_mapping) } } - -// there are probably more names we should check here, this is the only one that will result in an -// actual issue right now, though -pub fn check_if_name_is_invalid(name: &Ident) -> CompileResult<()> { - INVALID_NAMES - .iter() - .find_map(|x| { - if *x == name.as_str() { - Some(err( - vec![], - [CompileError::InvalidVariableName { name: name.clone() }].to_vec(), - )) - } else { - None - } - }) - .unwrap_or_else(|| ok((), vec![], vec![])) -} diff --git a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs index ffa34ff0d7a..1d363ab136a 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs @@ -1,181 +1,243 @@ use std::fmt; +use itertools::Itertools; +use sway_parse::intrinsics::Intrinsic; use sway_types::Span; use crate::{ error::{err, ok}, - semantic_analysis::{EnforceTypeArguments, Mode, TCOpts, TypeCheckArguments}, + semantic_analysis::TypeCheckContext, type_engine::*, types::DeterministicallyAborts, - CompileError, CompileResult, IntrinsicFunctionKind, Namespace, + CompileError, CompileResult, Expression, }; use super::TypedExpression; -#[derive(Debug, Clone)] -pub enum TypedIntrinsicFunctionKind { - SizeOfVal { exp: Box }, - SizeOfType { type_id: TypeId, type_span: Span }, - IsRefType { type_id: TypeId, type_span: Span }, - GetStorageKey, -} - -// 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 TypedIntrinsicFunctionKind { - fn eq(&self, other: &Self) -> bool { - use TypedIntrinsicFunctionKind::*; - match (self, other) { - (SizeOfVal { exp: l_exp }, SizeOfVal { exp: r_exp }) => *l_exp == *r_exp, - ( - SizeOfType { - type_id: l_type_id, .. - }, - SizeOfType { - type_id: r_type_id, .. - }, - ) => look_up_type_id(*l_type_id) == look_up_type_id(*r_type_id), - ( - IsRefType { - type_id: l_type_id, .. - }, - IsRefType { - type_id: r_type_id, .. - }, - ) => look_up_type_id(*l_type_id) == look_up_type_id(*r_type_id), - (GetStorageKey, GetStorageKey) => true, - _ => false, - } - } +#[derive(Debug, Clone, PartialEq)] +pub struct TypedIntrinsicFunctionKind { + pub kind: Intrinsic, + pub arguments: Vec, + pub type_arguments: Vec, + pub span: Span, } impl CopyTypes for TypedIntrinsicFunctionKind { fn copy_types(&mut self, type_mapping: &TypeMapping) { - use TypedIntrinsicFunctionKind::*; - match self { - SizeOfVal { exp } => { - exp.copy_types(type_mapping); - } - SizeOfType { type_id, type_span } => { - type_id.update_type(type_mapping, type_span); - } - IsRefType { type_id, type_span } => { - type_id.update_type(type_mapping, type_span); - } - GetStorageKey => {} + for arg in &mut self.arguments { + arg.copy_types(type_mapping); + } + for targ in &mut self.type_arguments { + targ.type_id.update_type(type_mapping, &targ.span); } } } impl fmt::Display for TypedIntrinsicFunctionKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use TypedIntrinsicFunctionKind::*; - let s = match self { - SizeOfVal { exp } => format!("size_of_val({})", exp), - SizeOfType { type_id, .. } => format!("size_of({})", look_up_type_id(*type_id)), - IsRefType { type_id, .. } => format!("is_ref_type({})", look_up_type_id(*type_id)), - GetStorageKey => "get_storage_key".to_string(), - }; - write!(f, "{}", s) + let targs = self + .type_arguments + .iter() + .map(|targ| look_up_type_id(targ.type_id)) + .join(", "); + let args = self.arguments.iter().map(|e| format!("{}", e)).join(", "); + + write!(f, "{}::<{}>::({})", self.kind, targs, args) } } impl DeterministicallyAborts for TypedIntrinsicFunctionKind { fn deterministically_aborts(&self) -> bool { - use TypedIntrinsicFunctionKind::*; - match self { - SizeOfVal { exp } => exp.deterministically_aborts(), - SizeOfType { .. } | GetStorageKey | IsRefType { .. } => false, - } + self.arguments.iter().any(|x| x.deterministically_aborts()) } } impl UnresolvedTypeCheck for TypedIntrinsicFunctionKind { fn check_for_unresolved_types(&self) -> Vec { - use TypedIntrinsicFunctionKind::*; - match self { - SizeOfVal { exp } => exp.check_for_unresolved_types(), - SizeOfType { type_id, .. } => type_id.check_for_unresolved_types(), - IsRefType { type_id, .. } => type_id.check_for_unresolved_types(), - GetStorageKey => vec![], - } + self.type_arguments + .iter() + .flat_map(|targ| targ.type_id.check_for_unresolved_types()) + .chain( + self.arguments + .iter() + .flat_map(UnresolvedTypeCheck::check_for_unresolved_types), + ) + .collect() } } impl TypedIntrinsicFunctionKind { pub(crate) fn type_check( - kind: IntrinsicFunctionKind, - self_type: TypeId, - namespace: &mut Namespace, - opts: TCOpts, - ) -> CompileResult<(TypedIntrinsicFunctionKind, TypeId)> { + mut ctx: TypeCheckContext, + kind: Intrinsic, + type_arguments: Vec, + arguments: Vec, + span: Span, + ) -> CompileResult<(Self, TypeId)> { let mut warnings = vec![]; let mut errors = vec![]; let (intrinsic_function, return_type) = match kind { - IntrinsicFunctionKind::SizeOfVal { exp } => { + Intrinsic::SizeOfVal => { + if arguments.len() != 1 { + errors.push(CompileError::IntrinsicIncorrectNumArgs { + name: kind.to_string(), + expected: 1, + span, + }); + return err(warnings, errors); + } + let ctx = ctx + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); let exp = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: *exp, - namespace, - self_type, - mode: Mode::NonAbi, - opts, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - }), + TypedExpression::type_check(ctx, arguments[0].clone()), return err(warnings, errors), warnings, errors ); - let intrinsic_function = - TypedIntrinsicFunctionKind::SizeOfVal { exp: Box::new(exp) }; + let intrinsic_function = TypedIntrinsicFunctionKind { + kind, + arguments: vec![exp], + type_arguments: vec![], + span, + }; let return_type = insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)); (intrinsic_function, return_type) } - IntrinsicFunctionKind::SizeOfType { - type_name, - type_span, - } => { + Intrinsic::SizeOfType => { + if !arguments.is_empty() { + errors.push(CompileError::IntrinsicIncorrectNumArgs { + name: kind.to_string(), + expected: 0, + span, + }); + return err(warnings, errors); + } + if type_arguments.len() != 1 { + errors.push(CompileError::IntrinsicIncorrectNumTArgs { + name: kind.to_string(), + expected: 1, + span, + }); + return err(warnings, errors); + } + let targ = type_arguments[0].clone(); let type_id = check!( - namespace.resolve_type_with_self( - type_name, - self_type, - &type_span, + ctx.resolve_type_with_self( + insert_type(resolve_type(targ.type_id, &targ.span).unwrap()), + &targ.span, EnforceTypeArguments::Yes ), insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); - let intrinsic_function = - TypedIntrinsicFunctionKind::SizeOfType { type_id, type_span }; + let intrinsic_function = TypedIntrinsicFunctionKind { + kind, + arguments: vec![], + type_arguments: vec![TypeArgument { + type_id, + span: targ.span, + }], + span, + }; let return_type = insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)); (intrinsic_function, return_type) } - IntrinsicFunctionKind::IsRefType { - type_name, - type_span, - } => { + Intrinsic::IsReferenceType => { + if type_arguments.len() != 1 { + errors.push(CompileError::IntrinsicIncorrectNumTArgs { + name: kind.to_string(), + expected: 1, + span, + }); + return err(warnings, errors); + } + let targ = type_arguments[0].clone(); let type_id = check!( - namespace.resolve_type_with_self( - type_name, - self_type, - &type_span, + ctx.resolve_type_with_self( + insert_type(resolve_type(targ.type_id, &targ.span).unwrap()), + &targ.span, EnforceTypeArguments::Yes ), insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); - let intrinsic_function = - TypedIntrinsicFunctionKind::IsRefType { type_id, type_span }; + let intrinsic_function = TypedIntrinsicFunctionKind { + kind, + arguments: vec![], + type_arguments: vec![TypeArgument { + type_id, + span: targ.span, + }], + span, + }; (intrinsic_function, insert_type(TypeInfo::Boolean)) } - IntrinsicFunctionKind::GetStorageKey => ( - TypedIntrinsicFunctionKind::GetStorageKey, + Intrinsic::GetStorageKey => ( + TypedIntrinsicFunctionKind { + kind, + arguments: vec![], + type_arguments: vec![], + span, + }, insert_type(TypeInfo::B256), ), + Intrinsic::Eq => { + if arguments.len() != 2 { + errors.push(CompileError::IntrinsicIncorrectNumArgs { + name: kind.to_string(), + expected: 2, + span, + }); + return err(warnings, errors); + } + let mut ctx = ctx + .by_ref() + .with_type_annotation(insert_type(TypeInfo::Unknown)); + + let lhs = arguments[0].clone(); + let lhs = check!( + TypedExpression::type_check(ctx.by_ref(), lhs), + return err(warnings, errors), + warnings, + errors + ); + + // Check for supported argument types + let arg_ty = resolve_type(lhs.return_type, &lhs.span).unwrap(); + let is_valid_arg_ty = matches!(arg_ty, TypeInfo::UnsignedInteger(_)) + || matches!(arg_ty, TypeInfo::Boolean); + if !is_valid_arg_ty { + errors.push(CompileError::IntrinsicUnsupportedArgType { + name: kind.to_string(), + span: lhs.span, + }); + return err(warnings, errors); + } + + let rhs = arguments[1].clone(); + let ctx = ctx + .by_ref() + .with_help_text("Incorrect argument type") + .with_type_annotation(lhs.return_type); + let rhs = check!( + TypedExpression::type_check(ctx, rhs), + return err(warnings, errors), + warnings, + errors + ); + ( + TypedIntrinsicFunctionKind { + kind, + arguments: vec![lhs, rhs], + type_arguments: vec![], + span, + }, + insert_type(TypeInfo::Boolean), + ) + } }; ok((intrinsic_function, return_type), warnings, errors) } diff --git a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/analysis/pattern.rs b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/analysis/pattern.rs index b8ef31573db..26acf90ea09 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/analysis/pattern.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/analysis/pattern.rs @@ -140,20 +140,22 @@ impl Pattern { .. } => { let mut new_fields = vec![]; - for StructScrutineeField { - field, scrutinee, .. - } in fields.into_iter() - { - let f = match scrutinee { - Some(scrutinee) => check!( - Pattern::from_scrutinee(scrutinee), - return err(warnings, errors), - warnings, - errors - ), - None => Pattern::Wildcard, - }; - new_fields.push((field.as_str().to_string(), f)); + for field in fields.into_iter() { + if let StructScrutineeField::Field { + field, scrutinee, .. + } = field + { + let f = match scrutinee { + Some(scrutinee) => check!( + Pattern::from_scrutinee(scrutinee), + return err(warnings, errors), + warnings, + errors + ), + None => Pattern::Wildcard, + }; + new_fields.push((field.as_str().to_string(), f)); + } } Pattern::Struct(StructPattern { struct_name: struct_name.to_string(), diff --git a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_branch.rs b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_branch.rs index dd634a5614a..c0862dc9590 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_branch.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_branch.rs @@ -4,10 +4,10 @@ use crate::{ error::{err, ok}, semantic_analysis::{ ast_node::expression::match_expression::typed::typed_scrutinee::TypedScrutinee, IsConstant, - TypeCheckArguments, TypedAstNode, TypedAstNodeContent, TypedCodeBlock, TypedExpression, + TypeCheckContext, TypedAstNode, TypedAstNodeContent, TypedCodeBlock, TypedExpression, TypedExpressionVariant, TypedVariableDeclaration, VariableMutability, }, - type_engine::{insert_type, unify_with_self}, + type_engine::insert_type, types::DeterministicallyAborts, CompileResult, MatchBranch, TypeInfo, TypedDeclaration, }; @@ -24,21 +24,13 @@ pub(crate) struct TypedMatchBranch { impl TypedMatchBranch { pub(crate) fn type_check( - arguments: TypeCheckArguments<'_, (&TypedExpression, MatchBranch)>, + mut ctx: TypeCheckContext, + typed_value: &TypedExpression, + branch: MatchBranch, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; - let TypeCheckArguments { - checkee: (typed_value, branch), - namespace, - return_type_annotation, - self_type, - opts, - help_text, - mode, - } = arguments; - let MatchBranch { scrutinee, result, @@ -47,7 +39,7 @@ impl TypedMatchBranch { // type check the scrutinee let typed_scrutinee = check!( - TypedScrutinee::type_check(scrutinee, namespace, self_type), + TypedScrutinee::type_check(ctx.by_ref(), scrutinee), return err(warnings, errors), warnings, errors @@ -55,14 +47,15 @@ impl TypedMatchBranch { // calculate the requirements map and the declarations map let (match_req_map, match_decl_map) = check!( - matcher(typed_value, typed_scrutinee, namespace), + matcher(typed_value, typed_scrutinee, ctx.namespace), return err(warnings, errors), warnings, errors ); // create a new namespace for this branch - let mut namespace = namespace.clone(); + let mut namespace = ctx.namespace.clone(); + let mut ctx = ctx.scoped(&mut namespace); // for every item in the declarations map, create a variable declaration, // insert it into the branch namespace, and add it to a block of code statements @@ -75,9 +68,8 @@ impl TypedMatchBranch { body: right_decl, is_mutable: VariableMutability::Immutable, type_ascription, - const_decl_origin: false, }); - namespace.insert_symbol(left_decl, var_decl.clone()); + ctx.namespace.insert_symbol(left_decl, var_decl.clone()); code_block_contents.push(TypedAstNode { content: TypedAstNodeContent::Declaration(var_decl), span, @@ -85,30 +77,22 @@ impl TypedMatchBranch { } // type check the branch result - let typed_result = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: result, - namespace: &mut namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text, - self_type, - mode, - opts, - }), - return err(warnings, errors), - warnings, - errors - ); + let typed_result = { + let ctx = ctx + .by_ref() + .with_type_annotation(insert_type(TypeInfo::Unknown)); + check!( + TypedExpression::type_check(ctx, result), + return err(warnings, errors), + warnings, + errors + ) + }; // unify the return type from the typed result with the type annotation if !typed_result.deterministically_aborts() { - let (mut new_warnings, new_errors) = unify_with_self( - typed_result.return_type, - return_type_annotation, - self_type, - &typed_result.span, - help_text, - ); + let (mut new_warnings, new_errors) = + ctx.unify_with_self(typed_result.return_type, &typed_result.span); warnings.append(&mut new_warnings); errors.append(&mut new_errors.into_iter().map(|x| x.into()).collect()); } diff --git a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs index 431f7ae4735..74cc4a1ba17 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs @@ -6,8 +6,7 @@ use crate::{ ast_node::expression::typed_expression::{ instantiate_if_expression, instantiate_lazy_operator, }, - namespace::Namespace, - IsConstant, TypeCheckArguments, TypedExpression, TypedExpressionVariant, + IsConstant, TypeCheckContext, TypedExpression, TypedExpressionVariant, }, type_engine::{insert_type, TypeId}, CompileError, CompileResult, LazyOp, Literal, MatchBranch, TypeInfo, @@ -25,35 +24,21 @@ pub(crate) struct TypedMatchExpression { impl TypedMatchExpression { pub(crate) fn type_check( - arguments: TypeCheckArguments<'_, (TypedExpression, Vec)>, + ctx: TypeCheckContext, + typed_value: TypedExpression, + branches: Vec, span: Span, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; - let TypeCheckArguments { - checkee: (typed_value, branches), - namespace, - return_type_annotation, - self_type, - opts, - mode, - .. - } = arguments; - // type check all of the branches let mut typed_branches = vec![]; + let mut ctx = + ctx.with_help_text("all branches of a match statement must return the same type"); for branch in branches.into_iter() { let typed_branch = check!( - TypedMatchBranch::type_check(TypeCheckArguments { - checkee: (&typed_value, branch), - namespace, - return_type_annotation, - help_text: "all branches of a match statement must return the same type", - self_type, - mode, - opts, - }), + TypedMatchBranch::type_check(ctx.by_ref(), &typed_value, branch), continue, warnings, errors @@ -67,7 +52,7 @@ impl TypedMatchExpression { let exp = TypedMatchExpression { branches: typed_branches, - return_type_id: return_type_annotation, + return_type_id: ctx.type_annotation(), span, }; ok(exp, warnings, errors) @@ -75,8 +60,7 @@ impl TypedMatchExpression { pub(crate) fn convert_to_typed_if_expression( self, - namespace: &mut Namespace, - self_type: TypeId, + mut ctx: TypeCheckContext, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; @@ -95,13 +79,9 @@ impl TypedMatchExpression { let mut conditional: Option = None; for (left_req, right_req) in conditions.into_iter().rev() { let joined_span = Span::join(left_req.span.clone(), right_req.span.clone()); + let args = vec![left_req, right_req]; let new_condition = check!( - TypedExpression::core_ops_eq( - vec![left_req, right_req], - joined_span, - namespace, - self_type - ), + TypedExpression::core_ops_eq(ctx.by_ref(), args, joined_span), continue, warnings, errors @@ -135,7 +115,7 @@ impl TypedMatchExpression { Some(result), // TODO: this is a really bad hack and we should not do this result_span, self.return_type_id, // TODO: figure out if this argument matters or not - self_type + ctx.self_type() ), continue, warnings, @@ -156,7 +136,7 @@ impl TypedMatchExpression { Some(prev_if_exp), result_span, self.return_type_id, - self_type + ctx.self_type() ), continue, warnings, @@ -171,7 +151,7 @@ impl TypedMatchExpression { Some(prev_if_exp), result_span, self.return_type_id, - self_type + ctx.self_type() ), continue, warnings, diff --git a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_scrutinee.rs b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_scrutinee.rs index 62489f31118..cddbaa66b5c 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_scrutinee.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_scrutinee.rs @@ -1,14 +1,10 @@ use sway_types::{Ident, Span, Spanned}; -use crate::semantic_analysis::declaration::EnforceTypeArguments; -use crate::semantic_analysis::namespace::Namespace; -use crate::semantic_analysis::TypedEnumVariant; -use crate::type_engine::CreateTypeId; -use crate::CompileError; use crate::{ error::{err, ok}, - type_engine::{insert_type, TypeId}, - CompileResult, Literal, Scrutinee, TypeArgument, TypeInfo, + semantic_analysis::{TypeCheckContext, TypedEnumVariant}, + type_engine::{insert_type, CreateTypeId, EnforceTypeArguments, TypeArgument, TypeId}, + CompileError, CompileResult, Literal, Scrutinee, StructScrutineeField, TypeInfo, }; #[derive(Debug, Clone)] @@ -41,9 +37,8 @@ pub(crate) struct TypedStructScrutineeField { impl TypedScrutinee { pub(crate) fn type_check( + mut ctx: TypeCheckContext, scrutinee: Scrutinee, - namespace: &mut Namespace, - self_type: TypeId, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; @@ -70,25 +65,24 @@ impl TypedScrutinee { } => { // find the struct definition from the name let unknown_decl = check!( - namespace.resolve_symbol(&struct_name).cloned(), + ctx.namespace.resolve_symbol(&struct_name).cloned(), return err(warnings, errors), warnings, errors ); - let struct_decl = check!( + let mut struct_decl = check!( unknown_decl.expect_struct().cloned(), return err(warnings, errors), warnings, errors ); // monomorphize the struct definition - let struct_decl = check!( - namespace.monomorphize( - struct_decl, + check!( + ctx.monomorphize( + &mut struct_decl, vec!(), EnforceTypeArguments::No, - Some(self_type), - None + &struct_name.span() ), return err(warnings, errors), warnings, @@ -96,29 +90,55 @@ impl TypedScrutinee { ); // type check the fields let mut typed_fields = vec![]; + let mut rest_pattern = None; for field in fields.into_iter() { - // ensure that the struct definition has this field - let _ = check!( - struct_decl.expect_field(&field.field), - return err(warnings, errors), - warnings, - errors - ); - // type check the nested scrutinee - let typed_scrutinee = match field.scrutinee { - None => None, - Some(scrutinee) => Some(check!( - TypedScrutinee::type_check(scrutinee, namespace, self_type), - return err(warnings, errors), - warnings, - errors - )), - }; - typed_fields.push(TypedStructScrutineeField { - field: field.field, - scrutinee: typed_scrutinee, - span: field.span, + match field { + StructScrutineeField::Rest { .. } => rest_pattern = Some(field), + StructScrutineeField::Field { + field, + scrutinee, + span, + } => { + // ensure that the struct definition has this field + let _ = check!( + struct_decl.expect_field(&field), + return err(warnings, errors), + warnings, + errors + ); + // type check the nested scrutinee + let typed_scrutinee = match scrutinee { + None => None, + Some(scrutinee) => Some(check!( + TypedScrutinee::type_check(ctx.by_ref(), scrutinee), + return err(warnings, errors), + warnings, + errors + )), + }; + typed_fields.push(TypedStructScrutineeField { + field, + scrutinee: typed_scrutinee, + span, + }); + } + } + } + // ensure that the pattern uses all fields of the struct unless the rest pattern is present + if (struct_decl.fields.len() != typed_fields.len()) && rest_pattern.is_none() { + let missing_fields = struct_decl + .fields + .iter() + .filter(|f| !typed_fields.iter().any(|tf| f.name == tf.field)) + .map(|f| f.name.to_string()) + .collect::>(); + + errors.push(CompileError::MatchStructPatternMissingFields { + span, + missing_fields, }); + + return err(warnings, errors); } TypedScrutinee { variant: TypedScrutineeVariant::StructScrutinee(typed_fields), @@ -144,25 +164,24 @@ impl TypedScrutinee { let variant_name = call_path.suffix; // find the enum definition from the name let unknown_decl = check!( - namespace.resolve_symbol(enum_name).cloned(), + ctx.namespace.resolve_symbol(enum_name).cloned(), return err(warnings, errors), warnings, errors ); - let enum_decl = check!( + let mut enum_decl = check!( unknown_decl.expect_enum().cloned(), return err(warnings, errors), warnings, errors ); // monomorphize the enum definition - let enum_decl = check!( - namespace.monomorphize( - enum_decl, + check!( + ctx.monomorphize( + &mut enum_decl, vec!(), EnforceTypeArguments::No, - Some(self_type), - None + &enum_name.span() ), return err(warnings, errors), warnings, @@ -178,7 +197,7 @@ impl TypedScrutinee { ); // type check the nested scrutinee let typed_value = check!( - TypedScrutinee::type_check(*value, namespace, self_type), + TypedScrutinee::type_check(ctx, *value), return err(warnings, errors), warnings, errors @@ -196,7 +215,7 @@ impl TypedScrutinee { let mut typed_elems = vec![]; for elem in elems.into_iter() { typed_elems.push(check!( - TypedScrutinee::type_check(elem, namespace, self_type), + TypedScrutinee::type_check(ctx.by_ref(), elem), continue, warnings, errors 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 3becc8e00c2..71873e87c5d 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 @@ -16,6 +16,7 @@ use crate::{ error::*, parse_tree::*, semantic_analysis::*, type_engine::*, types::DeterministicallyAborts, }; +use sway_parse::intrinsics::Intrinsic; use sway_types::{Ident, Span, Spanned}; use std::{ @@ -65,128 +66,151 @@ impl fmt::Display for TypedExpression { impl UnresolvedTypeCheck for TypedExpression { fn check_for_unresolved_types(&self) -> Vec { use TypedExpressionVariant::*; + let mut res = self.return_type.check_for_unresolved_types(); match &self.expression { FunctionApplication { arguments, function_body, .. } => { - let mut args = arguments - .iter() - .map(|x| &x.1) - .flat_map(UnresolvedTypeCheck::check_for_unresolved_types) - .collect::>(); - args.append( + res.append( + &mut arguments + .iter() + .map(|x| &x.1) + .flat_map(UnresolvedTypeCheck::check_for_unresolved_types) + .collect::>(), + ); + res.append( &mut function_body .contents .iter() .flat_map(UnresolvedTypeCheck::check_for_unresolved_types) .collect(), ); - args } - // expressions don't ever have return types themselves, they're stored in - // `TypedExpression::return_type`. Variable expressions are just names of variables. - VariableExpression { .. } => vec![], - Tuple { fields } => fields - .iter() - .flat_map(|x| x.check_for_unresolved_types()) - .collect(), - AsmExpression { registers, .. } => registers - .iter() - .filter_map(|x| x.initializer.as_ref()) - .flat_map(UnresolvedTypeCheck::check_for_unresolved_types) - .collect::>(), - StructExpression { fields, .. } => fields - .iter() - .flat_map(|x| x.value.check_for_unresolved_types()) - .collect(), - LazyOperator { lhs, rhs, .. } => lhs - .check_for_unresolved_types() - .into_iter() - .chain(rhs.check_for_unresolved_types().into_iter()) - .collect(), - Array { contents } => contents - .iter() - .flat_map(|x| x.check_for_unresolved_types()) - .collect(), - ArrayIndex { prefix, .. } => prefix.check_for_unresolved_types(), - CodeBlock(block) => block - .contents - .iter() - .flat_map(UnresolvedTypeCheck::check_for_unresolved_types) - .collect(), + Tuple { fields } => { + res.append( + &mut fields + .iter() + .flat_map(|x| x.check_for_unresolved_types()) + .collect(), + ); + } + AsmExpression { registers, .. } => { + res.append( + &mut registers + .iter() + .filter_map(|x| x.initializer.as_ref()) + .flat_map(UnresolvedTypeCheck::check_for_unresolved_types) + .collect::>(), + ); + } + StructExpression { fields, .. } => { + res.append( + &mut fields + .iter() + .flat_map(|x| x.value.check_for_unresolved_types()) + .collect(), + ); + } + LazyOperator { lhs, rhs, .. } => { + res.append(&mut lhs.check_for_unresolved_types()); + res.append(&mut rhs.check_for_unresolved_types()); + } + Array { contents } => { + res.append( + &mut contents + .iter() + .flat_map(|x| x.check_for_unresolved_types()) + .collect(), + ); + } + ArrayIndex { prefix, index } => { + res.append(&mut prefix.check_for_unresolved_types()); + res.append(&mut index.check_for_unresolved_types()); + } + CodeBlock(block) => { + res.append( + &mut block + .contents + .iter() + .flat_map(UnresolvedTypeCheck::check_for_unresolved_types) + .collect(), + ); + } IfExp { condition, then, r#else, } => { - let mut buf = condition - .check_for_unresolved_types() - .into_iter() - .chain(then.check_for_unresolved_types().into_iter()) - .collect::>(); + res.append(&mut condition.check_for_unresolved_types()); + res.append(&mut then.check_for_unresolved_types()); if let Some(r#else) = r#else { - buf.append(&mut r#else.check_for_unresolved_types()); + res.append(&mut r#else.check_for_unresolved_types()); } - buf } StructFieldAccess { prefix, resolved_type_of_parent, .. - } => prefix - .check_for_unresolved_types() - .into_iter() - .chain( - resolved_type_of_parent - .check_for_unresolved_types() - .into_iter(), - ) - .collect(), + } => { + res.append(&mut prefix.check_for_unresolved_types()); + res.append(&mut resolved_type_of_parent.check_for_unresolved_types()); + } TupleElemAccess { prefix, resolved_type_of_parent, .. - } => prefix - .check_for_unresolved_types() - .into_iter() - .chain( - resolved_type_of_parent - .check_for_unresolved_types() - .into_iter(), - ) - .collect(), + } => { + res.append(&mut prefix.check_for_unresolved_types()); + res.append(&mut resolved_type_of_parent.check_for_unresolved_types()); + } EnumInstantiation { enum_decl, contents, .. } => { - let mut buf = if let Some(contents) = contents { - contents.check_for_unresolved_types().into_iter().collect() - } else { - vec![] - }; - buf.append( + if let Some(contents) = contents { + res.append(&mut contents.check_for_unresolved_types().into_iter().collect()); + } + res.append( &mut enum_decl .variants .iter() .flat_map(|x| x.type_id.check_for_unresolved_types()) .collect(), ); - buf + res.append( + &mut enum_decl + .type_parameters + .iter() + .flat_map(|x| x.type_id.check_for_unresolved_types()) + .collect(), + ); + } + AbiCast { address, .. } => { + res.append(&mut address.check_for_unresolved_types()); + } + IntrinsicFunction(kind) => { + res.append(&mut kind.check_for_unresolved_types()); + } + EnumTag { exp } => { + res.append(&mut exp.check_for_unresolved_types()); + } + UnsafeDowncast { exp, variant } => { + res.append(&mut exp.check_for_unresolved_types()); + res.append(&mut variant.type_id.check_for_unresolved_types()); } - AbiCast { address, .. } => address.check_for_unresolved_types(), // storage access can never be generic - StorageAccess { .. } | Literal(_) | AbiName(_) | FunctionParameter => vec![], - IntrinsicFunction(kind) => kind.check_for_unresolved_types(), - EnumTag { exp } => exp.check_for_unresolved_types(), - UnsafeDowncast { exp, variant } => exp - .check_for_unresolved_types() - .into_iter() - .chain(variant.type_id.check_for_unresolved_types().into_iter()) - .collect(), + // variable expressions don't ever have return types themselves, they're stored in + // `TypedExpression::return_type`. Variable expressions are just names of variables. + VariableExpression { .. } + | StorageAccess { .. } + | Literal(_) + | AbiName(_) + | FunctionParameter => {} } + res } } @@ -273,10 +297,9 @@ pub(crate) fn error_recovery_expr(span: Span) -> TypedExpression { #[allow(clippy::too_many_arguments)] impl TypedExpression { pub(crate) fn core_ops_eq( + ctx: TypeCheckContext, arguments: Vec, span: Span, - namespace: &mut Namespace, - self_type: TypeId, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; @@ -297,14 +320,7 @@ impl TypedExpression { }; let arguments = VecDeque::from(arguments); let method = check!( - resolve_method_name( - &method_name, - arguments.clone(), - vec![], - span.clone(), - namespace, - self_type, - ), + resolve_method_name(ctx, &method_name, arguments.clone(), vec![], span.clone()), return err(warnings, errors), warnings, errors @@ -370,21 +386,12 @@ impl TypedExpression { } } - pub(crate) fn type_check(arguments: TypeCheckArguments<'_, Expression>) -> CompileResult { - let TypeCheckArguments { - checkee: other, - namespace, - return_type_annotation: type_annotation, - help_text, - self_type, - opts, - .. - } = arguments; - let expr_span = other.span(); - let res = match other { + pub(crate) fn type_check(mut ctx: TypeCheckContext, expr: Expression) -> CompileResult { + let expr_span = expr.span(); + let res = match expr { Expression::Literal { value: lit, span } => Self::type_check_literal(lit, span), Expression::VariableExpression { name, span, .. } => { - Self::type_check_variable_expression(name, span, namespace) + Self::type_check_variable_expression(ctx.namespace, name, span) } Expression::FunctionApplication { name, @@ -393,38 +400,21 @@ impl TypedExpression { type_arguments, .. } => Self::type_check_function_application( - TypeCheckArguments { - checkee: (name, arguments, type_arguments), - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text, - self_type, - mode: Mode::NonAbi, - opts, - }, - span, - ), - Expression::LazyOperator { op, lhs, rhs, span } => Self::type_check_lazy_operator( - TypeCheckArguments { - checkee: (op, *lhs, *rhs), - return_type_annotation: insert_type(TypeInfo::Boolean), - namespace, - help_text, - self_type, - mode: Mode::NonAbi, - opts, - }, - span, - ), - Expression::CodeBlock { contents, span, .. } => Self::type_check_code_block( - contents, + ctx.by_ref(), + name, + arguments, + type_arguments, span, - namespace, - type_annotation, - help_text, - self_type, - opts, ), + Expression::LazyOperator { op, lhs, rhs, span } => { + let ctx = ctx + .by_ref() + .with_type_annotation(insert_type(TypeInfo::Boolean)); + Self::type_check_lazy_operator(ctx, op, *lhs, *rhs, span) + } + Expression::CodeBlock { contents, span, .. } => { + Self::type_check_code_block(ctx.by_ref(), contents, span) + } // TODO if _condition_ is constant, evaluate it and compile this to an // expression with only one branch Expression::IfExp { @@ -433,15 +423,10 @@ impl TypedExpression { r#else, span, } => Self::type_check_if_expression( - TypeCheckArguments { - checkee: (*condition, *then, r#else.map(|x| *x)), - return_type_annotation: type_annotation, - namespace, - self_type, - mode: Mode::NonAbi, - help_text: Default::default(), - opts, - }, + ctx.by_ref().with_help_text(""), + *condition, + *then, + r#else.map(|e| *e), span, ), Expression::MatchExp { @@ -449,19 +434,13 @@ impl TypedExpression { branches, span, } => Self::type_check_match_expression( - TypeCheckArguments { - checkee: (*value, branches), - return_type_annotation: type_annotation, - namespace, - self_type, - mode: Mode::NonAbi, - help_text: Default::default(), - opts, - }, + ctx.by_ref().with_help_text(""), + *value, + branches, span, ), Expression::AsmExpression { asm, span, .. } => { - Self::type_check_asm_expression(asm, span, namespace, self_type, opts) + Self::type_check_asm_expression(ctx.by_ref(), asm, span) } Expression::StructExpression { span, @@ -469,26 +448,17 @@ impl TypedExpression { struct_name, fields, } => Self::type_check_struct_expression( - span, + ctx.by_ref(), struct_name, type_arguments, fields, - namespace, - self_type, - opts, + span, ), Expression::SubfieldExpression { prefix, span, field_to_access, - } => Self::type_check_subfield_expression( - *prefix, - span, - field_to_access, - namespace, - self_type, - opts, - ), + } => Self::type_check_subfield_expression(ctx.by_ref(), *prefix, span, field_to_access), Expression::MethodApplication { method_name, contract_call_params, @@ -496,79 +466,72 @@ impl TypedExpression { type_arguments, span, } => type_check_method_application( + ctx.by_ref(), method_name, contract_call_params, arguments, type_arguments, span, - namespace, - self_type, - opts, ), Expression::Tuple { fields, span } => { - Self::type_check_tuple(fields, span, namespace, type_annotation, self_type, opts) + Self::type_check_tuple(ctx.by_ref(), fields, span) } Expression::TupleIndex { prefix, index, index_span, span, - } => Self::type_check_tuple_index( - *prefix, index, index_span, span, namespace, self_type, opts, - ), + } => Self::type_check_tuple_index(ctx.by_ref(), *prefix, index, index_span, span), Expression::DelineatedPath { call_path, span, args, type_arguments, } => Self::type_check_delineated_path( + ctx.by_ref(), call_path, span, args, type_arguments, - namespace, - self_type, - opts, ), Expression::AbiCast { abi_name, address, span, - } => Self::type_check_abi_cast(abi_name, address, span, namespace, self_type, opts), + } => Self::type_check_abi_cast(ctx.by_ref(), abi_name, address, span), Expression::Array { contents, span } => { - Self::type_check_array(contents, span, namespace, self_type, opts) + Self::type_check_array(ctx.by_ref(), contents, span) } Expression::ArrayIndex { prefix, index, span, - } => Self::type_check_array_index( - TypeCheckArguments { - checkee: (*prefix, *index), - namespace, - self_type, - opts, - return_type_annotation: insert_type(TypeInfo::Unknown), - mode: Default::default(), - help_text: Default::default(), - }, + } => { + let ctx = ctx + .by_ref() + .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_help_text(""); + Self::type_check_array_index(ctx, *prefix, *index, span) + } + Expression::StorageAccess { field_names, .. } => { + let ctx = ctx + .by_ref() + .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_help_text(""); + Self::type_check_storage_load(ctx, field_names, &expr_span) + } + Expression::IntrinsicFunction { + kind, + type_arguments, + arguments, + span, + } => Self::type_check_intrinsic_function( + ctx.by_ref(), + kind, + type_arguments, + arguments, span, ), - Expression::StorageAccess { field_names, .. } => Self::type_check_storage_load( - TypeCheckArguments { - checkee: field_names, - namespace, - self_type, - opts, - return_type_annotation: insert_type(TypeInfo::Unknown), - mode: Default::default(), - help_text: Default::default(), - }, - &expr_span, - ), - Expression::IntrinsicFunction { kind, span } => { - Self::type_check_intrinsic_function(kind, self_type, namespace, opts, span) - } }; let mut typed_expression = match res.value { Some(r) => r, @@ -580,22 +543,16 @@ impl TypedExpression { // if one of the expressions deterministically aborts, we don't want to type check it. if !typed_expression.deterministically_aborts() { // if the return type cannot be cast into the annotation type then it is a type error - let (mut new_warnings, new_errors) = unify_with_self( - typed_expression.return_type, - type_annotation, - self_type, - &expr_span, - help_text, - ); + let (mut new_warnings, new_errors) = + ctx.unify_with_self(typed_expression.return_type, &expr_span); warnings.append(&mut new_warnings); errors.append(&mut new_errors.into_iter().map(|x| x.into()).collect()); } // The annotation may result in a cast, which is handled in the type engine. typed_expression.return_type = check!( - namespace.resolve_type_with_self( - look_up_type_id(typed_expression.return_type), - self_type, + ctx.resolve_type_with_self( + typed_expression.return_type, &expr_span, EnforceTypeArguments::No ), @@ -652,9 +609,9 @@ impl TypedExpression { } pub(crate) fn type_check_variable_expression( + namespace: &Namespace, name: Ident, span: Span, - namespace: &Namespace, ) -> CompileResult { let mut errors = vec![]; let exp = match namespace.resolve_symbol(&name).value { @@ -703,20 +660,16 @@ impl TypedExpression { #[allow(clippy::type_complexity)] fn type_check_function_application( - arguments: TypeCheckArguments<'_, (CallPath, Vec, Vec)>, + ctx: TypeCheckContext, + name: CallPath, + arguments: Vec, + type_arguments: Vec, _span: Span, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; - let TypeCheckArguments { - checkee: (name, arguments, type_arguments), - namespace, - self_type, - opts, - .. - } = arguments; let unknown_decl = check!( - namespace.resolve_call_path(&name).cloned(), + ctx.namespace.resolve_call_path(&name).cloned(), return err(warnings, errors), warnings, errors @@ -728,86 +681,52 @@ impl TypedExpression { errors ); instantiate_function_application( + ctx, function_decl.clone(), name, type_arguments, arguments, - namespace, - self_type, - opts, ) } fn type_check_lazy_operator( - arguments: TypeCheckArguments<'_, (LazyOp, Expression, Expression)>, + ctx: TypeCheckContext, + op: LazyOp, + lhs: Expression, + rhs: Expression, span: Span, ) -> CompileResult { - let TypeCheckArguments { - checkee: (op, lhs, rhs), - namespace, - self_type, - return_type_annotation, - opts, - .. - } = arguments; - let mut warnings = vec![]; let mut errors = vec![]; + let mut ctx = ctx.with_help_text(""); let typed_lhs = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: lhs.clone(), - help_text: Default::default(), - mode: Mode::NonAbi, - opts, - self_type, - namespace, - return_type_annotation, - }), + TypedExpression::type_check(ctx.by_ref(), lhs.clone()), error_recovery_expr(lhs.span()), warnings, errors ); let typed_rhs = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: rhs.clone(), - namespace, - return_type_annotation, - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx.by_ref(), rhs.clone()), error_recovery_expr(rhs.span()), warnings, errors ); - let exp = instantiate_lazy_operator(op, typed_lhs, typed_rhs, return_type_annotation, span); + let type_annotation = ctx.type_annotation(); + let exp = instantiate_lazy_operator(op, typed_lhs, typed_rhs, type_annotation, span); ok(exp, warnings, errors) } fn type_check_code_block( + mut ctx: TypeCheckContext, contents: CodeBlock, span: Span, - namespace: &mut Namespace, - type_annotation: TypeId, - help_text: &'static str, - self_type: TypeId, - opts: TCOpts, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; let (typed_block, block_return_type) = check!( - TypedCodeBlock::type_check(TypeCheckArguments { - checkee: contents, - namespace, - return_type_annotation: type_annotation, - help_text, - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedCodeBlock::type_check(ctx.by_ref(), contents), ( TypedCodeBlock { contents: vec![] }, crate::type_engine::insert_type(TypeInfo::Tuple(Vec::new())) @@ -816,13 +735,7 @@ impl TypedExpression { errors ); - let (mut new_warnings, new_errors) = unify_with_self( - block_return_type, - type_annotation, - self_type, - &span, - help_text, - ); + let (mut new_warnings, new_errors) = ctx.unify_with_self(block_return_type, &span); warnings.append(&mut new_warnings); errors.append(&mut new_errors.into_iter().map(|x| x.into()).collect()); let exp = TypedExpression { @@ -839,65 +752,59 @@ impl TypedExpression { #[allow(clippy::type_complexity)] fn type_check_if_expression( - arguments: TypeCheckArguments<'_, (Expression, Expression, Option)>, + mut ctx: TypeCheckContext, + condition: Expression, + then: Expression, + r#else: Option, span: Span, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; - let TypeCheckArguments { - checkee: (condition, then, r#else), - namespace, - return_type_annotation: type_annotation, - self_type, - opts, - .. - } = arguments; - let condition = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: condition.clone(), - namespace, - return_type_annotation: insert_type(TypeInfo::Boolean), - help_text: "The condition of an if expression must be a boolean expression.", - self_type, - mode: Mode::NonAbi, - opts, - }), - error_recovery_expr(condition.span()), - warnings, - errors - ); - let then = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: then.clone(), - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), - error_recovery_expr(then.span()), - warnings, - errors - ); + let condition = { + let ctx = ctx + .by_ref() + .with_help_text("The condition of an if expression must be a boolean expression.") + .with_type_annotation(insert_type(TypeInfo::Boolean)); + check!( + TypedExpression::type_check(ctx, condition.clone()), + error_recovery_expr(condition.span()), + warnings, + errors + ) + }; + let then = { + let ctx = ctx + .by_ref() + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); + check!( + TypedExpression::type_check(ctx, then.clone()), + error_recovery_expr(then.span()), + warnings, + errors + ) + }; let r#else = r#else.map(|expr| { + let ctx = ctx + .by_ref() + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: expr.clone(), - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, expr.clone()), error_recovery_expr(expr.span()), warnings, errors ) }); let exp = check!( - instantiate_if_expression(condition, then, r#else, span, type_annotation, self_type), + instantiate_if_expression( + condition, + then, + r#else, + span, + ctx.type_annotation(), + ctx.self_type(), + ), return err(warnings, errors), warnings, errors @@ -906,35 +813,27 @@ impl TypedExpression { } fn type_check_match_expression( - arguments: TypeCheckArguments<'_, (Expression, Vec)>, + mut ctx: TypeCheckContext, + value: Expression, + branches: Vec, span: Span, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; - let TypeCheckArguments { - checkee: (value, branches), - namespace, - return_type_annotation, - self_type, - opts, - .. - } = arguments; // type check the value - let typed_value = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: value.clone(), - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), - error_recovery_expr(value.span()), - warnings, - errors - ); + let typed_value = { + let ctx = ctx + .by_ref() + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); + check!( + TypedExpression::type_check(ctx, value.clone()), + error_recovery_expr(value.span()), + warnings, + errors + ) + }; let type_id = typed_value.return_type; let _ = check!( @@ -950,23 +849,15 @@ impl TypedExpression { .collect::>(); // type check the match expression and create a TypedMatchExpression object - let typed_match_expression = check!( - TypedMatchExpression::type_check( - TypeCheckArguments { - checkee: (typed_value, branches), - namespace, - return_type_annotation, - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }, - span.clone() - ), - return err(warnings, errors), - warnings, - errors - ); + let typed_match_expression = { + let ctx = ctx.by_ref().with_help_text(""); + check!( + TypedMatchExpression::type_check(ctx, typed_value, branches, span.clone()), + return err(warnings, errors), + warnings, + errors + ) + }; // check to see if the match expression is exhaustive and if all match arms are reachable let (witness_report, arms_reachability) = check!( @@ -993,7 +884,7 @@ impl TypedExpression { // desugar the typed match expression to a typed if expression let typed_if_exp = check!( - typed_match_expression.convert_to_typed_if_expression(namespace, self_type), + typed_match_expression.convert_to_typed_if_expression(ctx), return err(warnings, errors), warnings, errors @@ -1004,11 +895,9 @@ impl TypedExpression { #[allow(clippy::too_many_arguments)] fn type_check_asm_expression( + mut ctx: TypeCheckContext, asm: AsmExpression, span: Span, - namespace: &mut Namespace, - self_type: TypeId, - opts: TCOpts, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; @@ -1018,9 +907,8 @@ impl TypedExpression { .map(|x| x.1) .unwrap_or_else(|| asm.whole_block_span.clone()); let return_type = check!( - namespace.resolve_type_with_self( - asm.return_type.clone(), - self_type, + ctx.resolve_type_with_self( + insert_type(asm.return_type.clone()), &asm_span, EnforceTypeArguments::No ), @@ -1036,16 +924,12 @@ impl TypedExpression { |AsmRegisterDeclaration { name, initializer }| TypedAsmRegisterDeclaration { name, initializer: initializer.map(|initializer| { + let ctx = ctx + .by_ref() + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: initializer.clone(), - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, initializer.clone()), error_recovery_expr(initializer.span()), warnings, errors @@ -1074,21 +958,19 @@ impl TypedExpression { #[allow(clippy::too_many_arguments)] fn type_check_struct_expression( - span: Span, + mut ctx: TypeCheckContext, call_path: CallPath, type_arguments: Vec, fields: Vec, - namespace: &mut Namespace, - self_type: TypeId, - opts: TCOpts, + span: Span, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; // find the module that the symbol is in - let module_path = namespace.find_module_path(&call_path.prefixes); + let module_path = ctx.namespace.find_module_path(&call_path.prefixes); check!( - namespace.root().check_submodule(&module_path), + ctx.namespace.root().check_submodule(&module_path), return err(warnings, errors), warnings, errors @@ -1096,7 +978,7 @@ impl TypedExpression { // find the struct definition from the name let unknown_decl = check!( - namespace + ctx.namespace .root() .resolve_symbol(&module_path, &call_path.suffix) .cloned(), @@ -1104,22 +986,20 @@ impl TypedExpression { warnings, errors ); - let struct_decl = check!( - unknown_decl.expect_struct(), + let mut struct_decl = check!( + unknown_decl.expect_struct().cloned(), return err(warnings, errors), warnings, errors - ) - .clone(); + ); // monomorphize the struct definition - let mut struct_decl = check!( - namespace.monomorphize( - struct_decl, + check!( + ctx.monomorphize( + &mut struct_decl, type_arguments, EnforceTypeArguments::No, - Some(self_type), - None + &call_path.span() ), return err(warnings, errors), warnings, @@ -1151,17 +1031,14 @@ impl TypedExpression { } }; + let ctx = ctx + .by_ref() + .with_help_text( + "Struct field's type must match up with the type specified in its declaration.", + ) + .with_type_annotation(def_field.type_id); let typed_field = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: expr_field.value, - namespace, - return_type_annotation: def_field.type_id, - help_text: "Struct field's type must match up with the type specified in its \ - declaration.", - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, expr_field.value), continue, warnings, errors @@ -1198,25 +1075,18 @@ impl TypedExpression { #[allow(clippy::too_many_arguments)] fn type_check_subfield_expression( + ctx: TypeCheckContext, prefix: Expression, span: Span, field_to_access: Ident, - namespace: &mut Namespace, - self_type: TypeId, - opts: TCOpts, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; + let ctx = ctx + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); let parent = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: prefix, - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, prefix), return err(warnings, errors), warnings, errors @@ -1231,16 +1101,13 @@ impl TypedExpression { } fn type_check_tuple( + mut ctx: TypeCheckContext, fields: Vec, span: Span, - namespace: &mut Namespace, - type_annotation: TypeId, - self_type: TypeId, - opts: TCOpts, - ) -> CompileResult { + ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; - let field_type_opt = match look_up_type_id(type_annotation) { + let field_type_opt = match look_up_type_id(ctx.type_annotation()) { TypeInfo::Tuple(field_type_ids) if field_type_ids.len() == fields.len() => { Some(field_type_ids) } @@ -1255,16 +1122,12 @@ impl TypedExpression { .map(|field_type_ids| field_type_ids[i].clone()) .unwrap_or_default(); let field_span = field.span(); + let ctx = ctx + .by_ref() + .with_help_text("tuple field type does not match the expected type") + .with_type_annotation(field_type.type_id); let typed_field = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: field, - namespace, - return_type_annotation: field_type.type_id, - help_text: "tuple field type does not match the expected type", - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, field), error_recovery_expr(field_span), warnings, errors @@ -1293,22 +1156,19 @@ impl TypedExpression { /// If there isn't any storage, then this is an error. If there is storage, find the corresponding /// field that has been specified and return that value. fn type_check_storage_load( - arguments: TypeCheckArguments<'_, Vec>, + ctx: TypeCheckContext, + checkee: Vec, span: &Span, - ) -> CompileResult { - let TypeCheckArguments { - checkee, namespace, .. - } = arguments; - + ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; - if !namespace.has_storage_declared() { + if !ctx.namespace.has_storage_declared() { errors.push(CompileError::NoDeclaredStorage { span: span.clone() }); return err(warnings, errors); } let storage_fields = check!( - namespace.get_storage_field_descriptors(), + ctx.namespace.get_storage_field_descriptors(), return err(warnings, errors), warnings, errors @@ -1316,7 +1176,7 @@ impl TypedExpression { // Do all namespace checking here! let (storage_access, return_type) = check!( - namespace.apply_storage_load(checkee, &storage_fields), + ctx.namespace.apply_storage_load(checkee, &storage_fields), return err(warnings, errors), warnings, errors @@ -1334,26 +1194,19 @@ impl TypedExpression { } fn type_check_tuple_index( + ctx: TypeCheckContext, prefix: Expression, index: usize, index_span: Span, span: Span, - namespace: &mut Namespace, - self_type: TypeId, - opts: TCOpts, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; + let ctx = ctx + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); let parent = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: prefix, - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, prefix), return err(warnings, errors), warnings, errors @@ -1369,13 +1222,11 @@ impl TypedExpression { #[allow(clippy::too_many_arguments)] fn type_check_delineated_path( + ctx: TypeCheckContext, call_path: CallPath, span: Span, args: Vec, type_arguments: Vec, - namespace: &mut Namespace, - self_type: TypeId, - opts: TCOpts, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; @@ -1390,20 +1241,22 @@ impl TypedExpression { // First, check if this could be a module. We check first so that we can check for // ambiguity in the following enum check. - let is_module = namespace + let is_module = ctx + .namespace .check_submodule(&call_path.prefixes) .ok(&mut probe_warnings, &mut probe_errors) .is_some(); // Check if the call path refers to an enum in another module. let (enum_name, enum_mod_path) = call_path.prefixes.split_last().expect("empty call path"); - let abs_enum_mod_path: Vec<_> = namespace.find_module_path(enum_mod_path); - let exp = if let Some(enum_decl) = namespace + let abs_enum_mod_path: Vec<_> = ctx.namespace.find_module_path(enum_mod_path); + let exp = if let Some(enum_decl) = ctx + .namespace .check_submodule_mut(enum_mod_path) .ok(&mut warnings, &mut errors) .map(|_| ()) .and_then(|_| { - namespace + ctx.namespace .root() .resolve_symbol(&abs_enum_mod_path, enum_name) .value @@ -1416,28 +1269,21 @@ impl TypedExpression { return err(warnings, errors); } check!( - instantiate_enum( - enum_decl, - call_path.suffix, - args, - type_arguments, - namespace, - self_type, - opts, - ), + instantiate_enum(ctx, enum_decl, call_path.suffix, args, type_arguments), return err(warnings, errors), warnings, errors ) // Otherwise, our prefix should point to some module ending with an enum or function. - } else if namespace + } else if ctx + .namespace .check_submodule_mut(&call_path.prefixes) .ok(&mut probe_warnings, &mut probe_errors) .is_some() { let decl = check!( - namespace.resolve_call_path(&call_path).cloned(), + ctx.namespace.resolve_call_path(&call_path).cloned(), return err(warnings, errors), warnings, errors @@ -1445,15 +1291,7 @@ impl TypedExpression { match decl { TypedDeclaration::EnumDeclaration(enum_decl) => { check!( - instantiate_enum( - enum_decl, - call_path.suffix, - args, - type_arguments, - namespace, - self_type, - opts, - ), + instantiate_enum(ctx, enum_decl, call_path.suffix, args, type_arguments), return err(warnings, errors), warnings, errors @@ -1462,13 +1300,11 @@ impl TypedExpression { TypedDeclaration::FunctionDeclaration(func_decl) => { check!( instantiate_function_application( + ctx, func_decl, call_path, vec!(), // the type args in this position are guarenteed to be empty due to parsing args, - namespace, - self_type, - opts, ), return err(warnings, errors), warnings, @@ -1499,35 +1335,31 @@ impl TypedExpression { #[allow(clippy::too_many_arguments)] fn type_check_abi_cast( + mut ctx: TypeCheckContext, abi_name: CallPath, address: Box, span: Span, - namespace: &mut Namespace, - self_type: TypeId, - opts: TCOpts, - ) -> CompileResult { + ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; // TODO use lib-std's Address type instead of b256 // type check the address and make sure it is let err_span = address.span(); - let address_expr = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: *address, - namespace, - return_type_annotation: insert_type(TypeInfo::B256), - help_text: "An address that is being ABI cast must be of type b256", - self_type, - mode: Mode::NonAbi, - opts, - }), - error_recovery_expr(err_span), - warnings, - errors - ); + let address_expr = { + let ctx = ctx + .by_ref() + .with_help_text("An address that is being ABI cast must be of type b256") + .with_type_annotation(insert_type(TypeInfo::B256)); + check!( + TypedExpression::type_check(ctx, *address), + error_recovery_expr(err_span), + warnings, + errors + ) + }; // look up the call path and get the declaration it references let abi = check!( - namespace.resolve_call_path(&abi_name).cloned(), + ctx.namespace.resolve_call_path(&abi_name).cloned(), return err(warnings, errors), warnings, errors @@ -1553,7 +1385,7 @@ impl TypedExpression { // look up the call path and get the declaration it references AbiName::Known(abi_name) => { let unknown_decl = check!( - namespace.resolve_call_path(&abi_name).cloned(), + ctx.namespace.resolve_call_path(&abi_name).cloned(), return err(warnings, errors), warnings, errors @@ -1606,16 +1438,13 @@ impl TypedExpression { // they instead just use the CALL opcode and the return type let mut type_checked_fn_buf = Vec::with_capacity(abi.methods.len()); for method in &abi.methods { + let ctx = ctx + .by_ref() + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_mode(Mode::ImplAbiFn); type_checked_fn_buf.push(check!( - TypedFunctionDeclaration::type_check(TypeCheckArguments { - checkee: method.clone(), - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type: insert_type(TypeInfo::Contract), - mode: Mode::ImplAbiFn, - opts, - }), + TypedFunctionDeclaration::type_check(ctx, method.clone()), return err(warnings, errors), warnings, errors @@ -1623,7 +1452,8 @@ impl TypedExpression { } functions_buf.append(&mut type_checked_fn_buf); - namespace.insert_trait_implementation(abi_name.clone(), return_type, functions_buf); + ctx.namespace + .insert_trait_implementation(abi_name.clone(), return_type, functions_buf); let exp = TypedExpression { expression: TypedExpressionVariant::AbiCast { abi_name, @@ -1637,14 +1467,11 @@ impl TypedExpression { ok(exp, warnings, errors) } - #[allow(clippy::too_many_arguments)] fn type_check_array( + mut ctx: TypeCheckContext, contents: Vec, span: Span, - namespace: &mut Namespace, - self_type: TypeId, - opts: TCOpts, - ) -> CompileResult { + ) -> CompileResult { if contents.is_empty() { return ok( TypedExpression { @@ -1666,16 +1493,12 @@ impl TypedExpression { .into_iter() .map(|expr| { let span = expr.span(); + let ctx = ctx + .by_ref() + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); check!( - Self::type_check(TypeCheckArguments { - checkee: expr, - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), + Self::type_check(ctx, expr), error_recovery_expr(span), warnings, errors @@ -1685,13 +1508,10 @@ impl TypedExpression { let elem_type = typed_contents[0].return_type; for typed_elem in &typed_contents[1..] { - let (mut new_warnings, new_errors) = unify_with_self( - typed_elem.return_type, - elem_type, - self_type, - &typed_elem.span, - "", - ); + let (mut new_warnings, new_errors) = ctx + .by_ref() + .with_type_annotation(elem_type) + .unify_with_self(typed_elem.return_type, &typed_elem.span); let no_warnings = new_warnings.is_empty(); let no_errors = new_errors.is_empty(); warnings.append(&mut new_warnings); @@ -1719,48 +1539,35 @@ impl TypedExpression { } fn type_check_array_index( - arguments: TypeCheckArguments<'_, (Expression, Expression)>, + mut ctx: TypeCheckContext, + prefix: Expression, + index: Expression, span: Span, - ) -> CompileResult { - let TypeCheckArguments { - checkee: (prefix, index), - namespace, - self_type, - opts, - .. - } = arguments; + ) -> CompileResult { let mut warnings = Vec::new(); let mut errors = Vec::new(); - let prefix_te = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: prefix.clone(), - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), - return err(warnings, errors), - warnings, - errors - ); + let prefix_te = { + let ctx = ctx + .by_ref() + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); + check!( + TypedExpression::type_check(ctx, prefix.clone()), + return err(warnings, errors), + warnings, + errors + ) + }; // If the return type is a static array then create a TypedArrayIndex. if let TypeInfo::Array(elem_type_id, _) = look_up_type_id(prefix_te.return_type) { + let type_info_u64 = TypeInfo::UnsignedInteger(IntegerBits::SixtyFour); + let ctx = ctx + .with_help_text("") + .with_type_annotation(insert_type(type_info_u64)); let index_te = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: index, - namespace, - return_type_annotation: insert_type(TypeInfo::UnsignedInteger( - IntegerBits::SixtyFour - )), - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, index), return err(warnings, errors), warnings, errors @@ -1792,29 +1599,33 @@ impl TypedExpression { }, }; type_check_method_application( + ctx, method_name, vec![], vec![prefix, index], vec![], span, - namespace, - self_type, - opts, ) } } fn type_check_intrinsic_function( - kind: IntrinsicFunctionKind, - self_type: TypeId, - namespace: &mut Namespace, - opts: TCOpts, + ctx: TypeCheckContext, + kind: Intrinsic, + type_arguments: Vec, + arguments: Vec, span: Span, - ) -> CompileResult { + ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; let (intrinsic_function, return_type) = check!( - TypedIntrinsicFunctionKind::type_check(kind, self_type, namespace, opts), + TypedIntrinsicFunctionKind::type_check( + ctx, + kind, + type_arguments, + arguments, + span.clone() + ), return err(warnings, errors), warnings, errors @@ -1920,17 +1731,8 @@ mod tests { fn do_type_check(expr: Expression, type_annotation: TypeId) -> CompileResult { let mut namespace = Namespace::init_root(namespace::Module::default()); - let self_type = insert_type(TypeInfo::Unknown); - - TypedExpression::type_check(TypeCheckArguments { - checkee: expr, - namespace: &mut namespace, - return_type_annotation: type_annotation, - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts: Default::default(), - }) + let ctx = TypeCheckContext::from_root(&mut namespace).with_type_annotation(type_annotation); + TypedExpression::type_check(ctx, expr) } fn do_type_check_for_boolx2(expr: Expression) -> CompileResult { diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/enum_instantiation.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/enum_instantiation.rs index 80adecaf40d..e91fef07608 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/enum_instantiation.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/enum_instantiation.rs @@ -6,25 +6,22 @@ use sway_types::{Ident, Spanned}; /// [TypedExpression]. #[allow(clippy::too_many_arguments)] pub(crate) fn instantiate_enum( - enum_decl: TypedEnumDeclaration, + mut ctx: TypeCheckContext, + mut enum_decl: TypedEnumDeclaration, enum_field_name: Ident, args: Vec, type_arguments: Vec, - namespace: &mut Namespace, - self_type: TypeId, - opts: TCOpts, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; // monomorphize the enum definition with the type arguments - let enum_decl = check!( - namespace.monomorphize( - enum_decl, + check!( + ctx.monomorphize( + &mut enum_decl, type_arguments, EnforceTypeArguments::No, - Some(self_type), - Some(&enum_field_name.span()) + &enum_field_name.span() ), return err(warnings, errors), warnings, @@ -61,16 +58,11 @@ pub(crate) fn instantiate_enum( errors, ), ([single_expr], _) => { + let ctx = ctx + .with_help_text("Enum instantiator must match its declared variant type.") + .with_type_annotation(enum_variant.type_id); let typed_expr = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: single_expr.clone(), - namespace, - return_type_annotation: enum_variant.type_id, - help_text: "Enum instantiator must match its declared variant type.", - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, single_expr.clone()), return err(warnings, errors), warnings, errors diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs index 525d562a397..5a2adccf410 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs @@ -1,32 +1,28 @@ use crate::{ error::*, - semantic_analysis::{ast_node::*, TCOpts, TypeCheckArguments}, - type_engine::TypeId, + semantic_analysis::{ast_node::*, TypeCheckContext}, }; use std::collections::{hash_map::RandomState, HashMap, VecDeque}; use sway_types::{state::StateIndex, Spanned}; #[allow(clippy::too_many_arguments)] pub(crate) fn instantiate_function_application( - function_decl: TypedFunctionDeclaration, + mut ctx: TypeCheckContext, + mut function_decl: TypedFunctionDeclaration, call_path: CallPath, type_arguments: Vec, arguments: Vec, - namespace: &mut Namespace, - self_type: TypeId, - opts: TCOpts, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; // monomorphize the function declaration - let function_decl = check!( - namespace.monomorphize( - function_decl, + check!( + ctx.monomorphize( + &mut function_decl, type_arguments, EnforceTypeArguments::No, - Some(self_type), - Some(&call_path.span()) + &call_path.span() ), return err(warnings, errors), warnings, @@ -34,9 +30,9 @@ pub(crate) fn instantiate_function_application( ); // 'purity' is that of the callee, 'opts.purity' of the caller. - if !opts.purity.can_call(function_decl.purity) { + if !ctx.purity().can_call(function_decl.purity) { errors.push(CompileError::StorageAccessMismatch { - attrs: promote_purity(opts.purity, function_decl.purity).to_attribute_syntax(), + attrs: promote_purity(ctx.purity(), function_decl.purity).to_attribute_syntax(), span: call_path.span(), }); } @@ -48,18 +44,16 @@ pub(crate) fn instantiate_function_application( .into_iter() .zip(function_decl.parameters.iter()) .map(|(arg, param)| { + let ctx = ctx + .by_ref() + .with_help_text( + "The argument that has been provided to this function's type does \ + not match the declared type of the parameter in the function \ + declaration.", + ) + .with_type_annotation(param.type_id); let exp = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: arg.clone(), - namespace, - return_type_annotation: param.type_id, - help_text: "The argument that has been provided to this function's type does \ - not match the declared type of the parameter in the function \ - declaration.", - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, arg.clone()), error_recovery_expr(arg.span()), warnings, errors diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/if_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/if_expression.rs index a146b571954..ac5670cc0fc 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/if_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/if_expression.rs @@ -37,11 +37,16 @@ pub(crate) fn instantiate_if_expression( let mut else_deterministically_aborts = false; let r#else = r#else.map(|r#else| { else_deterministically_aborts = r#else.deterministically_aborts(); + let ty_to_check = if then_deterministically_aborts { + type_annotation + } else { + then.return_type + }; if !else_deterministically_aborts { // if this does not deterministically_abort, check the block return type let (mut new_warnings, new_errors) = unify_with_self( r#else.return_type, - then.return_type, + ty_to_check, self_type, &r#else.span, "`else` branch must return expected type.", @@ -78,7 +83,11 @@ pub(crate) fn instantiate_if_expression( } } - let return_type = then.return_type; + let return_type = if !then_deterministically_aborts { + then.return_type + } else { + r#else_ret_ty + }; let exp = TypedExpression { expression: TypedExpressionVariant::IfExp { condition: Box::new(condition), diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs index 39313691d5b..1a03e347b60 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs @@ -12,30 +12,24 @@ use sway_types::{Ident, Spanned}; #[allow(clippy::too_many_arguments)] pub(crate) fn type_check_method_application( + mut ctx: TypeCheckContext, method_name: MethodName, contract_call_params: Vec, arguments: Vec, type_arguments: Vec, span: Span, - namespace: &mut Namespace, - self_type: TypeId, - opts: TCOpts, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; let mut args_buf = VecDeque::new(); let mut contract_call_params_map = HashMap::new(); for arg in &arguments { + let ctx = ctx + .by_ref() + .with_help_text("") + .with_type_annotation(insert_type(TypeInfo::Unknown)); args_buf.push_back(check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: arg.clone(), - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, arg.clone()), error_recovery_expr(span.clone()), warnings, errors @@ -44,12 +38,11 @@ pub(crate) fn type_check_method_application( let method = check!( resolve_method_name( + ctx.by_ref(), &method_name, args_buf.clone(), type_arguments, span.clone(), - namespace, - self_type ), return err(warnings, errors), warnings, @@ -64,9 +57,9 @@ pub(crate) fn type_check_method_application( if !method.is_contract_call { // 'method.purity' is that of the callee, 'opts.purity' of the caller. - if !opts.purity.can_call(method.purity) { + if !ctx.purity().can_call(method.purity) { errors.push(CompileError::StorageAccessMismatch { - attrs: promote_purity(opts.purity, method.purity).to_attribute_syntax(), + attrs: promote_purity(ctx.purity(), method.purity).to_attribute_syntax(), span: method_name.easy_name().span(), }); } @@ -96,6 +89,18 @@ pub(crate) fn type_check_method_application( } for param in contract_call_params { + let type_annotation = match param.name.span().as_str() { + constants::CONTRACT_CALL_GAS_PARAMETER_NAME + | constants::CONTRACT_CALL_COINS_PARAMETER_NAME => { + insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)) + } + constants::CONTRACT_CALL_ASSET_ID_PARAMETER_NAME => insert_type(TypeInfo::B256), + _ => unreachable!(), + }; + let ctx = ctx + .by_ref() + .with_help_text("") + .with_type_annotation(type_annotation); match param.name.span().as_str() { constants::CONTRACT_CALL_GAS_PARAMETER_NAME | constants::CONTRACT_CALL_COINS_PARAMETER_NAME @@ -103,23 +108,7 @@ pub(crate) fn type_check_method_application( contract_call_params_map.insert( param.name.to_string(), check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: param.value, - namespace, - return_type_annotation: match param.name.span().as_str() { - constants::CONTRACT_CALL_GAS_PARAMETER_NAME - | constants::CONTRACT_CALL_COINS_PARAMETER_NAME => insert_type( - TypeInfo::UnsignedInteger(IntegerBits::SixtyFour) - ), - constants::CONTRACT_CALL_ASSET_ID_PARAMETER_NAME => - insert_type(TypeInfo::B256), - _ => unreachable!(), - }, - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, param.value), error_recovery_expr(span.clone()), warnings, errors @@ -139,9 +128,9 @@ pub(crate) fn type_check_method_application( // If this method was called with self being a `StorageAccess` (e.g. storage.map.insert(..)), // then record the index of that storage variable and pass it on. let mut self_state_idx = None; - if namespace.has_storage_declared() { + if ctx.namespace.has_storage_declared() { let storage_fields = check!( - namespace.get_storage_field_descriptors(), + ctx.namespace.get_storage_field_descriptors(), return err(warnings, errors), warnings, errors @@ -172,13 +161,11 @@ pub(crate) fn type_check_method_application( // type check all of the arguments against the parameters in the method declaration for (arg, param) in args_buf.iter().zip(method.parameters.iter()) { // if the return type cannot be cast into the annotation type then it is a type error - let (mut new_warnings, new_errors) = unify_with_self( - arg.return_type, - param.type_id, - self_type, - &arg.span, - "This argument's type is not castable to the declared parameter type.", - ); + let (mut new_warnings, new_errors) = ctx + .by_ref() + .with_help_text("This argument's type is not castable to the declared parameter type.") + .with_type_annotation(param.type_id) + .unify_with_self(arg.return_type, &arg.span); warnings.append(&mut new_warnings); if !new_errors.is_empty() { errors.push(CompileError::ArgumentParameterTypeMismatch { @@ -201,19 +188,26 @@ pub(crate) fn type_check_method_application( ) = (args_buf.get(0), method.parameters.get(0)) { let unknown_decl = check!( - namespace.resolve_symbol(name).cloned(), - return err(warnings, errors), - warnings, - errors - ); - let variable_decl = check!( - unknown_decl.expect_variable().cloned(), + ctx.namespace.resolve_symbol(name).cloned(), return err(warnings, errors), warnings, errors ); - if !variable_decl.is_mutable.is_mutable() && *is_mutable { + let is_decl_mutable = match unknown_decl { + TypedDeclaration::ConstantDeclaration(_) => false, + _ => { + let variable_decl = check!( + unknown_decl.expect_variable().cloned(), + return err(warnings, errors), + warnings, + errors + ); + variable_decl.is_mutable.is_mutable() + } + }; + + if !is_decl_mutable && *is_mutable { errors.push(CompileError::MethodRequiresMutableSelf { method_name: method_name.easy_name(), variable_name: name.clone(), @@ -330,12 +324,11 @@ pub(crate) fn type_check_method_application( } pub(crate) fn resolve_method_name( + ctx: TypeCheckContext, method_name: &MethodName, arguments: VecDeque, type_arguments: Vec, span: Span, - namespace: &mut Namespace, - self_type: TypeId, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; @@ -346,13 +339,12 @@ pub(crate) fn resolve_method_name( type_name_span, } => check!( find_method( + ctx, type_name, type_name_span, type_arguments, - namespace, &arguments, call_path, - self_type ), return err(warnings, errors), warnings, @@ -365,13 +357,12 @@ pub(crate) fn resolve_method_name( .unwrap_or_else(|| (TypeInfo::Unknown, span.clone())); check!( find_method( + ctx, &type_name, &type_name_span, type_arguments, - namespace, &arguments, call_path, - self_type ), return err(warnings, errors), warnings, @@ -383,9 +374,10 @@ pub(crate) fn resolve_method_name( .get(0) .map(|x| x.return_type) .unwrap_or_else(|| insert_type(TypeInfo::Unknown)); - let abs_path: Vec<_> = namespace.find_module_path(Some(method_name)); + let abs_path: Vec<_> = ctx.namespace.find_module_path(Some(method_name)); check!( - namespace.find_method_for_type(ty, &abs_path, self_type, &arguments), + ctx.namespace + .find_method_for_type(ty, &abs_path, ctx.self_type(), &arguments), return err(warnings, errors), warnings, errors @@ -396,13 +388,12 @@ pub(crate) fn resolve_method_name( } fn find_method( + ctx: TypeCheckContext, type_name: &TypeInfo, type_name_span: &Span, type_arguments: Vec, - namespace: &mut Namespace, arguments: &VecDeque, call_path: &CallPath, - self_type: TypeId, ) -> CompileResult { let warnings = vec![]; let mut errors = vec![]; @@ -443,7 +434,8 @@ fn find_method( let abs_path: Vec = if call_path.is_absolute { call_path.full_path().cloned().collect() } else { - namespace.find_module_path(call_path.full_path()) + ctx.namespace.find_module_path(call_path.full_path()) }; - namespace.find_method_for_type(insert_type(ty), &abs_path, self_type, arguments) + ctx.namespace + .find_method_for_type(insert_type(ty), &abs_path, ctx.self_type(), arguments) } diff --git a/sway-core/src/semantic_analysis/ast_node/mod.rs b/sway-core/src/semantic_analysis/ast_node/mod.rs index 50d521abe60..3632445aab5 100644 --- a/sway-core/src/semantic_analysis/ast_node/mod.rs +++ b/sway-core/src/semantic_analysis/ast_node/mod.rs @@ -214,28 +214,16 @@ impl TypedAstNode { } } - pub(crate) fn type_check( - arguments: TypeCheckArguments<'_, AstNode>, - ) -> CompileResult { - let TypeCheckArguments { - checkee: node, - namespace, - return_type_annotation, - help_text, - self_type, - opts, - .. - } = arguments; + pub(crate) fn type_check(mut ctx: TypeCheckContext, node: AstNode) -> CompileResult { let mut warnings = Vec::new(); let mut errors = Vec::new(); // A little utility used to check an ascribed type matches its associated expression. let mut type_check_ascribed_expr = - |namespace: &mut Namespace, type_ascription: TypeInfo, value| { + |mut ctx: TypeCheckContext, type_ascription: TypeInfo, expr| { let type_id = check!( - namespace.resolve_type_with_self( - type_ascription, - self_type, + ctx.resolve_type_with_self( + insert_type(type_ascription), &node.span, EnforceTypeArguments::No ), @@ -243,16 +231,11 @@ impl TypedAstNode { warnings, errors, ); - TypedExpression::type_check(TypeCheckArguments { - checkee: value, - namespace, - return_type_annotation: type_id, - help_text: "This declaration's type annotation does \ - not match up with the assigned expression's type.", - self_type, - mode: Mode::NonAbi, - opts, - }) + let ctx = ctx.with_type_annotation(type_id).with_help_text( + "This declaration's type annotation does not match up with the assigned \ + expression's type.", + ); + TypedExpression::type_check(ctx, expr) }; let node = TypedAstNode { @@ -261,12 +244,12 @@ impl TypedAstNode { let path = if a.is_absolute { a.call_path.clone() } else { - namespace.find_module_path(&a.call_path) + ctx.namespace.find_module_path(&a.call_path) }; let mut res = match a.import_type { - ImportType::Star => namespace.star_import(&path), - ImportType::SelfImport => namespace.self_import(&path, a.alias), - ImportType::Item(s) => namespace.item_import(&path, &s, a.alias), + ImportType::Star => ctx.namespace.star_import(&path), + ImportType::SelfImport => ctx.namespace.self_import(&path, a.alias), + ImportType::Item(s) => ctx.namespace.item_import(&path, &s, a.alias), }; warnings.append(&mut res.warnings); errors.append(&mut res.errors); @@ -282,15 +265,13 @@ impl TypedAstNode { body, is_mutable, }) => { - check_if_name_is_invalid(&name).ok(&mut warnings, &mut errors); let type_ascription_span = match type_ascription_span { Some(type_ascription_span) => type_ascription_span, None => name.span(), }; let type_ascription = check!( - namespace.resolve_type_with_self( - type_ascription, - self_type, + ctx.resolve_type_with_self( + insert_type(type_ascription), &type_ascription_span, EnforceTypeArguments::Yes, ), @@ -298,18 +279,11 @@ impl TypedAstNode { warnings, errors ); - let result = { - TypedExpression::type_check(TypeCheckArguments { - checkee: body, - namespace, - return_type_annotation: type_ascription, - help_text: "Variable declaration's type annotation does \ - not match up with the assigned expression's type.", - self_type, - mode: Mode::NonAbi, - opts, - }) - }; + let mut ctx = ctx.with_type_annotation(type_ascription).with_help_text( + "Variable declaration's type annotation does not match up \ + with the assigned expression's type.", + ); + let result = TypedExpression::type_check(ctx.by_ref(), body); let body = check!(result, error_recovery_expr(name.span()), warnings, errors); let typed_var_decl = @@ -317,10 +291,9 @@ impl TypedAstNode { name: name.clone(), body, is_mutable: is_mutable.into(), - const_decl_origin: false, type_ascription, }); - namespace.insert_symbol(name, typed_var_decl.clone()); + ctx.namespace.insert_symbol(name, typed_var_decl.clone()); typed_var_decl } Declaration::ConstantDeclaration(ConstantDeclaration { @@ -330,28 +303,22 @@ impl TypedAstNode { visibility, }) => { let result = - type_check_ascribed_expr(namespace, type_ascription.clone(), value); + type_check_ascribed_expr(ctx.by_ref(), type_ascription, value); is_screaming_snake_case(&name).ok(&mut warnings, &mut errors); let value = check!(result, error_recovery_expr(name.span()), warnings, errors); let typed_const_decl = - TypedDeclaration::VariableDeclaration(TypedVariableDeclaration { + TypedDeclaration::ConstantDeclaration(TypedConstantDeclaration { name: name.clone(), - body: value, - is_mutable: if visibility.is_public() { - VariableMutability::ExportedConst - } else { - VariableMutability::Immutable - }, - const_decl_origin: true, - type_ascription: insert_type(type_ascription), + value, + visibility, }); - namespace.insert_symbol(name, typed_const_decl.clone()); + ctx.namespace.insert_symbol(name, typed_const_decl.clone()); typed_const_decl } Declaration::EnumDeclaration(decl) => { let enum_decl = check!( - TypedEnumDeclaration::type_check(decl, namespace, self_type), + TypedEnumDeclaration::type_check(ctx.by_ref(), decl), return err(warnings, errors), warnings, errors @@ -359,7 +326,7 @@ impl TypedAstNode { let name = enum_decl.name.clone(); let decl = TypedDeclaration::EnumDeclaration(enum_decl); let _ = check!( - namespace.insert_symbol(name, decl.clone()), + ctx.namespace.insert_symbol(name, decl.clone()), return err(warnings, errors), warnings, errors @@ -367,52 +334,36 @@ impl TypedAstNode { decl } Declaration::FunctionDeclaration(fn_decl) => { + let mut ctx = ctx.with_type_annotation(insert_type(TypeInfo::Unknown)); let fn_decl = check!( - TypedFunctionDeclaration::type_check(TypeCheckArguments { - checkee: fn_decl.clone(), - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text, - self_type, - mode: Mode::NonAbi, - opts - }), + TypedFunctionDeclaration::type_check(ctx.by_ref(), fn_decl.clone()), error_recovery_function_declaration(fn_decl), warnings, errors ); let name = fn_decl.name.clone(); let decl = TypedDeclaration::FunctionDeclaration(fn_decl); - namespace.insert_symbol(name, decl.clone()); + ctx.namespace.insert_symbol(name, decl.clone()); decl } Declaration::TraitDeclaration(trait_decl) => { let trait_decl = check!( - TypedTraitDeclaration::type_check(trait_decl, namespace), + TypedTraitDeclaration::type_check(ctx.by_ref(), trait_decl), return err(warnings, errors), warnings, errors ); let name = trait_decl.name.clone(); let decl = TypedDeclaration::TraitDeclaration(trait_decl); - namespace.insert_symbol(name, decl.clone()); + ctx.namespace.insert_symbol(name, decl.clone()); decl } Declaration::Reassignment(Reassignment { lhs, rhs, span }) => { + let ctx = ctx + .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_help_text(""); check!( - reassignment( - TypeCheckArguments { - checkee: (lhs, rhs), - namespace, - self_type, - // this is unused by `reassignment` - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - mode: Mode::NonAbi, - opts, - }, - span, - ), + reassignment(ctx, lhs, rhs, span), return err(warnings, errors), warnings, errors @@ -420,12 +371,12 @@ impl TypedAstNode { } Declaration::ImplTrait(impl_trait) => { let (impl_trait, implementing_for_type_id) = check!( - TypedImplTrait::type_check_impl_trait(impl_trait, namespace, opts), + TypedImplTrait::type_check_impl_trait(ctx.by_ref(), impl_trait), return err(warnings, errors), warnings, errors ); - namespace.insert_trait_implementation( + ctx.namespace.insert_trait_implementation( impl_trait.trait_name.clone(), implementing_for_type_id, impl_trait.methods.clone(), @@ -434,12 +385,12 @@ impl TypedAstNode { } Declaration::ImplSelf(impl_self) => { let impl_trait = check!( - TypedImplTrait::type_check_impl_self(impl_self, namespace, opts), + TypedImplTrait::type_check_impl_self(ctx.by_ref(), impl_self), return err(warnings, errors), warnings, errors ); - namespace.insert_trait_implementation( + ctx.namespace.insert_trait_implementation( impl_trait.trait_name.clone(), impl_trait.implementing_for_type_id, impl_trait.methods.clone(), @@ -448,7 +399,7 @@ impl TypedAstNode { } Declaration::StructDeclaration(decl) => { let decl = check!( - TypedStructDeclaration::type_check(decl, namespace, self_type), + TypedStructDeclaration::type_check(ctx.by_ref(), decl), return err(warnings, errors), warnings, errors @@ -457,7 +408,7 @@ impl TypedAstNode { let decl = TypedDeclaration::StructDeclaration(decl); // insert the struct decl into namespace let _ = check!( - namespace.insert_symbol(name, decl.clone()), + ctx.namespace.insert_symbol(name, decl.clone()), return err(warnings, errors), warnings, errors @@ -466,39 +417,59 @@ impl TypedAstNode { } Declaration::AbiDeclaration(abi_decl) => { let abi_decl = check!( - TypedAbiDeclaration::type_check(abi_decl, namespace, self_type), + TypedAbiDeclaration::type_check(ctx.by_ref(), abi_decl), return err(warnings, errors), warnings, errors ); let name = abi_decl.name.clone(); let decl = TypedDeclaration::AbiDeclaration(abi_decl); - namespace.insert_symbol(name, decl.clone()); + ctx.namespace.insert_symbol(name, decl.clone()); decl } Declaration::StorageDeclaration(StorageDeclaration { span, fields }) => { let mut fields_buf = Vec::with_capacity(fields.len()); for StorageField { name, - type_info: r#type, + type_info, + initializer, } in fields { - let r#type = check!( - namespace.resolve_type_without_self(r#type), + let type_id = check!( + ctx.namespace.resolve_type_without_self( + insert_type(type_info), + &name.span() + ), return err(warnings, errors), warnings, errors ); - fields_buf.push(TypedStorageField::new(name, r#type, span.clone())); - } + let mut ctx = ctx.by_ref().with_type_annotation(type_id); + let initializer = match initializer { + Some(initializer) => Some(check!( + TypedExpression::type_check(ctx.by_ref(), initializer), + return err(warnings, errors), + warnings, + errors, + )), + None => None, + }; + + fields_buf.push(TypedStorageField::new( + name, + type_id, + initializer, + span.clone(), + )); + } let decl = TypedStorageDeclaration::new(fields_buf, span); // insert the storage declaration into the symbols // if there already was one, return an error that duplicate storage // declarations are not allowed check!( - namespace.set_storage_declaration(decl.clone()), + ctx.namespace.set_storage_declaration(decl.clone()), return err(warnings, errors), warnings, errors @@ -507,45 +478,37 @@ impl TypedAstNode { } }) } - AstNodeContent::Expression(a) => { + AstNodeContent::Expression(expr) => { + let ctx = ctx + .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_help_text(""); let inner = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: a.clone(), - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts - }), - error_recovery_expr(a.span()), + TypedExpression::type_check(ctx, expr.clone()), + error_recovery_expr(expr.span()), warnings, errors ); TypedAstNodeContent::Expression(inner) } AstNodeContent::ReturnStatement(ReturnStatement { expr }) => { + let ctx = ctx + // we use "unknown" here because return statements do not + // necessarily follow the type annotation of their immediate + // surrounding context. Because a return statement is control flow + // that breaks out to the nearest function, we need to type check + // it against the surrounding function. + // That is impossible here, as we don't have that information. It + // is the responsibility of the function declaration to type check + // all return statements contained within it. + .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_help_text( + "Returned value must match up with the function return type \ + annotation.", + ); + TypedAstNodeContent::ReturnStatement(TypedReturnStatement { expr: check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: expr.clone(), - namespace, - // we use "unknown" here because return statements do not - // necessarily follow the type annotation of their immediate - // surrounding context. Because a return statement is control flow - // that breaks out to the nearest function, we need to type check - // it against the surrounding function. - // That is impossible here, as we don't have that information. It - // is the responsibility of the function declaration to type check - // all return statements contained within it. - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: - "Returned value must match up with the function return type \ - annotation.", - self_type, - mode: Mode::NonAbi, - opts - }), + TypedExpression::type_check(ctx, expr.clone()), error_recovery_expr(expr.span()), warnings, errors @@ -553,16 +516,10 @@ impl TypedAstNode { }) } AstNodeContent::ImplicitReturnExpression(expr) => { + let ctx = + ctx.with_help_text("Implicit return must match up with block's type."); let typed_expr = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: expr.clone(), - namespace, - return_type_annotation, - help_text: "Implicit return must match up with block's type.", - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, expr.clone()), error_recovery_expr(expr.span()), warnings, errors @@ -570,34 +527,30 @@ impl TypedAstNode { TypedAstNodeContent::ImplicitReturnExpression(typed_expr) } AstNodeContent::WhileLoop(WhileLoop { condition, body }) => { - let typed_condition = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: condition, - namespace, - return_type_annotation: insert_type(TypeInfo::Boolean), - help_text: + let typed_condition = { + let ctx = ctx + .by_ref() + .with_type_annotation(insert_type(TypeInfo::Boolean)) + .with_help_text( "A while loop's loop condition must be a boolean expression.", - self_type, - mode: Mode::NonAbi, - opts - }), - return err(warnings, errors), - warnings, - errors - ); - let (typed_body, _block_implicit_return) = check!( - TypedCodeBlock::type_check(TypeCheckArguments { - checkee: body, - namespace, - return_type_annotation: insert_type(TypeInfo::Tuple(Vec::new())), - help_text: - "A while loop's loop body cannot implicitly return a value.Try \ + ); + check!( + TypedExpression::type_check(ctx, condition), + return err(warnings, errors), + warnings, + errors + ) + }; + + let ctx = ctx + .with_type_annotation(insert_type(TypeInfo::Tuple(Vec::new()))) + .with_help_text( + "A while loop's loop body cannot implicitly return a value. Try \ assigning it to a mutable variable declared outside of the loop \ instead.", - self_type, - mode: Mode::NonAbi, - opts, - }), + ); + let (typed_body, _block_implicit_return) = check!( + TypedCodeBlock::type_check(ctx, body), ( TypedCodeBlock { contents: vec![] }, insert_type(TypeInfo::Tuple(Vec::new())) @@ -635,16 +588,11 @@ impl TypedAstNode { } fn reassignment( - arguments: TypeCheckArguments<'_, (ReassignmentTarget, Expression)>, + ctx: TypeCheckContext, + lhs: ReassignmentTarget, + rhs: Expression, span: Span, ) -> CompileResult { - let TypeCheckArguments { - checkee: (lhs, rhs), - namespace, - self_type, - opts, - .. - } = arguments; let mut errors = vec![]; let mut warnings = vec![]; // ensure that the lhs is a variable expression or struct field access @@ -657,7 +605,7 @@ fn reassignment( Expression::VariableExpression { name, .. } => { // check that the reassigned name exists let unknown_decl = check!( - namespace.resolve_symbol(&name).cloned(), + ctx.namespace.resolve_symbol(&name).cloned(), return err(warnings, errors), warnings, errors @@ -701,22 +649,15 @@ fn reassignment( }; let names_vec = names_vec.into_iter().rev().collect::>(); let (ty_of_field, _ty_of_parent) = check!( - namespace.find_subfield_type(&base_name, &names_vec), + ctx.namespace.find_subfield_type(&base_name, &names_vec), return err(warnings, errors), warnings, errors ); // type check the reassignment + let ctx = ctx.with_type_annotation(ty_of_field).with_help_text(""); let rhs = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: rhs, - namespace, - return_type_annotation: ty_of_field, - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, rhs), error_recovery_expr(span), warnings, errors @@ -733,16 +674,13 @@ fn reassignment( errors, ) } - ReassignmentTarget::StorageField(fields) => reassign_storage_subfield(TypeCheckArguments { - checkee: (fields, span, rhs), - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }) - .map(TypedDeclaration::StorageReassignment), + ReassignmentTarget::StorageField(fields) => { + let ctx = ctx + .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_help_text(""); + reassign_storage_subfield(ctx, fields, rhs, span) + .map(TypedDeclaration::StorageReassignment) + } } } @@ -778,7 +716,7 @@ fn type_check_interface_surface( is_mutable, type_id: check!( namespace.resolve_type_with_self( - look_up_type_id(type_id), + type_id, insert_type(TypeInfo::SelfType), &type_span, EnforceTypeArguments::Yes @@ -793,7 +731,7 @@ fn type_check_interface_surface( .collect(), return_type: check!( namespace.resolve_type_with_self( - return_type, + insert_type(return_type), insert_type(TypeInfo::SelfType), &return_type_span, EnforceTypeArguments::Yes @@ -809,9 +747,8 @@ fn type_check_interface_surface( } fn type_check_trait_methods( + mut ctx: TypeCheckContext, methods: Vec, - namespace: &mut Namespace, - self_type: TypeId, ) -> CompileResult> { let mut warnings = vec![]; let mut errors = vec![]; @@ -828,16 +765,15 @@ fn type_check_trait_methods( .. } in methods { + // A context while checking the signature where `self_type` refers to `SelfType`. + let mut sig_ctx = ctx.by_ref().with_self_type(insert_type(TypeInfo::SelfType)); parameters.clone().into_iter().for_each( |FunctionParameter { - name, - type_id: ref r#type, - .. + name, ref type_id, .. }| { let r#type = check!( - namespace.resolve_type_with_self( - look_up_type_id(*r#type), - insert_type(TypeInfo::SelfType), + sig_ctx.resolve_type_with_self( + *type_id, &name.span(), EnforceTypeArguments::Yes ), @@ -845,7 +781,7 @@ fn type_check_trait_methods( warnings, errors, ); - namespace.insert_symbol( + sig_ctx.namespace.insert_symbol( name.clone(), TypedDeclaration::VariableDeclaration(TypedVariableDeclaration { name: name.clone(), @@ -857,7 +793,6 @@ fn type_check_trait_methods( }, // TODO allow mutable function params? is_mutable: VariableMutability::Immutable, - const_decl_origin: false, type_ascription: r#type, }), ); @@ -915,9 +850,8 @@ fn type_check_trait_methods( name, is_mutable, type_id: check!( - namespace.resolve_type_with_self( - look_up_type_id(type_id), - crate::type_engine::insert_type(TypeInfo::SelfType), + sig_ctx.resolve_type_with_self( + type_id, &type_span, EnforceTypeArguments::Yes ), @@ -933,9 +867,8 @@ fn type_check_trait_methods( // TODO check code block implicit return let return_type = check!( - namespace.resolve_type_with_self( - return_type, - self_type, + ctx.resolve_type_with_self( + insert_type(return_type), &return_type_span, EnforceTypeArguments::Yes ), @@ -943,17 +876,16 @@ fn type_check_trait_methods( warnings, errors, ); + let ctx = ctx + .by_ref() + .with_purity(purity) + .with_type_annotation(return_type) + .with_help_text( + "Trait method body's return type does not match up with its return type \ + annotation.", + ); let (body, _code_block_implicit_return) = check!( - TypedCodeBlock::type_check(TypeCheckArguments { - checkee: body, - namespace, - return_type_annotation: return_type, - help_text: "Trait method body's return type does not match up with \ - its return type annotation.", - self_type, - mode: Mode::NonAbi, - opts: TCOpts { purity } - }), + TypedCodeBlock::type_check(ctx, body), continue, warnings, errors @@ -1050,27 +982,21 @@ impl PartialEq for TypeCheckedStorageReassignDescriptor { } fn reassign_storage_subfield( - arguments: TypeCheckArguments<'_, (Vec, Span, Expression)>, + ctx: TypeCheckContext, + fields: Vec, + rhs: Expression, + span: Span, ) -> CompileResult { - let TypeCheckArguments { - checkee: (fields, span, rhs), - namespace, - return_type_annotation: _return_type_annotation, - help_text: _help_text, - self_type, - opts, - .. - } = arguments; let mut errors = vec![]; let mut warnings = vec![]; - if !namespace.has_storage_declared() { + if !ctx.namespace.has_storage_declared() { errors.push(CompileError::NoDeclaredStorage { span }); return err(warnings, errors); } let storage_fields = check!( - namespace.get_storage_field_descriptors(), + ctx.namespace.get_storage_field_descriptors(), return err(warnings, errors), warnings, errors @@ -1146,16 +1072,9 @@ fn reassign_storage_subfield( } } } + let ctx = ctx.with_type_annotation(curr_type).with_help_text(""); let rhs = check!( - TypedExpression::type_check(TypeCheckArguments { - checkee: rhs, - namespace, - return_type_annotation: curr_type, - help_text: Default::default(), - self_type, - mode: Mode::NonAbi, - opts, - }), + TypedExpression::type_check(ctx, rhs), error_recovery_expr(span), warnings, errors diff --git a/sway-core/src/semantic_analysis/module.rs b/sway-core/src/semantic_analysis/module.rs index 08307da5d4a..e662c429f7e 100644 --- a/sway-core/src/semantic_analysis/module.rs +++ b/sway-core/src/semantic_analysis/module.rs @@ -19,13 +19,13 @@ impl TypedModule { /// Type-check the given parsed module to produce a typed module. /// /// Recursively type-checks submodules first. - pub fn type_check(parsed: ParseModule, namespace: &mut Namespace) -> CompileResult { + pub fn type_check(mut ctx: TypeCheckContext, parsed: ParseModule) -> CompileResult { let ParseModule { submodules, tree } = parsed; // Type-check submodules first in order of declaration. let mut submodules_res = ok(vec![], vec![], vec![]); for (name, submodule) in submodules { - let submodule_res = TypedSubmodule::type_check(name.clone(), submodule, namespace); + let submodule_res = TypedSubmodule::type_check(ctx.by_ref(), name.clone(), submodule); submodules_res = submodules_res.flat_map(|mut submodules| { submodule_res.map(|submodule| { submodules.push((name, submodule)); @@ -38,41 +38,31 @@ impl TypedModule { let ordered_nodes_res = node_dependencies::order_ast_nodes_by_dependency(tree.root_nodes); let typed_nodes_res = ordered_nodes_res - .flat_map(|ordered_nodes| Self::type_check_nodes(ordered_nodes, namespace)); + .flat_map(|ordered_nodes| Self::type_check_nodes(ctx.by_ref(), ordered_nodes)); let validated_nodes_res = typed_nodes_res.flat_map(|typed_nodes| { - let errors = check_supertraits(&typed_nodes, namespace); + let errors = check_supertraits(&typed_nodes, ctx.namespace); ok(typed_nodes, vec![], errors) }); submodules_res.flat_map(|submodules| { validated_nodes_res.map(|all_nodes| Self { submodules, - namespace: namespace.module().clone(), + namespace: ctx.namespace.module().clone(), all_nodes, }) }) } fn type_check_nodes( + mut ctx: TypeCheckContext, nodes: Vec, - namespace: &mut Namespace, ) -> CompileResult> { let mut warnings = Vec::new(); let mut errors = Vec::new(); let typed_nodes = nodes .into_iter() - .map(|node| { - TypedAstNode::type_check(TypeCheckArguments { - checkee: node, - namespace, - return_type_annotation: insert_type(TypeInfo::Unknown), - help_text: Default::default(), - self_type: insert_type(TypeInfo::Contract), - mode: Mode::NonAbi, - opts: Default::default(), - }) - }) + .map(|node| TypedAstNode::type_check(ctx.by_ref(), node)) .filter_map(|res| res.ok(&mut warnings, &mut errors)) .collect(); @@ -86,19 +76,20 @@ impl TypedModule { impl TypedSubmodule { pub fn type_check( + parent_ctx: TypeCheckContext, dep_name: DepName, submodule: ParseSubmodule, - parent_namespace: &mut Namespace, ) -> CompileResult { let ParseSubmodule { library_name, module, } = submodule; - let mut dep_namespace = parent_namespace.enter_submodule(dep_name); - let module_res = TypedModule::type_check(module, &mut dep_namespace); - module_res.map(|module| TypedSubmodule { - library_name, - module, + parent_ctx.enter_submodule(dep_name, |submod_ctx| { + let module_res = TypedModule::type_check(submod_ctx, module); + module_res.map(|module| TypedSubmodule { + library_name, + module, + }) }) } } diff --git a/sway-core/src/semantic_analysis/namespace/items.rs b/sway-core/src/semantic_analysis/namespace/items.rs index 995b5885c47..92f137fc7a4 100644 --- a/sway-core/src/semantic_analysis/namespace/items.rs +++ b/sway-core/src/semantic_analysis/namespace/items.rs @@ -138,33 +138,6 @@ impl Items { .get_methods_for_type(implementing_for_type_id) } - // Given a TypeInfo old_type with a set of methods available to it, make those same methods - // available to TypeInfo new_type. This is useful in situations where old_type is being - // monomorphized to new_type and and we want `get_methods_for_type()` to return the same set of - // methods for new_type as it does for old_type. - pub(crate) fn copy_methods_to_type( - &mut self, - old_type: TypeId, - new_type: TypeId, - type_mapping: &TypeMapping, - ) { - // This map grabs all (trait name, vec of methods) from self.implemented_traits - // corresponding to `old_type`. - let methods = self - .implemented_traits - .get_methods_for_type_by_trait(old_type); - - // Insert into `self.implemented_traits` the contents of the map above but with `new_type` - // as the `TypeInfo` key. - for (trait_name, mut trait_methods) in methods.into_iter() { - trait_methods - .iter_mut() - .for_each(|method| method.copy_types(type_mapping)); - self.implemented_traits - .insert(trait_name, new_type, trait_methods); - } - } - pub(crate) fn get_canonical_path(&self, symbol: &Ident) -> &[Ident] { self.use_synonyms.get(symbol).map(|v| &v[..]).unwrap_or(&[]) } diff --git a/sway-core/src/semantic_analysis/namespace/namespace.rs b/sway-core/src/semantic_analysis/namespace/namespace.rs index 7e8ad5d8d3b..187e260659d 100644 --- a/sway-core/src/semantic_analysis/namespace/namespace.rs +++ b/sway-core/src/semantic_analysis/namespace/namespace.rs @@ -1,16 +1,11 @@ use crate::{ - semantic_analysis::{ - ast_node::TypedExpression, - declaration::{EnforceTypeArguments, Monomorphize, MonomorphizeHelper}, - }, - type_engine::*, - CallPath, CompileResult, Ident, TypeArgument, TypeInfo, TypedDeclaration, - TypedFunctionDeclaration, + semantic_analysis::ast_node::TypedExpression, type_engine::*, CallPath, CompileResult, Ident, + TypedDeclaration, TypedFunctionDeclaration, }; use super::{module::Module, root::Root, submodule_namespace::SubmoduleNamespace, Path, PathBuf}; -use sway_types::{span::Span, Spanned}; +use sway_types::span::Span; use std::collections::VecDeque; @@ -100,49 +95,24 @@ impl Namespace { /// Short-hand for calling [Root::resolve_type_with_self] on `root` with the `mod_path`. pub(crate) fn resolve_type_with_self( &mut self, - type_info: TypeInfo, + mut type_id: TypeId, self_type: TypeId, span: &Span, enforce_type_args: EnforceTypeArguments, ) -> CompileResult { - self.root.resolve_type_with_self( - type_info, - self_type, - span, - enforce_type_args, - &self.mod_path, - ) + type_id.replace_self_type(self_type); + self.root + .resolve_type(type_id, span, enforce_type_args, &self.mod_path) } /// Short-hand for calling [Root::resolve_type_without_self] on `root` and with the `mod_path`. pub(crate) fn resolve_type_without_self( &mut self, - type_info: TypeInfo, + type_id: TypeId, + span: &Span, ) -> CompileResult { self.root - .resolve_type_without_self(type_info, &self.mod_path) - } - - /// Short-hand for calling `monomorphize` from the `Monomorphize` trait, on `root` with the `mod_path`. - pub(crate) fn monomorphize( - &mut self, - decl: T, - type_arguments: Vec, - enforce_type_arguments: EnforceTypeArguments, - self_type: Option, - call_site_span: Option<&Span>, - ) -> CompileResult - where - T: MonomorphizeHelper + Spanned, - { - decl.monomorphize( - type_arguments, - enforce_type_arguments, - self_type, - call_site_span, - &mut self.root, - &self.mod_path, - ) + .resolve_type(type_id, span, EnforceTypeArguments::Yes, &self.mod_path) } /// Short-hand for calling [Root::find_method_for_type] on `root` with the `mod_path`. diff --git a/sway-core/src/semantic_analysis/namespace/root.rs b/sway-core/src/semantic_analysis/namespace/root.rs index d32aa8529b8..dd9581c042d 100644 --- a/sway-core/src/semantic_analysis/namespace/root.rs +++ b/sway-core/src/semantic_analysis/namespace/root.rs @@ -64,17 +64,16 @@ impl Root { }) } - pub(crate) fn resolve_type_with_self( + pub(crate) fn resolve_type( &mut self, - type_info: TypeInfo, - self_type: TypeId, + type_id: TypeId, span: &Span, enforce_type_arguments: EnforceTypeArguments, mod_path: &Path, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; - let type_id = match type_info { + let type_id = match look_up_type_id(type_id) { TypeInfo::Custom { ref name, type_arguments, @@ -84,13 +83,13 @@ impl Root { .ok(&mut warnings, &mut errors) .cloned() { - Some(TypedDeclaration::StructDeclaration(decl)) => { - let new_decl = check!( - decl.monomorphize( + Some(TypedDeclaration::StructDeclaration(mut decl)) => { + check!( + monomorphize( + &mut decl, type_arguments, enforce_type_arguments, - Some(self_type), - Some(span), + span, self, mod_path // NOTE: Once `TypeInfo::Custom` takes a `CallPath`, this will need to change ), @@ -98,15 +97,15 @@ impl Root { warnings, errors ); - new_decl.create_type_id() + decl.create_type_id() } - Some(TypedDeclaration::EnumDeclaration(decl)) => { - let new_decl = check!( - decl.monomorphize( + Some(TypedDeclaration::EnumDeclaration(mut decl)) => { + check!( + monomorphize( + &mut decl, type_arguments, enforce_type_arguments, - Some(self_type), - Some(span), + span, self, mod_path // NOTE: Once `TypeInfo::Custom` takes a `CallPath`, this will need to change ), @@ -114,7 +113,7 @@ impl Root { warnings, errors ); - new_decl.create_type_id() + decl.create_type_id() } Some(TypedDeclaration::GenericTypeForFunctionScope { name, type_id }) => { insert_type(TypeInfo::Ref(type_id, name.span())) @@ -124,21 +123,14 @@ impl Root { name: name.to_string(), span: name.span(), }); - return err(warnings, errors); + insert_type(TypeInfo::ErrorRecovery) } } } - TypeInfo::SelfType => self_type, TypeInfo::Ref(id, _) => id, TypeInfo::Array(type_id, n) => { let new_type_id = check!( - self.resolve_type_with_self( - look_up_type_id(type_id), - self_type, - span, - enforce_type_arguments, - mod_path - ), + self.resolve_type(type_id, span, enforce_type_arguments, mod_path), insert_type(TypeInfo::ErrorRecovery), warnings, errors @@ -148,9 +140,8 @@ impl Root { TypeInfo::Tuple(mut type_arguments) => { for type_argument in type_arguments.iter_mut() { type_argument.type_id = check!( - self.resolve_type_with_self( - look_up_type_id(type_argument.type_id), - self_type, + self.resolve_type( + type_argument.type_id, span, enforce_type_arguments, mod_path @@ -167,90 +158,6 @@ impl Root { ok(type_id, warnings, errors) } - pub(crate) fn resolve_type_without_self( - &mut self, - type_info: TypeInfo, - mod_path: &Path, - ) -> CompileResult { - let mut warnings = vec![]; - let mut errors = vec![]; - let type_id = match type_info { - TypeInfo::Custom { - name, - type_arguments, - } => { - match self - .resolve_symbol(mod_path, &name) - .ok(&mut warnings, &mut errors) - .cloned() - { - Some(TypedDeclaration::StructDeclaration(decl)) => { - let new_decl = check!( - decl.monomorphize( - type_arguments, - EnforceTypeArguments::No, - None, - None, - self, - mod_path // NOTE: Once `TypeInfo::Custom` takes a `CallPath`, this will need to change - ), - return err(warnings, errors), - warnings, - errors - ); - new_decl.create_type_id() - } - Some(TypedDeclaration::EnumDeclaration(decl)) => { - let new_decl = check!( - decl.monomorphize( - type_arguments, - EnforceTypeArguments::No, - None, - None, - self, - mod_path // NOTE: Once `TypeInfo::Custom` takes a `CallPath`, this will need to change - ), - return err(warnings, errors), - warnings, - errors - ); - new_decl.create_type_id() - } - Some(TypedDeclaration::GenericTypeForFunctionScope { name, type_id }) => { - insert_type(TypeInfo::Ref(type_id, name.span())) - } - _ => insert_type(TypeInfo::Unknown), - } - } - TypeInfo::Ref(id, _) => id, - TypeInfo::Array(type_id, n) => { - let new_type_id = check!( - self.resolve_type_without_self(look_up_type_id(type_id), mod_path), - insert_type(TypeInfo::ErrorRecovery), - warnings, - errors - ); - insert_type(TypeInfo::Array(new_type_id, n)) - } - TypeInfo::Tuple(mut type_arguments) => { - for type_argument in type_arguments.iter_mut() { - type_argument.type_id = check!( - self.resolve_type_without_self( - look_up_type_id(type_argument.type_id), - mod_path - ), - insert_type(TypeInfo::ErrorRecovery), - warnings, - errors - ); - } - insert_type(TypeInfo::Tuple(type_arguments)) - } - o => insert_type(o), - }; - ok(type_id, warnings, errors) - } - /// Given a method and a type (plus a `self_type` to potentially resolve it), find that method /// in the namespace. Requires `args_buf` because of some special casing for the standard /// library where we pull the type from the arguments buffer. @@ -262,7 +169,7 @@ impl Root { pub(crate) fn find_method_for_type( &mut self, mod_path: &Path, - r#type: TypeId, + mut type_id: TypeId, method_path: &Path, self_type: TypeId, args_buf: &VecDeque, @@ -279,16 +186,17 @@ impl Root { ); // grab the local methods from the local module - let local_methods = local_module.get_methods_for_type(r#type); + let local_methods = local_module.get_methods_for_type(type_id); // split into the method name and method prefix let (method_name, method_prefix) = method_path.split_last().expect("method path is empty"); + type_id.replace_self_type(self_type); + // resolve the type - let r#type = check!( - self.resolve_type_with_self( - look_up_type_id(r#type), - self_type, + let type_id = check!( + self.resolve_type( + type_id, &method_name.span(), EnforceTypeArguments::No, method_prefix @@ -307,7 +215,7 @@ impl Root { ); // grab the methods from where the type is declared - let mut type_methods = type_module.get_methods_for_type(r#type); + let mut type_methods = type_module.get_methods_for_type(type_id); let mut methods = local_methods; methods.append(&mut type_methods); @@ -323,7 +231,7 @@ impl Root { { errors.push(CompileError::MethodNotFound { method_name: method_name.clone(), - type_name: r#type.to_string(), + type_name: type_id.to_string(), }); } err(warnings, errors) diff --git a/sway-core/src/semantic_analysis/namespace/trait_map.rs b/sway-core/src/semantic_analysis/namespace/trait_map.rs index ee6202df506..72f9c1eb890 100644 --- a/sway-core/src/semantic_analysis/namespace/trait_map.rs +++ b/sway-core/src/semantic_analysis/namespace/trait_map.rs @@ -1,10 +1,8 @@ use crate::{ - type_engine::{look_up_type_id, TypeId}, + type_engine::{create_type_mapping, look_up_type_id, CopyTypes, TypeId}, CallPath, TypeInfo, TypedFunctionDeclaration, }; -use std::collections::HashMap; - type TraitName = CallPath; // This cannot be a HashMap because of how TypeInfo's are handled. @@ -46,8 +44,7 @@ impl TraitMap { ) { let mut methods_map = im::HashMap::new(); for method in methods.into_iter() { - let method_name = method.name.as_str().to_string(); - methods_map.insert(method_name, method); + methods_map.insert(method.name.as_str().to_string(), method); } self.trait_map .push_back(((trait_name, incoming_type_id), methods_map)); @@ -69,7 +66,7 @@ impl TraitMap { ) -> Vec<((CallPath, TypeId), Vec)> { let mut ret = vec![]; for ((call_path, map_type_id), methods) in self.trait_map.iter() { - if look_up_type_id(*map_type_id) == look_up_type_id(incoming_type_id) { + if look_up_type_id(incoming_type_id).is_subset_of(&look_up_type_id(*map_type_id)) { ret.push(( (call_path.clone(), *map_type_id), methods.values().cloned().collect(), @@ -88,29 +85,14 @@ impl TraitMap { if look_up_type_id(incoming_type_id) == TypeInfo::ErrorRecovery { return methods; } - for ((_, map_type_id), l_methods) in self.trait_map.iter() { - if look_up_type_id(*map_type_id) == look_up_type_id(incoming_type_id) { - methods.append(&mut l_methods.values().cloned().collect()); - } - } - methods - } - - pub(crate) fn get_methods_for_type_by_trait( - &self, - incoming_type_id: TypeId, - ) -> HashMap> { - let mut methods: HashMap> = HashMap::new(); - // small performance gain in bad case - if look_up_type_id(incoming_type_id) == TypeInfo::ErrorRecovery { - return methods; - } - for ((trait_name, map_type_id), trait_methods) in self.trait_map.iter() { - if look_up_type_id(*map_type_id) == look_up_type_id(incoming_type_id) { - methods.insert( - (*trait_name).clone(), - trait_methods.values().cloned().collect(), - ); + for ((_, map_type_id), trait_methods) in self.trait_map.iter() { + if look_up_type_id(incoming_type_id).is_subset_of(&look_up_type_id(*map_type_id)) { + let type_mapping = create_type_mapping(*map_type_id, incoming_type_id); + let mut trait_methods = trait_methods.values().cloned().collect::>(); + trait_methods + .iter_mut() + .for_each(|x| x.copy_types(&type_mapping)); + methods.append(&mut trait_methods); } } methods diff --git a/sway-core/src/semantic_analysis/node_dependencies.rs b/sway-core/src/semantic_analysis/node_dependencies.rs index c9f84691114..69e7006f0f2 100644 --- a/sway-core/src/semantic_analysis/node_dependencies.rs +++ b/sway-core/src/semantic_analysis/node_dependencies.rs @@ -1,6 +1,7 @@ use std::collections::{HashMap, HashSet}; use std::iter::FromIterator; +use crate::type_engine::{TypeArgument, TypeParameter}; use crate::{ error::*, parse_tree::*, @@ -474,10 +475,9 @@ impl Dependencies { } Expression::TupleIndex { prefix, .. } => self.gather_from_expr(prefix), Expression::StorageAccess { .. } => self, - Expression::IntrinsicFunction { kind, .. } => match kind { - IntrinsicFunctionKind::SizeOfVal { exp } => self.gather_from_expr(exp), - _ => self, - }, + Expression::IntrinsicFunction { arguments, .. } => { + self.gather_from_iter(arguments.iter(), |deps, arg| deps.gather_from_expr(arg)) + } } } diff --git a/sway-core/src/semantic_analysis/program.rs b/sway-core/src/semantic_analysis/program.rs index 02c314428b8..ed05292ac25 100644 --- a/sway-core/src/semantic_analysis/program.rs +++ b/sway-core/src/semantic_analysis/program.rs @@ -7,11 +7,12 @@ use crate::{ parse_tree::{ParseProgram, Purity, TreeType}, semantic_analysis::{ namespace::{self, Namespace}, - TypedModule, + TypeCheckContext, TypedModule, }, type_engine::*, types::ToJsonAbi, }; +use fuel_tx::StorageSlot; use fuels_types::JsonABI; use sway_types::{span::Span, Ident, Spanned}; @@ -19,6 +20,7 @@ use sway_types::{span::Span, Ident, Spanned}; pub struct TypedProgram { pub kind: TypedProgramKind, pub root: TypedModule, + pub storage_slots: Vec, } impl TypedProgram { @@ -31,12 +33,17 @@ impl TypedProgram { initial_namespace: namespace::Module, ) -> CompileResult { let mut namespace = Namespace::init_root(initial_namespace); + 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(root, &mut namespace); + let mod_res = TypedModule::type_check(ctx, root); mod_res.flat_map(|root| { let kind_res = Self::validate_root(&root, kind, mod_span); - kind_res.map(|kind| Self { kind, root }) + kind_res.map(|kind| Self { + kind, + root, + storage_slots: vec![], + }) }) } @@ -220,6 +227,60 @@ impl TypedProgram { err(vec![], errors) } } + + pub fn get_typed_program_with_initialized_storage_slots(&self) -> CompileResult { + let mut warnings = vec![]; + let mut errors = vec![]; + match &self.kind { + TypedProgramKind::Contract { declarations, .. } => { + let storage_decl = declarations + .iter() + .find(|decl| matches!(decl, TypedDeclaration::StorageDeclaration(_))); + + // Expecting at most a single storage declaration + match storage_decl { + Some(TypedDeclaration::StorageDeclaration(decl)) => { + let mut storage_slots = check!( + decl.get_initialized_storage_slots(), + return err(warnings, errors), + warnings, + errors, + ); + // Sort the slots to standardize the output. Not strictly required by the + // spec. + storage_slots.sort(); + ok( + Self { + kind: self.kind.clone(), + root: self.root.clone(), + storage_slots, + }, + warnings, + errors, + ) + } + _ => ok( + Self { + kind: self.kind.clone(), + root: self.root.clone(), + storage_slots: vec![], + }, + warnings, + errors, + ), + } + } + _ => ok( + Self { + kind: self.kind.clone(), + root: self.root.clone(), + storage_slots: vec![], + }, + warnings, + errors, + ), + } + } } #[derive(Clone, Debug)] diff --git a/sway-core/src/semantic_analysis/type_check_arguments.rs b/sway-core/src/semantic_analysis/type_check_arguments.rs deleted file mode 100644 index 11d9adf467e..00000000000 --- a/sway-core/src/semantic_analysis/type_check_arguments.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::parse_tree::declaration::Purity; -use crate::semantic_analysis::{ast_node::Mode, *}; -use crate::type_engine::*; - -pub struct TypeCheckArguments<'a, T> { - pub checkee: T, - pub namespace: &'a mut Namespace, - pub return_type_annotation: TypeId, - pub help_text: &'static str, - pub self_type: TypeId, - pub mode: Mode, - pub opts: TCOpts, -} - -#[derive(Default, Clone, Copy)] -pub struct TCOpts { - pub(crate) purity: Purity, -} diff --git a/sway-core/src/semantic_analysis/type_check_context.rs b/sway-core/src/semantic_analysis/type_check_context.rs new file mode 100644 index 00000000000..88130d509e4 --- /dev/null +++ b/sway-core/src/semantic_analysis/type_check_context.rs @@ -0,0 +1,224 @@ +use crate::{ + parse_tree::declaration::Purity, + semantic_analysis::{ast_node::Mode, Namespace}, + type_engine::{ + insert_type, monomorphize, unify_with_self, CopyTypes, EnforceTypeArguments, + MonomorphizeHelper, TypeArgument, TypeId, TypeInfo, + }, + CompileResult, CompileWarning, TypeError, +}; +use sway_types::{span::Span, Ident}; + +/// Contextual state tracked and accumulated throughout type-checking. +pub struct TypeCheckContext<'ns> { + /// The namespace context accumulated throughout type-checking. + /// + /// Internally, this includes: + /// + /// - The `root` module from which all other modules maybe be accessed using absolute paths. + /// - The `init` module used to initialise submodule namespaces. + /// - A `mod_path` that represents the current module being type-checked. This is automatically + /// updated upon entering/exiting submodules via the `enter_submodule` method. + pub(crate) namespace: &'ns mut Namespace, + + // 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 + // the parent nodes. + /// While type-checking an `impl` (whether inherent or for a `trait`/`abi`) this represents the + /// type for which we are implementing. For example in `impl Foo {}` or `impl Trait for Foo + /// {}`, this represents the type ID of `Foo`. + self_type: TypeId, + /// While type-checking an expression, this indicates the expected type. + /// + /// Assists type inference. + type_annotation: TypeId, + /// Whether or not we're within an `abi` implementation. + /// + /// This is `ImplAbiFn` while checking `abi` implementations whether at their original impl + /// declaration or within an abi cast expression. + mode: Mode, + /// Provides "help text" to `TypeError`s during unification. + // TODO: We probably shouldn't carry this through the `Context`, but instead pass it directly + // to `unify` as necessary? + help_text: &'static str, + /// Tracks the purity of the context, e.g. whether or not we should be allowed to write to + /// storage. + purity: Purity, +} + +impl<'ns> TypeCheckContext<'ns> { + /// Initialise a context at the top-level of a module with its namespace. + /// + /// Initializes with: + /// + /// - type_annotation: unknown + /// - mode: NoneAbi + /// - help_text: "" + /// - purity: Pure + pub fn from_root(root_namespace: &'ns mut Namespace) -> Self { + Self::from_module_namespace(root_namespace) + } + + fn from_module_namespace(namespace: &'ns mut Namespace) -> Self { + Self { + namespace, + type_annotation: insert_type(TypeInfo::Unknown), + help_text: "", + // TODO: Contract? Should this be passed in based on program kind (aka TreeType)? + self_type: insert_type(TypeInfo::Contract), + mode: Mode::NonAbi, + purity: Purity::default(), + } + } + + /// Create a new context that mutably borrows the inner `namespace` with a lifetime bound by + /// `self`. + /// + /// This is particularly useful when type-checking a node that has more than one child node + /// (very often the case). By taking the context with the namespace lifetime bound to `self` + /// 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(&mut self) -> TypeCheckContext { + TypeCheckContext { + namespace: self.namespace, + type_annotation: self.type_annotation, + self_type: self.self_type, + mode: self.mode, + help_text: self.help_text, + purity: self.purity, + } + } + + /// Scope the `TypeCheckContext` with the given `Namespace`. + pub fn scoped(self, namespace: &mut Namespace) -> TypeCheckContext { + TypeCheckContext { + namespace, + type_annotation: self.type_annotation, + self_type: self.self_type, + mode: self.mode, + help_text: self.help_text, + purity: self.purity, + } + } + + /// Enter the submodule with the given name and produce a type-check context ready for + /// type-checking its content. + /// + /// Returns the result of the given `with_submod_ctx` function. + pub fn enter_submodule(self, dep_name: Ident, with_submod_ctx: F) -> T + where + F: FnOnce(TypeCheckContext) -> T, + { + // We're checking a submodule, so no need to pass through anything other than the + // namespace. However, we will likely want to pass through the type engine and declaration + // 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); + with_submod_ctx(submod_ctx) + } + + /// Map this `TypeCheckContext` instance to a new one with the given `help_text`. + pub(crate) fn with_help_text(self, help_text: &'static str) -> Self { + Self { help_text, ..self } + } + + /// Map this `TypeCheckContext` instance to a new one with the given type annotation. + pub(crate) fn with_type_annotation(self, type_annotation: TypeId) -> Self { + Self { + type_annotation, + ..self + } + } + + /// Map this `TypeCheckContext` instance to a new one with the given ABI `mode`. + pub(crate) fn with_mode(self, mode: Mode) -> Self { + Self { mode, ..self } + } + + /// Map this `TypeCheckContext` instance to a new one with the given purity. + pub(crate) fn with_purity(self, purity: Purity) -> Self { + Self { purity, ..self } + } + + /// Map this `TypeCheckContext` instance to a new one with the given purity. + pub(crate) fn with_self_type(self, self_type: TypeId) -> Self { + Self { self_type, ..self } + } + + // A set of accessor methods. We do this rather than making the fields `pub` in order to ensure + // that these are only updated via the `with_*` methods that produce a new `TypeCheckContext`. + + pub(crate) fn help_text(&self) -> &'static str { + self.help_text + } + + pub(crate) fn type_annotation(&self) -> TypeId { + self.type_annotation + } + + pub(crate) fn mode(&self) -> Mode { + self.mode + } + + pub(crate) fn purity(&self) -> Purity { + self.purity + } + + pub(crate) fn self_type(&self) -> TypeId { + self.self_type + } + + // Provide some convenience functions around the inner context. + + /// Short-hand for calling the `monomorphize` function in the type engine + pub(crate) fn monomorphize( + &mut self, + value: &mut T, + type_arguments: Vec, + enforce_type_arguments: EnforceTypeArguments, + call_site_span: &Span, + ) -> CompileResult<()> + where + T: MonomorphizeHelper + CopyTypes, + { + monomorphize( + value, + type_arguments, + enforce_type_arguments, + call_site_span, + &mut self.namespace.root, + &self.namespace.mod_path, + ) + } + + /// Short-hand for calling [Namespace::resolve_type_with_self] with the `self_type` provided by + /// the `TypeCheckContext`. + pub(crate) fn resolve_type_with_self( + &mut self, + type_id: TypeId, + span: &Span, + enforce_type_args: EnforceTypeArguments, + ) -> CompileResult { + self.namespace + .resolve_type_with_self(type_id, self.self_type, span, enforce_type_args) + } + + /// Short-hand around `type_engine::unify_with_self`, where the `TypeCheckContext` provides the + /// type annotation, self type and help text. + pub(crate) fn unify_with_self( + &self, + ty: TypeId, + span: &Span, + ) -> (Vec, Vec) { + unify_with_self( + ty, + self.type_annotation(), + self.self_type(), + span, + self.help_text(), + ) + } +} diff --git a/sway-core/src/type_engine/engine.rs b/sway-core/src/type_engine/engine.rs index c7f089ba5ae..bbd30a4ab10 100644 --- a/sway-core/src/type_engine/engine.rs +++ b/sway-core/src/type_engine/engine.rs @@ -1,9 +1,10 @@ use super::*; use crate::concurrent_slab::ConcurrentSlab; +use crate::namespace::{Path, Root}; use crate::type_engine::AbiName; use lazy_static::lazy_static; use sway_types::span::Span; -use sway_types::Spanned; +use sway_types::{Ident, Spanned}; lazy_static! { static ref TYPE_ENGINE: Engine = Engine::default(); @@ -30,6 +31,95 @@ impl Engine { } } + fn monomorphize( + &self, + value: &mut T, + mut type_arguments: Vec, + enforce_type_arguments: EnforceTypeArguments, + call_site_span: &Span, + namespace: &mut Root, + module_path: &Path, + ) -> CompileResult<()> + where + T: MonomorphizeHelper + CopyTypes, + { + let mut warnings = vec![]; + let mut errors = vec![]; + match ( + value.type_parameters().is_empty(), + type_arguments.is_empty(), + ) { + (true, true) => ok((), warnings, errors), + (false, true) => { + if let EnforceTypeArguments::Yes = enforce_type_arguments { + errors.push(CompileError::NeedsTypeArguments { + name: value.name().clone(), + span: call_site_span.clone(), + }); + return err(warnings, errors); + } + let type_mapping = insert_type_parameters(value.type_parameters()); + value.copy_types(&type_mapping); + ok((), warnings, errors) + } + (true, false) => { + let type_arguments_span = type_arguments + .iter() + .map(|x| x.span.clone()) + .reduce(Span::join) + .unwrap_or_else(|| value.name().span()); + errors.push(CompileError::DoesNotTakeTypeArguments { + name: value.name().clone(), + span: type_arguments_span, + }); + err(warnings, errors) + } + (false, false) => { + let type_arguments_span = type_arguments + .iter() + .map(|x| x.span.clone()) + .reduce(Span::join) + .unwrap_or_else(|| value.name().span()); + if value.type_parameters().len() != type_arguments.len() { + errors.push(CompileError::IncorrectNumberOfTypeArguments { + given: type_arguments.len(), + expected: value.type_parameters().len(), + span: type_arguments_span, + }); + return err(warnings, errors); + } + for type_argument in type_arguments.iter_mut() { + type_argument.type_id = check!( + namespace.resolve_type( + type_argument.type_id, + &type_argument.span, + enforce_type_arguments, + module_path + ), + insert_type(TypeInfo::ErrorRecovery), + warnings, + errors + ); + } + let type_mapping = insert_type_parameters(value.type_parameters()); + for ((_, interim_type), type_argument) in + type_mapping.iter().zip(type_arguments.iter()) + { + let (mut new_warnings, new_errors) = unify( + *interim_type, + type_argument.type_id, + &type_argument.span, + "Type argument is not assignable to generic type parameter.", + ); + warnings.append(&mut new_warnings); + errors.append(&mut new_errors.into_iter().map(|x| x.into()).collect()); + } + value.copy_types(&type_mapping); + ok((), warnings, errors) + } + } + } + /// Make the types of two type terms equivalent (or produce an error if /// there is a conflict between them). // @@ -380,6 +470,27 @@ pub(crate) fn look_up_type_id_raw(id: TypeId) -> TypeInfo { TYPE_ENGINE.look_up_type_id_raw(id) } +pub(crate) fn monomorphize( + value: &mut T, + type_arguments: Vec, + enforce_type_arguments: EnforceTypeArguments, + call_site_span: &Span, + namespace: &mut Root, + module_path: &Path, +) -> CompileResult<()> +where + T: MonomorphizeHelper + CopyTypes, +{ + TYPE_ENGINE.monomorphize( + value, + type_arguments, + enforce_type_arguments, + call_site_span, + namespace, + module_path, + ) +} + pub fn unify_with_self( a: TypeId, b: TypeId, @@ -427,3 +538,43 @@ enum NumericCastCompatResult { Compatible, CastableWithWarning(Warning), } + +pub(crate) trait MonomorphizeHelper { + fn name(&self) -> &Ident; + fn type_parameters(&self) -> &[TypeParameter]; +} + +/// This type is used to denote if, during monomorphization, the compiler +/// should enforce that type arguments be provided. An example of that +/// might be this: +/// +/// ```ignore +/// struct Point { +/// x: u64, +/// y: u64 +/// } +/// +/// fn add(p1: Point, p2: Point) -> Point { +/// Point { +/// x: p1.x + p2.x, +/// y: p1.y + p2.y +/// } +/// } +/// ``` +/// +/// `EnforeTypeArguments` would require that the type annotations +/// for `p1` and `p2` contain `<...>`. This is to avoid ambiguous definitions: +/// +/// ```ignore +/// fn add(p1: Point, p2: Point) -> Point { +/// Point { +/// x: p1.x + p2.x, +/// y: p1.y + p2.y +/// } +/// } +/// ``` +#[derive(Clone, Copy)] +pub(crate) enum EnforceTypeArguments { + Yes, + No, +} diff --git a/sway-core/src/type_engine/mod.rs b/sway-core/src/type_engine/mod.rs index 5c04578f3a0..23f6fd58f9a 100644 --- a/sway-core/src/type_engine/mod.rs +++ b/sway-core/src/type_engine/mod.rs @@ -4,9 +4,12 @@ mod engine; mod integer_bits; mod replace_self_type; mod resolved_type; +mod trait_constraint; +mod type_argument; mod type_id; mod type_info; mod type_mapping; +mod type_parameter; mod unresolved_type_check; pub(crate) use copy_types::*; @@ -15,9 +18,12 @@ pub use engine::*; pub use integer_bits::*; pub(crate) use replace_self_type::*; pub(crate) use resolved_type::*; +pub(crate) use trait_constraint::*; +pub(crate) use type_argument::*; pub use type_id::*; pub use type_info::*; pub(crate) use type_mapping::*; +pub(crate) use type_parameter::*; pub(crate) use unresolved_type_check::*; use crate::error::*; diff --git a/sway-core/src/type_engine/trait_constraint.rs b/sway-core/src/type_engine/trait_constraint.rs new file mode 100644 index 00000000000..70bc2f985ad --- /dev/null +++ b/sway-core/src/type_engine/trait_constraint.rs @@ -0,0 +1,6 @@ +use crate::CallPath; + +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub(crate) struct TraitConstraint { + pub(crate) call_path: CallPath, +} diff --git a/sway-core/src/parse_tree/declaration/type_argument.rs b/sway-core/src/type_engine/type_argument.rs similarity index 100% rename from sway-core/src/parse_tree/declaration/type_argument.rs rename to sway-core/src/type_engine/type_argument.rs diff --git a/sway-core/src/type_engine/type_info.rs b/sway-core/src/type_engine/type_info.rs index 229da791d79..814de264ff7 100644 --- a/sway-core/src/type_engine/type_info.rs +++ b/sway-core/src/type_engine/type_info.rs @@ -1,6 +1,6 @@ use super::*; -use crate::{semantic_analysis::*, types::*, CallPath, Ident, TypeArgument, TypeParameter}; +use crate::{semantic_analysis::*, types::*, CallPath, Ident}; use sway_types::{span::Span, Spanned}; @@ -863,6 +863,169 @@ impl TypeInfo { ok(generics, warnings, errors) } + /// Given two `TypeInfo`'s `self` and `other`, check to see if `self` is + /// unidirectionally a subset of `other`. + /// + /// `self` is a subset of `other` if it can be generalized over `other`. + /// For example, the generic `T` is a subset of the generic `F` because + /// anything of the type `T` could also be of the type `F` (minus any + /// external context that may make this statement untrue). + /// + /// Given: + /// + /// ```ignore + /// struct Data { + /// x: T, + /// y: F, + /// } + /// ``` + /// + /// the type `Data` is a subset of any generic type. + /// + /// Given: + /// + /// ```ignore + /// struct Data { + /// x: T, + /// y: F, + /// } + /// + /// impl Data { } + /// ``` + /// + /// the type `Data` is a subset of `Data`, but _`Data` is + /// not a subset of `Data`_. + /// + /// Given: + /// + /// ```ignore + /// struct Data { + /// x: T, + /// y: F, + /// } + /// + /// impl Data { } + /// + /// fn dummy() { + /// // the type of foo is Data + /// let foo = Data { + /// x: true, + /// y: 1u64 + /// }; + /// // the type of bar is Data + /// let bar = Data { + /// x: 0u8, + /// y: 0u8 + /// }; + /// } + /// ``` + /// + /// | type: | is subset of: | is not a subset of: | + /// |-------------------|----------------------------------------------|---------------------| + /// | `Data` | `Data`, any generic type | | + /// | `Data` | any generic type | `Data` | + /// | `Data` | `Data`, any generic type | `Data` | + /// | `Data` | `Data`, `Data`, any generic type | | + /// + pub(crate) fn is_subset_of(&self, other: &TypeInfo) -> bool { + match (self, other) { + // any type is the subset of a generic + (_, Self::UnknownGeneric { .. }) => true, + (Self::Ref(l, _), Self::Ref(r, _)) => { + look_up_type_id(*l).is_subset_of(&look_up_type_id(*r)) + } + (Self::Array(l0, l1), Self::Array(r0, r1)) => { + look_up_type_id(*l0).is_subset_of(&look_up_type_id(*r0)) && l1 == r1 + } + ( + Self::Custom { + name: l_name, + type_arguments: l_type_args, + }, + Self::Custom { + name: r_name, + type_arguments: r_type_args, + }, + ) => { + let l_types = l_type_args + .iter() + .map(|x| look_up_type_id(x.type_id)) + .collect::>(); + let r_types = r_type_args + .iter() + .map(|x| look_up_type_id(x.type_id)) + .collect::>(); + l_name == r_name && types_are_subset_of(&l_types, &r_types) + } + ( + Self::Enum { + name: l_name, + variant_types: l_variant_types, + type_parameters: l_type_parameters, + }, + Self::Enum { + name: r_name, + variant_types: r_variant_types, + type_parameters: r_type_parameters, + }, + ) => { + let l_names = l_variant_types + .iter() + .map(|x| x.name.clone()) + .collect::>(); + let r_names = r_variant_types + .iter() + .map(|x| x.name.clone()) + .collect::>(); + let l_types = l_type_parameters + .iter() + .map(|x| look_up_type_id(x.type_id)) + .collect::>(); + let r_types = r_type_parameters + .iter() + .map(|x| look_up_type_id(x.type_id)) + .collect::>(); + l_name == r_name && l_names == r_names && types_are_subset_of(&l_types, &r_types) + } + ( + Self::Struct { + name: l_name, + fields: l_fields, + type_parameters: l_type_parameters, + }, + Self::Struct { + name: r_name, + fields: r_fields, + type_parameters: r_type_parameters, + }, + ) => { + let l_names = l_fields.iter().map(|x| x.name.clone()).collect::>(); + let r_names = r_fields.iter().map(|x| x.name.clone()).collect::>(); + let l_types = l_type_parameters + .iter() + .map(|x| look_up_type_id(x.type_id)) + .collect::>(); + let r_types = r_type_parameters + .iter() + .map(|x| look_up_type_id(x.type_id)) + .collect::>(); + l_name == r_name && l_names == r_names && types_are_subset_of(&l_types, &r_types) + } + (Self::Tuple(l_types), Self::Tuple(r_types)) => { + let l_types = l_types + .iter() + .map(|x| look_up_type_id(x.type_id)) + .collect::>(); + let r_types = r_types + .iter() + .map(|x| look_up_type_id(x.type_id)) + .collect::>(); + types_are_subset_of(&l_types, &r_types) + } + (a, b) => a == b, + } + } + /// Given a `TypeInfo` `self` and a list of `Ident`'s `subfields`, /// iterate through the elements of `subfields` as `subfield`, /// and recursively apply `subfield` to `self`. @@ -982,6 +1145,113 @@ impl TypeInfo { } } +/// Given two lists of `TypeInfo`'s `left` and `right`, check to see if +/// `left` is a subset of `right`. +/// +/// `left` is a subset of `right` if the following invariants are true: +/// 1. `left` and and `right` are of the same length _n_ +/// 2. For every _i_ in [0, n), `left`áµ¢ is a subset of `right`áµ¢ +/// 3. The elements of `left` satisfy the trait constraints of `right` +/// +/// A property that falls of out these constraints are that if `left` and +/// `right` are empty, then `left` is a subset of `right`. +/// +/// Given: +/// +/// ```ignore +/// left: [T] +/// right: [T, F] +/// ``` +/// +/// `left` is not a subset of `right` because it violates invariant #1. +/// +/// Given: +/// +/// ```ignore +/// left: [T, F] +/// right: [bool, F] +/// ``` +/// +/// `left` is not a subset of `right` because it violates invariant #2. +/// +/// Given: +/// +/// ```ignore +/// left: [T, F] +/// right: [T, T] +/// ``` +/// +/// `left` is not a subset of `right` because it violates invariant #3. +/// +/// Given: +/// +/// ```ignore +/// left: [T, T] +/// right: [T, F] +/// ``` +/// +/// `left` is a subset of `right`. +/// +/// Given: +/// +/// ```ignore +/// left: [bool, T] +/// right: [T, F] +/// ``` +/// +/// `left` is a subset of `right`. +/// +/// Given: +/// +/// ```ignore +/// left: [Data, Data] +/// right: [Data, Data] +/// ``` +/// +/// `left` is a subset of `right`. +/// +fn types_are_subset_of(left: &[TypeInfo], right: &[TypeInfo]) -> bool { + // invariant 1. `left` and and `right` are of the same length _n_ + if left.len() != right.len() { + return false; + } + + // if `left` and `right` are empty, `left` is inherently a subset of `right` + if left.is_empty() && right.is_empty() { + return true; + } + + // invariant 2. For every _i_ in [0, n), `left`áµ¢ is a subset of `right`áµ¢ + for (l, r) in left.iter().zip(right.iter()) { + if !l.is_subset_of(r) { + return false; + } + } + + // invariant 3. The elements of `left` satisfy the trait constraints of `right` + let mut constraints = vec![]; + for i in 0..(right.len() - 1) { + for j in (i + 1)..right.len() { + let a = right.get(i).unwrap(); + let b = right.get(j).unwrap(); + if a == b { + // if a and b are the same type + constraints.push((i, j)); + } + } + } + for (i, j) in constraints.into_iter() { + let a = left.get(i).unwrap(); + let b = left.get(j).unwrap(); + if a != b { + return false; + } + } + + // if all of the invariants are met, then `self` is a subset of `other`! + true +} + fn print_inner_types(name: String, inner_types: impl Iterator) -> String { let inner_types = inner_types.map(|x| x.to_string()).collect::>(); format!( diff --git a/sway-core/src/type_engine/type_mapping.rs b/sway-core/src/type_engine/type_mapping.rs index 8335676addc..bb83531fcc6 100644 --- a/sway-core/src/type_engine/type_mapping.rs +++ b/sway-core/src/type_engine/type_mapping.rs @@ -1,5 +1,3 @@ -use crate::TypeParameter; - use super::*; pub(crate) type TypeMapping = Vec<(TypeId, TypeId)>; @@ -17,3 +15,111 @@ pub(crate) fn insert_type_parameters(type_parameters: &[TypeParameter]) -> TypeM }) .collect() } + +pub(crate) fn create_type_mapping(superset_type: TypeId, subset_type: TypeId) -> TypeMapping { + match (look_up_type_id(superset_type), look_up_type_id(subset_type)) { + (TypeInfo::Ref(superset_type, _), TypeInfo::Ref(subset_type, _)) => { + create_type_mapping(superset_type, subset_type) + } + (TypeInfo::Ref(superset_type, _), _) => create_type_mapping(superset_type, subset_type), + (_, TypeInfo::Ref(subset_type, _)) => create_type_mapping(superset_type, subset_type), + (TypeInfo::UnknownGeneric { .. }, _) => { + vec![(superset_type, subset_type)] + } + ( + TypeInfo::Custom { + type_arguments: type_parameters, + .. + }, + TypeInfo::Custom { type_arguments, .. }, + ) => { + let type_parameters = type_parameters + .iter() + .map(|x| x.type_id) + .collect::>(); + let type_arguments = type_arguments.iter().map(|x| x.type_id).collect::>(); + insert_type_parameters_with_type_arguments(type_parameters, type_arguments) + } + ( + TypeInfo::Enum { + type_parameters, .. + }, + TypeInfo::Enum { + type_parameters: type_arguments, + .. + }, + ) => { + let type_parameters = type_parameters + .iter() + .map(|x| x.type_id) + .collect::>(); + let type_arguments = type_arguments.iter().map(|x| x.type_id).collect::>(); + insert_type_parameters_with_type_arguments(type_parameters, type_arguments) + } + ( + TypeInfo::Struct { + type_parameters, .. + }, + TypeInfo::Struct { + type_parameters: type_arguments, + .. + }, + ) => { + let type_parameters = type_parameters + .iter() + .map(|x| x.type_id) + .collect::>(); + let type_arguments = type_arguments.iter().map(|x| x.type_id).collect::>(); + insert_type_parameters_with_type_arguments(type_parameters, type_arguments) + } + (TypeInfo::Tuple(type_parameters), TypeInfo::Tuple(type_arguments)) => { + insert_type_parameters_with_type_arguments( + type_parameters + .iter() + .map(|x| x.type_id) + .collect::>(), + type_arguments.iter().map(|x| x.type_id).collect::>(), + ) + } + (TypeInfo::Array(superset_type, _), TypeInfo::Array(subset_type, _)) => { + vec![(superset_type, subset_type)] + } + ( + TypeInfo::Storage { + fields: type_parameters, + }, + TypeInfo::Storage { + fields: type_arguments, + }, + ) => { + let type_parameters = type_parameters + .iter() + .map(|x| x.type_id) + .collect::>(); + let type_arguments = type_arguments.iter().map(|x| x.type_id).collect::>(); + insert_type_parameters_with_type_arguments(type_parameters, type_arguments) + } + (TypeInfo::Unknown, TypeInfo::Unknown) + | (TypeInfo::Boolean, TypeInfo::Boolean) + | (TypeInfo::SelfType, TypeInfo::SelfType) + | (TypeInfo::Byte, TypeInfo::Byte) + | (TypeInfo::B256, TypeInfo::B256) + | (TypeInfo::Numeric, TypeInfo::Numeric) + | (TypeInfo::Contract, TypeInfo::Contract) + | (TypeInfo::ErrorRecovery, TypeInfo::ErrorRecovery) + | (TypeInfo::Str(_), TypeInfo::Str(_)) + | (TypeInfo::UnsignedInteger(_), TypeInfo::UnsignedInteger(_)) + | (TypeInfo::ContractCaller { .. }, TypeInfo::ContractCaller { .. }) => vec![], + _ => vec![], + } +} + +fn insert_type_parameters_with_type_arguments( + type_parameters: Vec, + type_arguments: Vec, +) -> TypeMapping { + type_parameters + .into_iter() + .zip(type_arguments.into_iter()) + .collect::>() +} diff --git a/sway-core/src/parse_tree/declaration/type_parameter.rs b/sway-core/src/type_engine/type_parameter.rs similarity index 88% rename from sway-core/src/parse_tree/declaration/type_parameter.rs rename to sway-core/src/type_engine/type_parameter.rs index bdacbd14548..f4899a796b7 100644 --- a/sway-core/src/parse_tree/declaration/type_parameter.rs +++ b/sway-core/src/type_engine/type_parameter.rs @@ -1,8 +1,11 @@ -use crate::{error::*, parse_tree::*, semantic_analysis::*, type_engine::*}; +use crate::{error::*, semantic_analysis::*, type_engine::*}; use sway_types::{ident::Ident, span::Span, Spanned}; -use std::hash::{Hash, Hasher}; +use std::{ + fmt, + hash::{Hash, Hasher}, +}; #[derive(Debug, Clone, Eq)] pub struct TypeParameter { @@ -57,11 +60,17 @@ impl ReplaceSelfType for TypeParameter { } } +impl fmt::Display for TypeParameter { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}: {}", self.name_ident, self.type_id) + } +} + impl TypeParameter { pub(crate) fn type_check( + ctx: TypeCheckContext, type_parameter: TypeParameter, - namespace: &mut Namespace, - ) -> CompileResult { + ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; if !type_parameter.trait_constraints.is_empty() { @@ -78,7 +87,7 @@ impl TypeParameter { name: type_parameter.name_ident.clone(), type_id, }; - namespace + ctx.namespace .insert_symbol(type_parameter.name_ident.clone(), type_parameter_decl) .ok(&mut warnings, &mut errors); let type_parameter = TypeParameter { @@ -89,8 +98,3 @@ impl TypeParameter { ok(type_parameter, warnings, errors) } } - -#[derive(Debug, Clone, Eq, PartialEq, Hash)] -pub(crate) struct TraitConstraint { - pub(crate) call_path: CallPath, -} diff --git a/sway-core/tests/sway_to_ir/eq_intrinsic.ir b/sway-core/tests/sway_to_ir/eq_intrinsic.ir new file mode 100644 index 00000000000..119bcf76de2 --- /dev/null +++ b/sway-core/tests/sway_to_ir/eq_intrinsic.ir @@ -0,0 +1,21 @@ +script { + fn main() -> bool, !1 { + local ptr bool _ + + entry: + v0 = const u64 1, !2 + v1 = const u64 2, !3 + v2 = cmp eq v0 v1 + v3 = get_ptr ptr bool _, ptr bool, 0, !4 + store v2, ptr v3, !4 + v4 = const bool true, !5 + ret bool v4 + } +} + +!0 = filepath "/path/to/eq_intrinsic.sw" +!1 = span !0 9 59 +!2 = span !0 44 45 +!3 = span !0 47 48 +!4 = span !0 31 50 +!5 = span !0 53 57 diff --git a/sway-core/tests/sway_to_ir/eq_intrinsic.sw b/sway-core/tests/sway_to_ir/eq_intrinsic.sw new file mode 100644 index 00000000000..d32660611f4 --- /dev/null +++ b/sway-core/tests/sway_to_ir/eq_intrinsic.sw @@ -0,0 +1,6 @@ +script; + +fn main() -> bool { + let _ = __eq(1, 2); + true +} diff --git a/sway-core/tests/sway_to_ir/local_const_init.ir b/sway-core/tests/sway_to_ir/local_const_init.ir new file mode 100644 index 00000000000..c610e0b6608 --- /dev/null +++ b/sway-core/tests/sway_to_ir/local_const_init.ir @@ -0,0 +1,20 @@ +script { + fn main() -> u64, !1 { + local ptr { u64 } X + + entry: + v0 = get_ptr ptr { u64 } X, ptr { u64 }, 0, !2 + v1 = const { u64 } { u64 1 }, !3 + store v1, ptr v0, !2 + v2 = get_ptr ptr { u64 } X, ptr { u64 }, 0, !4 + v3 = extract_value v2, { u64 }, 0, !5 + ret u64 v3 + } +} + +!0 = filepath "/path/to/local_const_init.sw" +!1 = span !0 70 114 +!2 = span !0 91 106 +!3 = span !0 33 68 +!4 = span !0 109 110 +!5 = span !0 22 29 diff --git a/sway-core/tests/sway_to_ir/local_const_init.sw b/sway-core/tests/sway_to_ir/local_const_init.sw new file mode 100644 index 00000000000..cb05b34bea7 --- /dev/null +++ b/sway-core/tests/sway_to_ir/local_const_init.sw @@ -0,0 +1,14 @@ +script; + +struct S { + s : u64 +} + +fn s(x : u64) -> S { + S { s: x } +} + +fn main() -> u64 { + const X = s(1); + X.s +} diff --git a/sway-fmt-v2/Cargo.toml b/sway-fmt-v2/Cargo.toml index eb8accb7da7..7c82823560a 100644 --- a/sway-fmt-v2/Cargo.toml +++ b/sway-fmt-v2/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sway-fmt-v2" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -11,11 +11,11 @@ description = "Sway sway-fmt-v2." [dependencies] anyhow = "1" -forc-util = { version = "0.16.1", path = "../forc-util" } +forc-util = { version = "0.16.2", path = "../forc-util" } serde = { version = "1.0", features = ["derive"] } serde_ignored = "0.1" -sway-core = { version = "0.16.1", path = "../sway-core" } -sway-parse = { version = "0.16.1", path = "../sway-parse" } -sway-types = { version = "0.16.1", path = "../sway-types" } +sway-core = { version = "0.16.2", path = "../sway-core" } +sway-parse = { version = "0.16.2", path = "../sway-parse" } +sway-types = { version = "0.16.2", path = "../sway-types" } thiserror = "1.0.30" toml = "0.5" diff --git a/sway-fmt-v2/src/config/heuristics.rs b/sway-fmt-v2/src/config/heuristics.rs index f145504c987..3760424481b 100644 --- a/sway-fmt-v2/src/config/heuristics.rs +++ b/sway-fmt-v2/src/config/heuristics.rs @@ -69,12 +69,12 @@ pub struct WidthHeuristics { // Maximum width of the args of a function-like attributes before falling // back to vertical formatting. pub(crate) attr_fn_like_width: usize, - // Maximum width in the body of a struct lit before falling back to + // Maximum width in the body of a user-defined structure literal before falling back to // vertical formatting. - pub(crate) struct_lit_width: usize, - // Maximum width in the body of a struct variant before falling back + pub(crate) structure_lit_width: usize, + // Maximum width in the body of a user-defined structure field before falling back // to vertical formatting. - pub(crate) struct_variant_width: usize, + pub(crate) structure_field_width: usize, // Maximum width of an array literal before falling back to vertical // formatting. pub(crate) array_width: usize, @@ -97,8 +97,8 @@ impl WidthHeuristics { WidthHeuristics { fn_call_width: usize::max_value(), attr_fn_like_width: usize::max_value(), - struct_lit_width: 0, - struct_variant_width: 0, + structure_lit_width: 0, + structure_field_width: 0, array_width: usize::max_value(), chain_width: usize::max_value(), single_line_if_else_max_width: 0, @@ -109,8 +109,8 @@ impl WidthHeuristics { WidthHeuristics { fn_call_width: max_width, attr_fn_like_width: max_width, - struct_lit_width: max_width, - struct_variant_width: max_width, + structure_lit_width: max_width, + structure_field_width: max_width, array_width: max_width, chain_width: max_width, single_line_if_else_max_width: max_width, @@ -131,8 +131,9 @@ impl WidthHeuristics { fn_call_width: (DEFAULT_FN_CALL_WIDTH as f32 * max_width_ratio).round() as usize, attr_fn_like_width: (DEFAULT_ATTR_FN_LIKE_WIDTH as f32 * max_width_ratio).round() as usize, - struct_lit_width: (DEFAULT_STRUCT_LIT_WIDTH as f32 * max_width_ratio).round() as usize, - struct_variant_width: (DEFAULT_STRUCT_VAR_WIDTH as f32 * max_width_ratio).round() + structure_lit_width: (DEFAULT_STRUCT_LIT_WIDTH as f32 * max_width_ratio).round() + as usize, + structure_field_width: (DEFAULT_STRUCT_VAR_WIDTH as f32 * max_width_ratio).round() as usize, array_width: (DEFAULT_ARRAY_WIDTH as f32 * max_width_ratio).round() as usize, chain_width: (DEFAULT_CHAIN_WIDTH as f32 * max_width_ratio).round() as usize, diff --git a/sway-fmt-v2/src/config/user_def.rs b/sway-fmt-v2/src/config/user_def.rs index b107ca9e3ba..66e698b2120 100644 --- a/sway-fmt-v2/src/config/user_def.rs +++ b/sway-fmt-v2/src/config/user_def.rs @@ -1,28 +1,23 @@ //! Configuration options related to formatting user-defined structures. -use crate::constants::{ - DEFAULT_ENUM_VARIANT_ALIGN_THRESHOLD, DEFAULT_STRUCT_FIELD_ALIGN_THRESHOLD, -}; +use serde::{Deserialize, Serialize}; use super::user_opts::StructuresOptions; /// Styling preferences for user-defined structures like `struct`s or `enum`s. #[derive(Debug)] pub struct Structures { - /// Align enum variants discrims, if their diffs fit within threshold. - pub enum_variant_align_threshold: usize, - /// Align struct fields if their diffs fits within threshold. - pub struct_field_align_threshold: usize, - /// Put small struct literals on a single line. - pub struct_lit_single_line: bool, + /// Align fields of user-defined structures if their diffs fit within threshold. + pub field_alignment: FieldAlignment, + /// Put small user-defined structure literals on a single line. + pub small_structures_single_line: bool, } impl Default for Structures { fn default() -> Self { Self { - enum_variant_align_threshold: DEFAULT_ENUM_VARIANT_ALIGN_THRESHOLD, - struct_field_align_threshold: DEFAULT_STRUCT_FIELD_ALIGN_THRESHOLD, - struct_lit_single_line: true, + field_alignment: FieldAlignment::Off, + small_structures_single_line: true, } } } @@ -31,15 +26,17 @@ impl Structures { pub fn from_opts(opts: &StructuresOptions) -> Self { let default = Self::default(); Self { - enum_variant_align_threshold: opts - .enum_variant_align_threshold - .unwrap_or(default.enum_variant_align_threshold), - struct_field_align_threshold: opts - .struct_field_align_threshold - .unwrap_or(default.struct_field_align_threshold), - struct_lit_single_line: opts + field_alignment: opts.field_alignment.unwrap_or(default.field_alignment), + small_structures_single_line: opts .struct_lit_single_line - .unwrap_or(default.struct_lit_single_line), + .unwrap_or(default.small_structures_single_line), } } } + +/// Align fields if they fit within a provided threshold. +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +pub enum FieldAlignment { + AlignFields(usize), + Off, +} diff --git a/sway-fmt-v2/src/config/user_opts.rs b/sway-fmt-v2/src/config/user_opts.rs index bbb9ffb9141..c0c03bdb221 100644 --- a/sway-fmt-v2/src/config/user_opts.rs +++ b/sway-fmt-v2/src/config/user_opts.rs @@ -8,6 +8,7 @@ use super::{ items::{ItemBraceStyle, ItemsLayout}, lists::{ListTactic, SeparatorTactic}, literals::HexLiteralCase, + user_def::FieldAlignment, whitespace::{IndentStyle, NewlineStyle}, }; /// See parent struct [Whitespace]. @@ -77,8 +78,7 @@ pub struct HeuristicsOptions { /// See parent struct [Structures]. #[derive(Serialize, Deserialize, Debug, Copy, Clone)] pub struct StructuresOptions { - pub enum_variant_align_threshold: Option, - pub struct_field_align_threshold: Option, + pub field_alignment: Option, pub struct_lit_single_line: Option, } /// See parent struct [Comments]. diff --git a/sway-fmt-v2/src/constants.rs b/sway-fmt-v2/src/constants.rs index c4c7d76e1bc..f95b30dec73 100644 --- a/sway-fmt-v2/src/constants.rs +++ b/sway-fmt-v2/src/constants.rs @@ -36,13 +36,6 @@ pub const DEFAULT_BLANK_LINES_LOWER_BOUND: usize = 0; /// Write an items and its attribute on the same line if their combined width is below a threshold. pub const DEFAULT_INLINE_ATTR_WIDTH: usize = 0; -/////USER_DEFINED_STRUCTURES///// - -/// Default max threshold for aligning struct fields. -pub const DEFAULT_STRUCT_FIELD_ALIGN_THRESHOLD: usize = 0; -/// Default max threshold for aligning enum variants. -pub const DEFAULT_ENUM_VARIANT_ALIGN_THRESHOLD: usize = 0; - /////COMMENTS///// /// Default max length of comments. diff --git a/sway-fmt-v2/src/error.rs b/sway-fmt-v2/src/error.rs index fda03500a60..d1b021c871b 100644 --- a/sway-fmt-v2/src/error.rs +++ b/sway-fmt-v2/src/error.rs @@ -5,6 +5,8 @@ use thiserror::Error; pub enum FormatterError { #[error("Error parsing file: {0}")] ParseFileError(#[from] sway_parse::ParseFileError), + #[error("Error formatting a message into a stream: {0}")] + FormatError(#[from] std::fmt::Error), } #[derive(Debug, Error)] diff --git a/sway-fmt-v2/src/fmt.rs b/sway-fmt-v2/src/fmt.rs index 1282c9a0e07..9636cf46dc5 100644 --- a/sway-fmt-v2/src/fmt.rs +++ b/sway-fmt-v2/src/fmt.rs @@ -1,9 +1,8 @@ use crate::utils::{ - attributes::format_attributes, indent_style::Shape, newline_style::apply_newline_style, + indent_style::Shape, newline_style::apply_newline_style, program_type::insert_program_type, }; use std::{path::Path, sync::Arc}; use sway_core::BuildConfig; -use sway_parse::ItemKind; pub use crate::{ config::manifest::Config, @@ -19,7 +18,11 @@ pub struct Formatter { pub type FormattedCode = String; pub trait Format { - fn format(&self, formatter: &mut Formatter) -> FormattedCode; + fn format( + &self, + formatted_code: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError>; } impl Formatter { @@ -38,34 +41,38 @@ impl Formatter { build_config: Option<&BuildConfig>, ) -> Result { let path = build_config.map(|build_config| build_config.canonical_root_module()); - let items = sway_parse::parse_file(src, path)?.items; - let formatted_raw_newline = items - .into_iter() - .map(|item| -> Result { - use ItemKind::*; - // format attributes first, then add corresponding item - let mut buf = format_attributes(item.attribute_list, self); - buf.push_str(&match item.value { - Use(item_use) => item_use.format(self), - Struct(item_struct) => item_struct.format(self), - Enum(item_enum) => item_enum.format(self), - Fn(item_fn) => item_fn.format(self), - Trait(item_trait) => item_trait.format(self), - Impl(item_impl) => item_impl.format(self), - Abi(item_abi) => item_abi.format(self), - Const(item_const) => item_const.format(self), - Storage(item_storage) => item_storage.format(self), - }); - Ok(buf) - }) - .collect::, _>>()? - .join("\n"); - let mut formatted_code = String::from(&formatted_raw_newline); + let src_len = src.len(); + let module = sway_parse::parse_file(src, path)?; + // Get parsed items + let items = module.items; + // Get the program type (script, predicate, contract or library) + let program_type = module.kind; + + // Formatted code will be pushed here with raw newline stlye. + // Which means newlines are not converted into system-specific versions by `apply_newline_style`. + // Use the length of src as a hint of the memory size needed for `raw_formatted_code`, + // which will reduce the number of reallocations + let mut raw_formatted_code = String::with_capacity(src_len); + + // Insert program type to the formatted code. + insert_program_type(&mut raw_formatted_code, program_type); + + // Insert parsed & formatted items into the formatted code. + let mut iter = items.iter().peekable(); + while let Some(item) = iter.next() { + // format Annotated + item.format(&mut raw_formatted_code, self)?; + if iter.peek().is_some() { + raw_formatted_code.push('\n'); + } + } + + let mut formatted_code = String::from(&raw_formatted_code); apply_newline_style( // The user's setting for `NewlineStyle` self.config.whitespace.newline_style, &mut formatted_code, - &formatted_raw_newline, + &raw_formatted_code, ); Ok(formatted_code) } @@ -73,15 +80,106 @@ impl Formatter { #[cfg(test)] mod tests { - use crate::utils::indent_style::Shape; - use std::sync::Arc; - use super::{Config, Formatter}; + use crate::{config::user_def::FieldAlignment, utils::indent_style::Shape}; + use std::sync::Arc; fn get_formatter(config: Config, shape: Shape) -> Formatter { Formatter { config, shape } } + #[test] + fn test_const() { + let sway_code_to_format = r#"contract; +pub const TEST:u16=10;"#; + let correct_sway_code = r#"contract; + +pub const TEST: u16 = 10;"#; + let mut formatter = Formatter::default(); + let formatted_sway_code = + Formatter::format(&mut formatter, Arc::from(sway_code_to_format), None).unwrap(); + assert!(correct_sway_code == formatted_sway_code) + } + + #[test] + fn test_struct_multiline_line_alignment() { + let sway_code_to_format = r#"contract; +pub struct Foo { + barbazfoo: u64, + baz : bool, +} +"#; + let correct_sway_code = r#"contract; + +pub struct Foo { + barbazfoo : u64, + baz : bool, +}"#; + let mut config = Config::default(); + config.structures.field_alignment = FieldAlignment::AlignFields(40); + let mut formatter = get_formatter(config, Shape::default()); + let formatted_sway_code = + Formatter::format(&mut formatter, Arc::from(sway_code_to_format), None).unwrap(); + assert!(correct_sway_code == formatted_sway_code) + } + #[test] + fn test_struct_single_line() { + let sway_code_to_format = r#"contract; +pub struct Foo { + bar: u64, + baz: bool, +} +"#; + let correct_sway_code = r#"contract; + +pub struct Foo { bar: u64, baz: bool }"#; + let mut config = Config::default(); + config.structures.small_structures_single_line = true; + config.whitespace.max_width = 300; + let mut formatter = get_formatter(config, Shape::default()); + let formatted_sway_code = + Formatter::format(&mut formatter, Arc::from(sway_code_to_format), None).unwrap(); + assert!(correct_sway_code == formatted_sway_code) + } + #[test] + fn test_enum_single_line() { + let sway_code_to_format = r#"contract; +pub enum Foo { + bar: u64, + baz: bool, +} +"#; + let correct_sway_code = r#"contract; + +pub enum Foo { bar: u64, baz: bool }"#; + let mut config = Config::default(); + config.structures.small_structures_single_line = true; + config.whitespace.max_width = 300; + let mut formatter = get_formatter(config, Shape::default()); + let formatted_sway_code = + Formatter::format(&mut formatter, Arc::from(sway_code_to_format), None).unwrap(); + assert!(correct_sway_code == formatted_sway_code) + } + #[test] + fn test_struct_multi_line() { + let sway_code_to_format = r#"contract; +pub struct Foo { + bar: u64, + baz: bool +} +"#; + let correct_sway_code = r#"contract; + +pub struct Foo { + bar: u64, + baz: bool, +}"#; + let mut formatter = Formatter::default(); + let formatted_sway_code = + Formatter::format(&mut formatter, Arc::from(sway_code_to_format), None).unwrap(); + assert!(correct_sway_code == formatted_sway_code) + } + #[test] fn test_enum_without_variant_alignment() { let sway_code_to_format = r#"contract; @@ -90,18 +188,18 @@ enum Color { Blue: (), Green: (), Red: (), Silver: (), - Grey: (), } + Grey: () } "#; + let correct_sway_code = r#"contract; - // Until #1995 is addressed we will not have contract; in the output - let correct_sway_code = r#"enum Color { - Blue : (), - Green : (), - Red : (), - Silver : (), - Grey : (), +enum Color { + Blue: (), + Green: (), + Red: (), + Silver: (), + Grey: (), }"#; - let mut formatter = get_formatter(Config::default(), Shape::default()); + let mut formatter = Formatter::default(); let formatted_sway_code = Formatter::format(&mut formatter, Arc::from(sway_code_to_format), None).unwrap(); assert!(correct_sway_code == formatted_sway_code) @@ -116,21 +214,59 @@ enum Color { Silver: (), Grey: (), } "#; + let correct_sway_code = r#"contract; - // Until #1995 is addressed we will not have contract; in the output - let correct_sway_code = r#"enum Color { - Blue : (), - Green : (), - Red : (), - Silver : (), - Grey : (), +enum Color { + Blue : (), + Green : (), + Red : (), + Silver : (), + Grey : (), }"#; // Creating a config with enum_variant_align_threshold that exceeds longest variant length - let mut config = Config::default(); - config.structures.enum_variant_align_threshold = 20; + let mut formatter = Formatter::default(); + formatter.config.structures.field_alignment = FieldAlignment::AlignFields(20); - let mut formatter = get_formatter(config, Shape::default()); + let formatted_sway_code = + Formatter::format(&mut formatter, Arc::from(sway_code_to_format), None).unwrap(); + assert!(correct_sway_code == formatted_sway_code) + } + #[test] + fn test_item_abi_with_generics_and_attributes() { + let sway_code_to_format = r#"contract; + +abi StorageMapExample { + #[storage(write)]fn insert_into_map1(key: u64, value: u64); + +fn hello(key: u64, value: u64); +}"#; + let correct_sway_code = r#"contract; + +abi StorageMapExample { + #[storage(write)] + fn insert_into_map1(key: u64, value: u64); + + fn hello(key: u64, value: u64); +}"#; + let mut formatter = Formatter::default(); + let formatted_sway_code = + Formatter::format(&mut formatter, Arc::from(sway_code_to_format), None).unwrap(); + assert!(correct_sway_code == formatted_sway_code) + } + + #[test] + fn test_multi_items() { + let sway_code_to_format = r#"contract; + +pub const TEST: u16 = 10; +pub const TEST1: u16 = 10;"#; + let correct_sway_code = r#"contract; + +pub const TEST: u16 = 10; +pub const TEST1: u16 = 10;"#; + + let mut formatter = Formatter::default(); let formatted_sway_code = Formatter::format(&mut formatter, Arc::from(sway_code_to_format), None).unwrap(); assert!(correct_sway_code == formatted_sway_code) diff --git a/sway-fmt-v2/src/items/item_abi.rs b/sway-fmt-v2/src/items/item_abi.rs index 9699f370074..c634a1591bd 100644 --- a/sway-fmt-v2/src/items/item_abi.rs +++ b/sway-fmt-v2/src/items/item_abi.rs @@ -1,8 +1,114 @@ -use crate::fmt::{Format, FormattedCode, Formatter}; -use sway_parse::ItemAbi; +use crate::{ + config::items::ItemBraceStyle, + fmt::{Format, FormattedCode, Formatter}, + utils::{attribute::FormatDecl, bracket::CurlyBrace}, + FormatterError, +}; +use std::fmt::Write; +use sway_parse::{token::Delimiter, ItemAbi}; +use sway_types::Spanned; impl Format for ItemAbi { - fn format(&self, _formatter: &mut Formatter) -> FormattedCode { - todo!() + fn format( + &self, + formatted_code: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + // Add enum token + write!(formatted_code, "{} ", self.abi_token.span().as_str())?; + + // Add name of the abi + formatted_code.push_str(self.name.as_str()); + Self::open_curly_brace(formatted_code, formatter)?; + + // Add item fields + // abi_items + let mut abi_items_iter = self.abi_items.get().iter().peekable(); + while let Some(item) = abi_items_iter.next() { + let attribute_list = item.0.attribute_list.clone(); + // add indent + format attribute if it exists + if !attribute_list.is_empty() { + formatted_code.push_str(&formatter.shape.indent.to_string(formatter)); + for attr in attribute_list { + attr.format(formatted_code, formatter)?; + } + } + // add indent + format item + formatted_code.push_str(&formatter.shape.indent.to_string(formatter)); + writeln!( + formatted_code, + "{}{}", + item.0.value.span().as_str(), // FnSignature formatting (todo!) + item.1.span().as_str() // SemicolonToken + )?; + + if abi_items_iter.peek().is_some() { + formatted_code.push('\n'); + } + } + + // abi_defs_opt + if let Some(abi_defs) = self.abi_defs_opt.clone() { + let mut iter = abi_defs.get().iter().peekable(); + while let Some(item) = iter.next() { + let attribute_list = item.attribute_list.clone(); + // add indent + format attribute if it exists + if !attribute_list.is_empty() { + formatted_code.push_str(&formatter.shape.indent.to_string(formatter)); + for attr in attribute_list { + attr.format(formatted_code, formatter)?; + } + } + + // add indent + format item + formatted_code.push_str(&formatter.shape.indent.to_string(formatter)); + item.value.format(formatted_code, formatter)?; // ItemFn formatting (todo!) + if iter.peek().is_some() { + formatted_code.push('\n'); + } + } + } + Self::close_curly_brace(formatted_code, formatter)?; + + Ok(()) + } +} + +impl CurlyBrace for ItemAbi { + fn open_curly_brace( + line: &mut String, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + let brace_style = formatter.config.items.item_brace_style; + let extra_width = formatter.config.whitespace.tab_spaces; + let mut shape = formatter.shape; + let open_brace = Delimiter::Brace.as_open_char(); + match brace_style { + ItemBraceStyle::AlwaysNextLine => { + // Add openning brace to the next line. + write!(line, "\n{}\n", open_brace)?; + shape = shape.block_indent(extra_width); + } + _ => { + // Add opening brace to the same line + writeln!(line, " {}", open_brace)?; + shape = shape.block_indent(extra_width); + } + } + + formatter.shape = shape; + Ok(()) + } + fn close_curly_brace( + line: &mut String, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + line.push(Delimiter::Brace.as_close_char()); + // If shape is becoming left-most alligned or - indent just have the defualt shape + formatter.shape = formatter + .shape + .shrink_left(formatter.config.whitespace.tab_spaces) + .unwrap_or_default(); + Ok(()) } } diff --git a/sway-fmt-v2/src/items/item_const.rs b/sway-fmt-v2/src/items/item_const.rs index c4a2810c489..315c85a61b5 100644 --- a/sway-fmt-v2/src/items/item_const.rs +++ b/sway-fmt-v2/src/items/item_const.rs @@ -1,8 +1,47 @@ -use crate::fmt::{Format, FormattedCode, Formatter}; +use crate::{ + fmt::{Format, FormattedCode, Formatter}, + FormatterError, +}; use sway_parse::ItemConst; +use sway_types::Spanned; impl Format for ItemConst { - fn format(&self, _formatter: &mut Formatter) -> FormattedCode { - todo!() + fn format( + &self, + formatted_code: &mut FormattedCode, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + // Check if visibility token exists if so add it. + if let Some(visibility_token) = &self.visibility { + formatted_code.push_str(visibility_token.span().as_str()); + formatted_code.push(' '); + } + + // Add the const token + formatted_code.push_str(self.const_token.span().as_str()); + formatted_code.push(' '); + + // Add name of the const + formatted_code.push_str(self.name.as_str()); + + // Check if ty exists + if let Some(ty) = &self.ty_opt { + // Add colon + formatted_code.push_str(ty.0.span().as_str()); + // TODO: We are not applying any custom formatting to ty probably we will need to in the future. + // Add ty + formatted_code.push(' '); + formatted_code.push_str(ty.1.span().as_str()); + } + + formatted_code.push(' '); + // Add equal token + formatted_code.push_str(self.eq_token.ident().as_str()); + formatted_code.push(' '); + + // TODO: We are not applying any custom formatting to expr, probably we will need to in the future. + formatted_code.push_str(self.expr.span().as_str()); + formatted_code.push_str(self.semicolon_token.ident().as_str()); + Ok(()) } } diff --git a/sway-fmt-v2/src/items/item_enum.rs b/sway-fmt-v2/src/items/item_enum.rs index 1d431bac8fa..067ff58331e 100644 --- a/sway-fmt-v2/src/items/item_enum.rs +++ b/sway-fmt-v2/src/items/item_enum.rs @@ -1,104 +1,228 @@ use crate::{ - config::items::ItemBraceStyle, + config::{items::ItemBraceStyle, user_def::FieldAlignment}, fmt::{Format, FormattedCode, Formatter}, - utils::bracket::CurlyBrace, + utils::{bracket::CurlyBrace, item_len::ItemLen}, + FormatterError, +}; +use std::fmt::Write; +use sway_parse::{ + token::{Delimiter, PunctKind}, + ItemEnum, }; -use sway_parse::ItemEnum; use sway_types::Spanned; impl Format for ItemEnum { - fn format(&self, formatter: &mut Formatter) -> FormattedCode { - // TODO: creating this formatted_code with String::new() will likely cause lots of - // reallocations maybe we can explore how we can do this, starting with with_capacity may help. - let mut formatted_code = String::new(); - let enum_variant_align_threshold = formatter.config.structures.enum_variant_align_threshold; - - if let Some(visibility_token) = &self.visibility { - formatted_code.push_str(visibility_token.span().as_str()); - formatted_code.push(' '); - } + fn format( + &self, + formatted_code: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + // Bring configurations into scope. + // + // Should small enums formatted into a single line. + let enum_lit_single_line = formatter.config.structures.small_structures_single_line; - // Add enum token - formatted_code.push_str(self.enum_token.span().as_str()); - formatted_code.push(' '); + // Get the width limit of an enum to be formatted into single line if `enum_lit_single_line` is true. + let width_heuristics = formatter + .config + .heuristics + .heuristics_pref + .to_width_heuristics(&formatter.config.whitespace); + let enum_lit_width = width_heuristics.structure_lit_width; + + let multiline = !enum_lit_single_line || self.get_formatted_len() > enum_lit_width; + + format_enum(self, formatted_code, formatter, multiline)?; + Ok(()) + } +} + +/// Format the enum if the multiline is passed as false enum will be formatted into a single line. +/// +/// ##examples +/// +/// (multiline : false): +/// +/// ```rust,ignore +/// enum Foo { bar: u64, baz: bool } +/// ``` +/// +/// (multiline : true): +/// ```rust,ignore +/// enum Foo { +/// bar: u64, +/// baz: bool, +/// } +/// ``` +fn format_enum( + item_enum: &ItemEnum, + formatted_code: &mut FormattedCode, + formatter: &mut Formatter, + multiline: bool, +) -> Result<(), FormatterError> { + // If there is a visibility token add it to the formatted_code with a ` ` after it. + if let Some(visibility) = &item_enum.visibility { + write!(formatted_code, "{} ", visibility.span().as_str())?; + } + // Add enum token + write!(formatted_code, "{} ", item_enum.enum_token.span().as_str())?; + + // Add enum name + formatted_code.push_str(item_enum.name.as_str()); + + // Format `GenericParams`, if any + if let Some(generics) = &item_enum.generics { + generics.format(formatted_code, formatter)?; + } - // Add name of the enum. - formatted_code.push_str(self.name.as_str()); - ItemEnum::open_curly_brace(&mut formatted_code, formatter); + let variants = item_enum.fields.clone().into_inner(); - let type_fields = &self.fields.clone().into_inner().value_separator_pairs; + // Handle openning brace + ItemEnum::open_curly_brace(formatted_code, formatter)?; + if multiline { + formatted_code.push('\n'); + // Determine alignment tactic + match formatter.config.structures.field_alignment { + FieldAlignment::AlignFields(enum_variant_align_threshold) => { + let value_pairs = variants.value_separator_pairs; + // In first iteration we are going to be collecting the lengths of the enum variants. + let variant_length: Vec = value_pairs + .iter() + .map(|variant| variant.0.name.as_str().len()) + .collect(); - // In first iteration we are going to be collecting the lengths of the enum variants. - let variant_length: Vec = type_fields - .iter() - .map(|variant| variant.0.name.as_str().len()) - .collect(); + // Find the maximum length in the variant_length vector that is still smaller than enum_field_align_threshold. + let mut max_valid_variant_length = 0; + variant_length.iter().for_each(|length| { + if *length > max_valid_variant_length && *length < enum_variant_align_threshold + { + max_valid_variant_length = *length; + } + }); - // Find the maximum length in the variant_length vector that is still smaller than enum_variant_align_threshold. - let mut max_valid_variant_length = 0; + let mut value_pairs_iter = value_pairs.iter().enumerate().peekable(); + for (var_index, variant) in value_pairs_iter.clone() { + formatted_code.push_str(&formatter.shape.indent.to_string(formatter)); - variant_length.iter().for_each(|length| { - if *length > max_valid_variant_length && *length < enum_variant_align_threshold { - max_valid_variant_length = *length; + let type_field = &variant.0; + // Add name + formatted_code.push_str(type_field.name.as_str()); + let current_variant_length = variant_length[var_index]; + if current_variant_length < max_valid_variant_length { + // We need to add alignment between : and ty + // max_valid_variant_length: the length of the variant that we are taking as a reference to align + // current_variant_length: the length of the current variant that we are trying to format + let mut required_alignment = + max_valid_variant_length - current_variant_length; + while required_alignment != 0 { + formatted_code.push(' '); + required_alignment -= 1; + } + } + // Add `:`, ty & `CommaToken` + // + // TODO(#2101): We are currently converting ty to string directly but we will probably need to format ty before adding. + write!( + formatted_code, + " {} {}", + type_field.colon_token.ident().as_str(), + type_field.ty.span().as_str(), + )?; + if value_pairs_iter.peek().is_some() { + writeln!(formatted_code, "{}", variant.1.span().as_str())?; + } else if let Some(final_value) = &variants.final_value_opt { + formatted_code.push_str(final_value.span().as_str()); + } + } } - }); - - // In second iteration we are going to be comparing current variants length and maximum accepted variant length - // for calculating the alignment required. - for (index, type_field) in type_fields.iter().enumerate() { - let type_field = &type_field.0; - // Push the current indentation level - formatted_code.push_str(&formatter.shape.indent.to_string(formatter)); - formatted_code.push_str(type_field.name.as_str()); - - // Currently does not apply custom formatting for ty, - let current_variant_length = variant_length[index]; - - if current_variant_length < max_valid_variant_length { - // We need to add alignment between : and ty - // max_valid_variant_length: the length of the variant that we are taking as a reference to allign - // current_variant_length: the length of the current variant that we are trying to format - let required_alignment = max_valid_variant_length - current_variant_length; - // TODO: Improve handling this - formatted_code.push_str(&(0..required_alignment).map(|_| ' ').collect::()); + FieldAlignment::Off => { + let mut value_pairs_iter = variants.value_separator_pairs.iter().peekable(); + for variant in value_pairs_iter.clone() { + formatted_code.push_str(&formatter.shape.indent.to_string(formatter)); + let item_field = &variant.0; + item_field.format(formatted_code, formatter)?; + + if value_pairs_iter.peek().is_some() { + writeln!(formatted_code, "{}", variant.1.span().as_str())?; + } + } + if let Some(final_value) = &variants.final_value_opt { + formatted_code.push_str(&formatter.shape.indent.to_string(formatter)); + final_value.format(formatted_code, formatter)?; + writeln!(formatted_code, "{}", PunctKind::Comma.as_char())?; + } } - formatted_code.push_str(" : "); - // TODO: We are currently converting ty to string directly but we will probably need to format ty before adding. - formatted_code.push_str(type_field.ty.span().as_str()); - formatted_code.push(','); - - // TODO: Here we assume that next enum variant is going to be in the new line but - // from the config we may understand next enum variant should be in the same line instead. - formatted_code.push('\n'); } - ItemEnum::close_curly_brace(&mut formatted_code, formatter); - formatted_code + } else { + // non-multiline formatting + formatted_code.push(' '); + let mut value_pairs_iter = variants.value_separator_pairs.iter().peekable(); + for variant in value_pairs_iter.clone() { + let item_field = &variant.0; + item_field.format(formatted_code, formatter)?; + + if value_pairs_iter.peek().is_some() { + write!(formatted_code, "{} ", variant.1.span().as_str())?; + } + } + if let Some(final_value) = &variants.final_value_opt { + final_value.format(formatted_code, formatter)?; + formatted_code.push(' '); + } else { + formatted_code.pop(); + formatted_code.pop(); + formatted_code.push(' '); + } + } + + // Handle closing brace + ItemEnum::close_curly_brace(formatted_code, formatter)?; + Ok(()) +} + +impl ItemLen for ItemEnum { + fn get_formatted_len(&self) -> usize { + // TODO while determininig the length we may want to format to some degree and take length. + let str_item = &self.span().as_str().len(); + *str_item as usize } } impl CurlyBrace for ItemEnum { - fn open_curly_brace(line: &mut String, formatter: &mut Formatter) { + fn open_curly_brace( + line: &mut String, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { let brace_style = formatter.config.items.item_brace_style; + let extra_width = formatter.config.whitespace.tab_spaces; let mut shape = formatter.shape; + let open_brace = Delimiter::Brace.as_open_char(); match brace_style { ItemBraceStyle::AlwaysNextLine => { // Add openning brace to the next line. - line.push_str("\n{\n"); - shape = shape.block_indent(1); + writeln!(line, "\n{}", open_brace)?; + shape = shape.block_indent(extra_width); } _ => { // Add opening brace to the same line - line.push_str(" {\n"); - shape = shape.block_indent(1); + write!(line, " {}", open_brace)?; + shape = shape.block_indent(extra_width); } } formatter.shape = shape; + Ok(()) } - - fn close_curly_brace(line: &mut String, formatter: &mut Formatter) { - line.push('}'); - // If shape is becoming left-most alligned or - indent just have the defualt shape - formatter.shape = formatter.shape.shrink_left(1).unwrap_or_default(); + fn close_curly_brace( + line: &mut String, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + line.push(Delimiter::Brace.as_close_char()); + // If shape is becoming left-most aligned or - indent just have the defualt shape + formatter.shape = formatter + .shape + .shrink_left(formatter.config.whitespace.tab_spaces) + .unwrap_or_default(); + Ok(()) } } diff --git a/sway-fmt-v2/src/items/item_fn.rs b/sway-fmt-v2/src/items/item_fn.rs index 123a294debd..d50df8d7827 100644 --- a/sway-fmt-v2/src/items/item_fn.rs +++ b/sway-fmt-v2/src/items/item_fn.rs @@ -1,8 +1,15 @@ -use crate::fmt::{Format, FormattedCode, Formatter}; +use crate::{ + fmt::{Format, FormattedCode, Formatter}, + FormatterError, +}; use sway_parse::ItemFn; impl Format for ItemFn { - fn format(&self, _formatter: &mut Formatter) -> FormattedCode { + fn format( + &self, + _formatted_code: &mut FormattedCode, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { todo!() } } diff --git a/sway-fmt-v2/src/items/item_impl.rs b/sway-fmt-v2/src/items/item_impl.rs index 2a7e53e3ce0..a14aedad852 100644 --- a/sway-fmt-v2/src/items/item_impl.rs +++ b/sway-fmt-v2/src/items/item_impl.rs @@ -1,8 +1,15 @@ -use crate::fmt::{Format, FormattedCode, Formatter}; +use crate::{ + fmt::{Format, FormattedCode, Formatter}, + FormatterError, +}; use sway_parse::ItemImpl; impl Format for ItemImpl { - fn format(&self, _formatter: &mut Formatter) -> FormattedCode { + fn format( + &self, + _formatted_code: &mut FormattedCode, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { todo!() } } diff --git a/sway-fmt-v2/src/items/item_storage.rs b/sway-fmt-v2/src/items/item_storage.rs index dd7f2962a23..8d3f385adb7 100644 --- a/sway-fmt-v2/src/items/item_storage.rs +++ b/sway-fmt-v2/src/items/item_storage.rs @@ -1,8 +1,15 @@ -use crate::fmt::{Format, FormattedCode, Formatter}; +use crate::{ + fmt::{Format, FormattedCode, Formatter}, + FormatterError, +}; use sway_parse::ItemStorage; impl Format for ItemStorage { - fn format(&self, _formatter: &mut Formatter) -> FormattedCode { + fn format( + &self, + _formatted_code: &mut FormattedCode, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { todo!() } } diff --git a/sway-fmt-v2/src/items/item_struct.rs b/sway-fmt-v2/src/items/item_struct.rs index ebc34dcab60..6d4c35c697c 100644 --- a/sway-fmt-v2/src/items/item_struct.rs +++ b/sway-fmt-v2/src/items/item_struct.rs @@ -1,8 +1,233 @@ -use crate::fmt::{Format, FormattedCode, Formatter}; -use sway_parse::ItemStruct; +use crate::{ + config::{items::ItemBraceStyle, user_def::FieldAlignment}, + fmt::{Format, FormattedCode, Formatter}, + utils::{bracket::CurlyBrace, item_len::ItemLen}, + FormatterError, +}; +use std::fmt::Write; +use sway_parse::{ + token::{Delimiter, PunctKind}, + ItemStruct, +}; +use sway_types::Spanned; impl Format for ItemStruct { - fn format(&self, _formatter: &mut Formatter) -> FormattedCode { - todo!() + fn format( + &self, + formatted_code: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + // Bring configurations into scope. + // + // Should small structs formatted into a single line. + let struct_lit_single_line = formatter.config.structures.small_structures_single_line; + + // Get the width limit of a struct to be formatted into single line if struct_lit_single_line is true. + let width_heuristics = formatter + .config + .heuristics + .heuristics_pref + .to_width_heuristics(&formatter.config.whitespace); + let struct_lit_width = width_heuristics.structure_lit_width; + + let multiline = !struct_lit_single_line || self.get_formatted_len() > struct_lit_width; + + format_struct(self, formatted_code, formatter, multiline)?; + Ok(()) + } +} + +/// Format the struct if the multiline is passed as false struct will be formatted into a single line. +/// +/// ## Examples +/// +/// (multiline : false): +/// +/// ```rust,ignore +/// struct Foo { bar: u64, baz: bool } +/// ``` +/// +/// (multiline : true): +/// +/// ```rust,ignore +/// struct Foo { +/// bar: u64, +/// baz: bool, +/// } +/// ``` +fn format_struct( + item_struct: &ItemStruct, + formatted_code: &mut FormattedCode, + formatter: &mut Formatter, + multiline: bool, +) -> Result<(), FormatterError> { + // If there is a visibility token add it to the formatted_code with a ` ` after it. + if let Some(visibility) = &item_struct.visibility { + write!(formatted_code, "{} ", visibility.span().as_str())?; + } + // Add struct token + write!( + formatted_code, + "{} ", + item_struct.struct_token.span().as_str() + )?; + + // Add struct name + formatted_code.push_str(item_struct.name.as_str()); + + // Format `GenericParams`, if any + if let Some(generics) = &item_struct.generics { + generics.format(formatted_code, formatter)?; + } + + let fields = item_struct.fields.clone().into_inner(); + + // Handle openning brace + ItemStruct::open_curly_brace(formatted_code, formatter)?; + if multiline { + formatted_code.push('\n'); + // Determine alignment tactic + match formatter.config.structures.field_alignment { + FieldAlignment::AlignFields(struct_field_align_threshold) => { + let value_pairs = fields.value_separator_pairs; + // In first iteration we are going to be collecting the lengths of the struct fields. + let field_length: Vec = value_pairs + .iter() + .map(|field| field.0.name.as_str().len()) + .collect(); + + // Find the maximum length in the `field_length` vector that is still smaller than `struct_field_align_threshold`. + // `max_valid_field_length`: the length of the field that we are taking as a reference to align. + let mut max_valid_field_length = 0; + field_length.iter().for_each(|length| { + if *length > max_valid_field_length && *length < struct_field_align_threshold { + max_valid_field_length = *length; + } + }); + + let mut value_pairs_iter = value_pairs.iter().enumerate().peekable(); + for (field_index, field) in value_pairs_iter.clone() { + formatted_code.push_str(&formatter.shape.indent.to_string(formatter)); + + let type_field = &field.0; + // Add name + formatted_code.push_str(type_field.name.as_str()); + + // `current_field_length`: the length of the current field that we are trying to format. + let current_field_length = field_length[field_index]; + if current_field_length < max_valid_field_length { + // We need to add alignment between `:` and `ty` + let mut required_alignment = max_valid_field_length - current_field_length; + while required_alignment != 0 { + formatted_code.push(' '); + required_alignment -= 1; + } + } + // Add `:`, `ty` & `CommaToken` + // + // TODO(#2101): We are currently converting ty to string directly but + // we will probably need to format `ty` before adding. + write!( + formatted_code, + " {} {}", + type_field.colon_token.ident().as_str(), + type_field.ty.span().as_str(), + )?; + if value_pairs_iter.peek().is_some() { + writeln!(formatted_code, "{}", field.1.span().as_str())?; + } else if let Some(final_value) = &fields.final_value_opt { + formatted_code.push_str(final_value.span().as_str()); + } + } + } + FieldAlignment::Off => { + let mut value_pairs_iter = fields.value_separator_pairs.iter().peekable(); + for field in value_pairs_iter.clone() { + formatted_code.push_str(&formatter.shape.indent.to_string(formatter)); + let item_field = &field.0; + item_field.format(formatted_code, formatter)?; + + if value_pairs_iter.peek().is_some() { + writeln!(formatted_code, "{}", field.1.span().as_str())?; + } + } + if let Some(final_value) = &fields.final_value_opt { + formatted_code.push_str(&formatter.shape.indent.to_string(formatter)); + final_value.format(formatted_code, formatter)?; + writeln!(formatted_code, "{}", PunctKind::Comma.as_char())?; + } + } + } + } else { + // non-multiline formatting + formatted_code.push(' '); + let mut value_pairs_iter = fields.value_separator_pairs.iter().peekable(); + for field in value_pairs_iter.clone() { + let type_field = &field.0; + type_field.format(formatted_code, formatter)?; + + if value_pairs_iter.peek().is_some() { + write!(formatted_code, "{} ", field.1.span().as_str())?; + } + } + if let Some(final_value) = &fields.final_value_opt { + final_value.format(formatted_code, formatter)?; + formatted_code.push(' '); + } else { + formatted_code.pop(); + formatted_code.pop(); + formatted_code.push(' '); + } + } + + // Handle closing brace + ItemStruct::close_curly_brace(formatted_code, formatter)?; + Ok(()) +} + +impl ItemLen for ItemStruct { + fn get_formatted_len(&self) -> usize { + // TODO while determininig the length we may want to format to some degree and take length. + let str_item = &self.span().as_str().len(); + *str_item as usize + } +} + +impl CurlyBrace for ItemStruct { + fn open_curly_brace( + line: &mut String, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + let brace_style = formatter.config.items.item_brace_style; + let extra_width = formatter.config.whitespace.tab_spaces; + let mut shape = formatter.shape; + match brace_style { + ItemBraceStyle::AlwaysNextLine => { + // Add openning brace to the next line. + write!(line, "\n{}", Delimiter::Brace.as_open_char())?; + shape = shape.block_indent(extra_width); + } + _ => { + // Add opening brace to the same line + write!(line, " {}", Delimiter::Brace.as_open_char())?; + shape = shape.block_indent(extra_width); + } + } + + formatter.shape = shape; + Ok(()) + } + + fn close_curly_brace( + line: &mut String, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + line.push(Delimiter::Brace.as_close_char()); + // If shape is becoming left-most alligned or - indent just have the defualt shape + formatter.shape = formatter + .shape + .shrink_left(formatter.config.whitespace.tab_spaces) + .unwrap_or_default(); + Ok(()) } } diff --git a/sway-fmt-v2/src/items/item_trait.rs b/sway-fmt-v2/src/items/item_trait.rs index 4b28ba62089..d6d0010da47 100644 --- a/sway-fmt-v2/src/items/item_trait.rs +++ b/sway-fmt-v2/src/items/item_trait.rs @@ -1,8 +1,15 @@ -use crate::fmt::{Format, FormattedCode, Formatter}; +use crate::{ + fmt::{Format, FormattedCode, Formatter}, + FormatterError, +}; use sway_parse::ItemTrait; impl Format for ItemTrait { - fn format(&self, _formatter: &mut Formatter) -> FormattedCode { + fn format( + &self, + _formatted_code: &mut FormattedCode, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { todo!() } } diff --git a/sway-fmt-v2/src/items/item_use.rs b/sway-fmt-v2/src/items/item_use.rs index 895cf2e7722..cf23ebc89dd 100644 --- a/sway-fmt-v2/src/items/item_use.rs +++ b/sway-fmt-v2/src/items/item_use.rs @@ -1,8 +1,15 @@ -use crate::fmt::{Format, FormattedCode, Formatter}; +use crate::{ + fmt::{Format, FormattedCode, Formatter}, + FormatterError, +}; use sway_parse::ItemUse; impl Format for ItemUse { - fn format(&self, _formatter: &mut Formatter) -> FormattedCode { + fn format( + &self, + _formatted_code: &mut FormattedCode, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { todo!() } } diff --git a/sway-fmt-v2/src/utils.rs b/sway-fmt-v2/src/utils.rs index 96bd73c8b3e..8d97a0a8c28 100644 --- a/sway-fmt-v2/src/utils.rs +++ b/sway-fmt-v2/src/utils.rs @@ -1,4 +1,9 @@ -pub mod attributes; -pub mod bracket; -pub mod indent_style; -pub mod newline_style; +pub(crate) mod attribute; +pub(crate) mod bracket; +pub(crate) mod generics; +pub(crate) mod indent_style; +pub(crate) mod item; +pub(crate) mod item_len; +pub(crate) mod newline_style; +pub(crate) mod program_type; +pub(crate) mod punctuated; diff --git a/sway-fmt-v2/src/utils/attribute.rs b/sway-fmt-v2/src/utils/attribute.rs new file mode 100644 index 00000000000..dbceaaa918d --- /dev/null +++ b/sway-fmt-v2/src/utils/attribute.rs @@ -0,0 +1,93 @@ +use crate::{ + fmt::{Format, FormattedCode, Formatter}, + FormatterError, +}; +use std::fmt::Write; +use sway_parse::{ + attribute::{Annotated, AttributeDecl}, + token::Delimiter, + Parse, +}; +use sway_types::Spanned; + +use super::bracket::{Parenthesis, SquareBracket}; + +impl Format for Annotated { + fn format( + &self, + formatted_code: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + // format each `Attribute` + for attr in &self.attribute_list { + attr.format(formatted_code, formatter)?; + } + // format `ItemKind` + self.value.format(formatted_code, formatter) + } +} + +pub trait FormatDecl { + fn format(&self, line: &mut String, formatter: &mut Formatter) -> Result<(), FormatterError>; +} + +impl FormatDecl for AttributeDecl { + fn format(&self, line: &mut String, formatter: &mut Formatter) -> Result<(), FormatterError> { + // At some point there will be enough attributes to warrant the need + // of formatting the list according to `config::lists::ListTactic`. + // For now the default implementation will be `Horizontal`. + // + // `#` + line.push_str(self.hash_token.span().as_str()); + // `[` + Self::open_square_bracket(line, formatter)?; + let attr = self.attribute.clone().into_inner(); + // name e.g. `storage` + line.push_str(attr.name.span().as_str()); + // `(` + Self::open_parenthesis(line, formatter)?; + // format and add args e.g. `read, write` + if let Some(args) = attr.args { + args.into_inner().format(line, formatter)?; + } + // ')' + Self::close_parenthesis(line, formatter)?; + // `]\n` + Self::close_square_bracket(line, formatter)?; + Ok(()) + } +} + +impl SquareBracket for AttributeDecl { + fn open_square_bracket( + line: &mut String, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + line.push(Delimiter::Bracket.as_open_char()); + Ok(()) + } + fn close_square_bracket( + line: &mut String, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + writeln!(line, "{}", Delimiter::Bracket.as_close_char())?; + Ok(()) + } +} + +impl Parenthesis for AttributeDecl { + fn open_parenthesis( + line: &mut String, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + line.push(Delimiter::Parenthesis.as_open_char()); + Ok(()) + } + fn close_parenthesis( + line: &mut String, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + line.push(Delimiter::Parenthesis.as_close_char()); + Ok(()) + } +} diff --git a/sway-fmt-v2/src/utils/attributes.rs b/sway-fmt-v2/src/utils/attributes.rs deleted file mode 100644 index 4700c41b7f6..00000000000 --- a/sway-fmt-v2/src/utils/attributes.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::Formatter; -use sway_parse::AttributeDecl; -use sway_types::Spanned; -pub fn format_attributes(attributes: Vec, _formatter: &mut Formatter) -> String { - // TODO format attributes - attributes - .into_iter() - .map(|x| x.span().as_str().to_string()) - .collect::>() - .join("\n") -} diff --git a/sway-fmt-v2/src/utils/bracket.rs b/sway-fmt-v2/src/utils/bracket.rs index 906d2bcb50f..c5ca4e5884b 100644 --- a/sway-fmt-v2/src/utils/bracket.rs +++ b/sway-fmt-v2/src/utils/bracket.rs @@ -1,35 +1,61 @@ //! The purpose of this file is to house the traits and associated functions for formatting opening and closing delimiters. //! This allows us to avoid matching a second time for the `ItemKind` and keeps the code pertaining to individual formatting //! contained to each item's file. -use crate::Formatter; +use crate::{fmt::FormattedCode, Formatter, FormatterError}; -pub trait CurlyBrace { +pub(crate) trait CurlyBrace { /// Handles brace open scenerio. Checks the config for the placement of the brace. /// Modifies the current shape of the formatter. - fn open_curly_brace(line: &mut String, formatter: &mut Formatter); + fn open_curly_brace( + line: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError>; /// Handles brace close scenerio. /// Currently it simply pushes a `}` and modifies the shape. - fn close_curly_brace(line: &mut String, formatter: &mut Formatter); + fn close_curly_brace( + line: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError>; } -pub trait SquareBracket { - fn open_square_bracket(line: &mut String, formatter: &mut Formatter); +pub(crate) trait SquareBracket { + fn open_square_bracket( + line: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError>; - fn close_square_bracket(line: &mut String, formatter: &mut Formatter); + fn close_square_bracket( + line: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError>; } -pub trait Parenthesis { +pub(crate) trait Parenthesis { /// Handles open parenthesis scenarios, checking the config for placement /// and modifying the shape of the formatter where necessary. - fn open_parenthesis(line: &mut String, formatter: &mut Formatter); + fn open_parenthesis( + line: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError>; /// Handles the closing parenthesis scenario. - fn close_parenthesis(line: &mut String, formatter: &mut Formatter); + fn close_parenthesis( + line: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError>; } pub trait AngleBracket { - fn open_angle_bracket(line: &mut String, formatter: &mut Formatter); - - fn close_angle_bracket(line: &mut String, formatter: &mut Formatter); + fn open_angle_bracket( + self, + line: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError>; + + fn close_angle_bracket( + self, + line: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError>; } diff --git a/sway-fmt-v2/src/utils/generics.rs b/sway-fmt-v2/src/utils/generics.rs new file mode 100644 index 00000000000..0b69758476d --- /dev/null +++ b/sway-fmt-v2/src/utils/generics.rs @@ -0,0 +1,48 @@ +use crate::{ + fmt::{Format, FormattedCode, Formatter, FormatterError}, + utils::bracket::AngleBracket, +}; +use sway_parse::GenericParams; +use sway_types::Spanned; + +// In the future we will need to determine whether the generic arguments +// are better suited with a `where` clause. At present they will be +// formatted in line. +// +impl Format for GenericParams { + fn format( + &self, + formatted_code: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + let params = self.parameters.clone().into_inner(); + + // `<` + Self::open_angle_bracket(self.clone(), formatted_code, formatter)?; + // format and add parameters + params.format(formatted_code, formatter)?; + // `>` + Self::close_angle_bracket(self.clone(), formatted_code, formatter)?; + + Ok(()) + } +} + +impl AngleBracket for GenericParams { + fn open_angle_bracket( + self, + line: &mut String, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + line.push_str(self.parameters.open_angle_bracket_token.span().as_str()); + Ok(()) + } + fn close_angle_bracket( + self, + line: &mut String, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + line.push_str(self.parameters.close_angle_bracket_token.span().as_str()); + Ok(()) + } +} diff --git a/sway-fmt-v2/src/utils/item.rs b/sway-fmt-v2/src/utils/item.rs new file mode 100644 index 00000000000..e6e8bd00de0 --- /dev/null +++ b/sway-fmt-v2/src/utils/item.rs @@ -0,0 +1,23 @@ +use sway_parse::{Item, ItemKind::*}; + +use crate::fmt::{Format, FormattedCode, Formatter, FormatterError}; + +impl Format for Item { + fn format( + &self, + formatted_code: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + match &self.value { + Use(item_use) => item_use.format(formatted_code, formatter), + Struct(item_struct) => item_struct.format(formatted_code, formatter), + Enum(item_enum) => item_enum.format(formatted_code, formatter), + Fn(item_fn) => item_fn.format(formatted_code, formatter), + Trait(item_trait) => item_trait.format(formatted_code, formatter), + Impl(item_impl) => item_impl.format(formatted_code, formatter), + Abi(item_abi) => item_abi.format(formatted_code, formatter), + Const(item_const) => item_const.format(formatted_code, formatter), + Storage(item_storage) => item_storage.format(formatted_code, formatter), + } + } +} diff --git a/sway-fmt-v2/src/utils/item_len.rs b/sway-fmt-v2/src/utils/item_len.rs new file mode 100644 index 00000000000..4a4279b7440 --- /dev/null +++ b/sway-fmt-v2/src/utils/item_len.rs @@ -0,0 +1,3 @@ +pub trait ItemLen { + fn get_formatted_len(&self) -> usize; +} diff --git a/sway-fmt-v2/src/utils/program_type.rs b/sway-fmt-v2/src/utils/program_type.rs new file mode 100644 index 00000000000..13b7b6e796f --- /dev/null +++ b/sway-fmt-v2/src/utils/program_type.rs @@ -0,0 +1,29 @@ +use sway_parse::{token::PunctKind, ModuleKind}; +use sway_types::Spanned; + +/// Insert the program type without applying a formatting to it. +/// +/// Possible list of program types: +/// - Script +/// - Contract +/// - Predicate +/// - Library +pub(crate) fn insert_program_type(push_to: &mut String, module_kind: ModuleKind) { + match module_kind { + ModuleKind::Script { script_token } => push_to.push_str(script_token.span().as_str()), + ModuleKind::Contract { contract_token } => push_to.push_str(contract_token.span().as_str()), + ModuleKind::Predicate { predicate_token } => { + push_to.push_str(predicate_token.span().as_str()) + } + ModuleKind::Library { + library_token, + name, + } => { + push_to.push_str(library_token.span().as_str()); + push_to.push(' '); + push_to.push_str(name.as_str()); + } + }; + push_to.push(PunctKind::Semicolon.as_char()); + push_to.push_str("\n\n"); +} diff --git a/sway-fmt-v2/src/utils/punctuated.rs b/sway-fmt-v2/src/utils/punctuated.rs new file mode 100644 index 00000000000..96ba1d501da --- /dev/null +++ b/sway-fmt-v2/src/utils/punctuated.rs @@ -0,0 +1,57 @@ +use crate::{ + fmt::{Format, FormattedCode, Formatter}, + FormatterError, +}; +use std::fmt::Write; +use sway_parse::{punctuated::Punctuated, TypeField}; +use sway_types::Spanned; + +impl Format for Punctuated +where + T: Spanned, + P: Spanned, +{ + fn format( + &self, + formatted_code: &mut FormattedCode, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + // format and add Type & Punct + let value_pairs = &self.value_separator_pairs; + + // Later on we may want to handle instances + // where the user wants to keep the trailing commas. + for pair in value_pairs.iter() { + write!( + formatted_code, + "{}{} ", + pair.0.span().as_str(), + pair.1.span().as_str(), + )?; + } + + // add final value, if any + if let Some(final_value) = &self.final_value_opt { + formatted_code.push_str(final_value.span().as_str()); + } + + Ok(()) + } +} + +impl Format for TypeField { + fn format( + &self, + formatted_code: &mut FormattedCode, + _formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + write!( + formatted_code, + "{}{} {}", + self.name.span().as_str(), + self.colon_token.span().as_str(), + self.ty.span().as_str() + )?; + Ok(()) + } +} diff --git a/sway-fmt/Cargo.toml b/sway-fmt/Cargo.toml index 72f4967f3c9..c7016da9e7a 100644 --- a/sway-fmt/Cargo.toml +++ b/sway-fmt/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sway-fmt" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -10,6 +10,6 @@ description = "Sway sway-fmt." [dependencies] ropey = "1.2" -sway-core = { version = "0.16.1", path = "../sway-core" } -sway-types = { version = "0.16.1", path = "../sway-types" } +sway-core = { version = "0.16.2", path = "../sway-core" } +sway-types = { version = "0.16.2", path = "../sway-types" } diff --git a/sway-ir/Cargo.toml b/sway-ir/Cargo.toml index 43759b163c5..2af5a31b5a9 100644 --- a/sway-ir/Cargo.toml +++ b/sway-ir/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sway-ir" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -12,5 +12,5 @@ description = "Sway intermediate representation." filecheck = "0.5" generational-arena = "0.2" peg = "0.7" -sway-types = { version = "0.16.1", path = "../sway-types" } +sway-types = { version = "0.16.2", path = "../sway-types" } tracing = "0.1" diff --git a/sway-ir/src/block.rs b/sway-ir/src/block.rs index b7dd20307ee..d2a8f85efee 100644 --- a/sway-ir/src/block.rs +++ b/sway-ir/src/block.rs @@ -149,6 +149,11 @@ impl Block { }) } + pub fn is_terminated_by_ret(&self, context: &Context) -> bool { + self.get_term_inst(context) + .map_or(false, |i| matches!(i, Instruction::Ret { .. })) + } + /// Replace a value within this block. /// /// For every instruction within the block, any reference to `old_val` is replaced with diff --git a/sway-ir/src/verify.rs b/sway-ir/src/verify.rs index cdde4d1b024..592a52cbcbd 100644 --- a/sway-ir/src/verify.rs +++ b/sway-ir/src/verify.rs @@ -173,10 +173,9 @@ impl<'a> InstructionVerifier<'a> { fn verify_bitcast(&self, value: &Value, ty: &Type) -> Result<(), IrError> { // The to and from types must be copy-types, excluding short strings, and the same size. - let val_ty = match value.get_type(self.context) { - None => return Err(IrError::VerifyBitcastUnknownSourceType), - Some(ty) => ty, - }; + let val_ty = value + .get_type(self.context) + .ok_or(IrError::VerifyBitcastUnknownSourceType)?; if !val_ty.is_copy_type() { return Err(IrError::VerifyBitcastFromNonCopyType( val_ty.as_string(self.context), @@ -305,6 +304,7 @@ impl<'a> InstructionVerifier<'a> { Ok(()) } } + (Type::Bool, Type::Bool) => Ok(()), _otherwise => Err(IrError::VerifyCmpBadTypes( lhs_ty.as_string(self.context), rhs_ty.as_string(self.context), diff --git a/sway-lib-core/src/ops.sw b/sway-lib-core/src/ops.sw index 4d3382caf31..d009e8d4ce3 100644 --- a/sway-lib-core/src/ops.sw +++ b/sway-lib-core/src/ops.sw @@ -210,46 +210,31 @@ pub trait Eq { impl Eq for bool { fn eq(self, other: Self) -> bool { - asm(r1: self, r2: other, r3) { - eq r3 r1 r2; - r3: bool - } + __eq(self, other) } } impl Eq for u64 { fn eq(self, other: Self) -> bool { - asm(r1: self, r2: other, r3) { - eq r3 r1 r2; - r3: bool - } + __eq(self, other) } } impl Eq for u32 { fn eq(self, other: Self) -> bool { - asm(r1: self, r2: other, r3) { - eq r3 r1 r2; - r3: bool - } + __eq(self, other) } } impl Eq for u16 { fn eq(self, other: Self) -> bool { - asm(r1: self, r2: other, r3) { - eq r3 r1 r2; - r3: bool - } + __eq(self, other) } } impl Eq for u8 { fn eq(self, other: Self) -> bool { - asm(r1: self, r2: other, r3) { - eq r3 r1 r2; - r3: bool - } + __eq(self, other) } } diff --git a/sway-lib-std/src/constants.sw b/sway-lib-std/src/constants.sw index b73e6cadf25..ea16cbda0cf 100644 --- a/sway-lib-std/src/constants.sw +++ b/sway-lib-std/src/constants.sw @@ -1,3 +1,5 @@ library constants; -const BASE_ASSET_ID = 0x0000000000000000000000000000000000000000000000000000000000000000; +use ::contract_id::ContractId; + +const BASE_ASSET_ID = ~ContractId::from(0x0000000000000000000000000000000000000000000000000000000000000000); diff --git a/sway-lib-std/src/identity.sw b/sway-lib-std/src/identity.sw index d39c1ac5ce1..64143d047fd 100644 --- a/sway-lib-std/src/identity.sw +++ b/sway-lib-std/src/identity.sw @@ -4,10 +4,12 @@ library identity; use ::address::Address; use ::contract_id::ContractId; +// ANCHOR: docs_identity pub enum Identity { Address: Address, ContractId: ContractId, } +// ANCHOR_END: docs_identity impl core::ops::Eq for Identity { fn eq(self, other: Self) -> bool { diff --git a/sway-lib-std/src/lib.sw b/sway-lib-std/src/lib.sw index e3b9be440d2..aa54fcd82ac 100644 --- a/sway-lib-std/src/lib.sw +++ b/sway-lib-std/src/lib.sw @@ -8,11 +8,11 @@ dep option; dep result; dep mem; dep alloc; -dep constants; dep contract_id; +dep constants; dep context; dep hash; -dep storage; +dep r#storage; dep b512; dep address; dep identity; @@ -26,6 +26,7 @@ dep reentrancy; dep vm/mod; dep flags; dep u128; +dep u256; dep vec; use core::*; diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index b5af3edc2db..ccea723db73 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -1,4 +1,4 @@ -library storage; +library r#storage; use ::hash::sha256; use ::option::Option; @@ -18,7 +18,7 @@ use ::context::registers::stack_ptr; let mut size_left = __size_of::(); let mut local_key = key; - // Cast the the pointer to `value` to a u64. This lets us increment + // Cast the pointer to `value` to a u64. This lets us increment // this pointer later on to iterate over 32 byte chunks of `value`. let mut ptr_to_value = asm(v: value) { v diff --git a/sway-lib-std/src/u128.sw b/sway-lib-std/src/u128.sw index 51f0ba28033..82a7ce2dfaf 100644 --- a/sway-lib-std/src/u128.sw +++ b/sway-lib-std/src/u128.sw @@ -12,6 +12,10 @@ pub struct U128 { lower: u64, } +pub enum U128Error { + LossOfPrecision: (), +} + pub trait From { /// Function for creating U128 from its u64 components. pub fn from(upper: u64, lower: u64) -> Self; @@ -24,7 +28,7 @@ pub trait From { impl From for U128 { pub fn from(upper: u64, lower: u64) -> U128 { U128 { - upper, lower, + upper, lower, } } } @@ -102,14 +106,15 @@ impl U128 { } } - /// Downcast to `u64`. Err if precision would be lost, Ok otherwise. - pub fn to_u64(self) -> Result { + /// Safely downcast to `u64` without loss of precision. + /// Returns Err if the number > ~u64::max() + pub fn as_u64(self) -> Result { match self.upper { 0 => { Result::Ok(self.lower) }, _ => { - Result::Err(()) + Result::Err(U128Error::LossOfPrecision) }, } } @@ -245,7 +250,7 @@ impl core::ops::Subtract for U128 { } U128 { - upper, lower, + upper, lower, } } } diff --git a/sway-lib-std/src/u256.sw b/sway-lib-std/src/u256.sw new file mode 100644 index 00000000000..5d9547c3deb --- /dev/null +++ b/sway-lib-std/src/u256.sw @@ -0,0 +1,90 @@ +library u256; + +use core::num::*; +use ::result::Result; + +/// The 256-bit unsigned integer type. +/// Represented as four 64-bit components: `(a, b, c, d)`, where `value = (a << 192) + (b << 128) + (c << 64) + d`. +pub struct U256 { + a: u64, + b: u64, + c: u64, + d: u64, +} + +pub enum U256Error { + LossOfPrecision: (), +} + +pub trait From { + /// Function for creating a U256 from its u64 components. + pub fn from(a: u64, b: u64, c: u64, d: u64) -> Self; +} { + /// Function for extracting 4 u64s from a U256. + fn into(val: U256) -> (u64, u64, u64, u64) { + (val.a, val.b, val.c, val.d) + } +} + +impl From for U256 { + pub fn from(a: u64, b: u64, c: u64, d: u64) -> U256 { + U256 { + a, b, c, d, + } + } +} + +impl core::ops::Eq for U256 { + /// Function for comparing 2 U256s for equality + pub fn eq(self, other: Self) -> bool { + self.a == other.a && self.b == other.b && self.c == other.c && self.d == other.d + } +} + +impl U256 { + /// Initializes a new, zeroed U256. + pub fn new() -> U256 { + U256 { + a: 0, + b: 0, + c: 0, + d: 0, + } + } + + /// Safely downcast to `u64` without loss of precision. + /// Returns Err if the number > ~u64::max() + pub fn as_u64(self) -> Result { + if self.a == 0 && self.b == 0 && self.c == 0 { + Result::Ok(self.d) + } else { + Result::Err(U256Error::LossOfPrecision) + } + } + + /// The smallest value that can be represented by this integer type. + pub fn min() -> U256 { + U256 { + a: 0, + b: 0, + c: 0, + d: 0, + } + } + + /// The largest value that can be represented by this type, + /// 2256 - 1. + pub fn max() -> U256 { + U256 { + a: ~u64::max(), + b: ~u64::max(), + c: ~u64::max(), + d: ~u64::max(), + } + } + + /// The size of this type in bits. + pub fn bits() -> u32 { + 256 + } +} diff --git a/sway-lsp/Cargo.toml b/sway-lsp/Cargo.toml index d156c9fd2dd..fd4ae6cd023 100644 --- a/sway-lsp/Cargo.toml +++ b/sway-lsp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sway-lsp" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -9,14 +9,16 @@ repository = "https://github.com/FuelLabs/sway" description = "LSP server for Sway." [dependencies] -dashmap = "4.0.2" -forc-util = { version = "0.16.1", path = "../forc-util" } +dashmap = "5.3.4" +forc = { version = "0.16.2", path = "../forc" } +forc-pkg = { version = "0.16.2", path = "../forc-pkg" } +forc-util = { version = "0.16.2", path = "../forc-util" } ropey = "1.2" serde_json = "1.0.60" -sway-core = { version = "0.16.1", path = "../sway-core" } -sway-fmt = { version = "0.16.1", path = "../sway-fmt" } -sway-types = { version = "0.16.1", path = "../sway-types" } -sway-utils = { version = "0.16.1", path = "../sway-utils" } +sway-core = { version = "0.16.2", path = "../sway-core" } +sway-fmt = { version = "0.16.2", path = "../sway-fmt" } +sway-types = { version = "0.16.2", path = "../sway-types" } +sway-utils = { version = "0.16.2", path = "../sway-utils" } tokio = { version = "1.3", features = ["io-std", "io-util", "macros", "net", "rt-multi-thread", "sync", "time"] } tower-lsp = "0.16.0" tracing = "0.1" diff --git a/sway-lsp/src/core/document.rs b/sway-lsp/src/core/document.rs index 8137bd89fec..3eea41621a5 100644 --- a/sway-lsp/src/core/document.rs +++ b/sway-lsp/src/core/document.rs @@ -6,14 +6,10 @@ use super::traverse_typed_tree; use super::typed_token_type::TokenMap; use crate::{capabilities, core::token::traverse_node, utils}; +use forc_pkg::{self as pkg}; use ropey::Rope; -use std::collections::HashMap; -use std::sync::Arc; -use sway_core::{ - parse, - semantic_analysis::{ast_node::TypedAstNode, namespace}, - CompileAstResult, TreeType, -}; +use std::{collections::HashMap, path::PathBuf, sync::Arc}; +use sway_core::{parse, semantic_analysis::ast_node::TypedAstNode, CompileAstResult, TreeType}; use tower_lsp::lsp_types::{Diagnostic, Position, Range, TextDocumentContentChangeEvent}; #[derive(Debug)] @@ -160,10 +156,15 @@ impl TextDocument { // private methods impl TextDocument { fn parse_typed_tokens_from_text(&self) -> Option> { - let text = Arc::from(self.get_text()); - let namespace = namespace::Module::default(); - let ast_res = sway_core::compile_to_ast(text, namespace, None); - match ast_res { + let manifest_dir = PathBuf::from(self.get_uri()); + let silent_mode = true; + let manifest = + pkg::ManifestFile::from_dir(&manifest_dir, forc::utils::SWAY_GIT_TAG).unwrap(); + let lock_path = forc_util::lock_path(manifest.dir()); + let plan = pkg::BuildPlan::from_lock_file(&lock_path, forc::utils::SWAY_GIT_TAG).unwrap(); + let res = pkg::check(&plan, silent_mode, forc::utils::SWAY_GIT_TAG).unwrap(); + + match res { CompileAstResult::Failure { .. } => None, CompileAstResult::Success { typed_program, .. } => Some(typed_program.root.all_nodes), } diff --git a/sway-lsp/src/core/token.rs b/sway-lsp/src/core/token.rs index a7d3dd231bf..c03f83ef9b5 100644 --- a/sway-lsp/src/core/token.rs +++ b/sway-lsp/src/core/token.rs @@ -8,7 +8,7 @@ use crate::{ use sway_core::{ constants::TUPLE_NAME_PREFIX, parse_tree::MethodName, type_engine::TypeInfo, AstNode, AstNodeContent, Declaration, Expression, FunctionDeclaration, FunctionParameter, - IntrinsicFunctionKind, VariableDeclaration, WhileLoop, + VariableDeclaration, WhileLoop, }; use sway_types::{ident::Ident, span::Span, Spanned}; use tower_lsp::lsp_types::Range; @@ -441,20 +441,15 @@ fn handle_expression(exp: Expression, tokens: &mut Vec) { tokens.push(token); } } - Expression::IntrinsicFunction { kind, .. } => { - handle_intrinsic_function(kind, tokens); + Expression::IntrinsicFunction { arguments, .. } => { + handle_intrinsic_function(arguments, tokens); } } } -fn handle_intrinsic_function(kind: IntrinsicFunctionKind, tokens: &mut Vec) { - match kind { - IntrinsicFunctionKind::SizeOfVal { exp } => { - handle_expression(*exp, tokens); - } - IntrinsicFunctionKind::SizeOfType { .. } => {} - IntrinsicFunctionKind::IsRefType { .. } => {} - IntrinsicFunctionKind::GetStorageKey => {} +fn handle_intrinsic_function(arguments: Vec, tokens: &mut Vec) { + for arg in arguments { + handle_expression(arg, tokens); } } diff --git a/sway-lsp/src/core/traverse_typed_tree.rs b/sway-lsp/src/core/traverse_typed_tree.rs index fa676176e5e..ee23d9b9cb2 100644 --- a/sway-lsp/src/core/traverse_typed_tree.rs +++ b/sway-lsp/src/core/traverse_typed_tree.rs @@ -332,14 +332,12 @@ fn handle_expression(expression: &TypedExpression, tokens: &mut TokenMap) { } } -fn handle_intrinsic_function(kind: &TypedIntrinsicFunctionKind, tokens: &mut TokenMap) { - match kind { - TypedIntrinsicFunctionKind::SizeOfVal { exp } => { - handle_expression(exp, tokens); - } - TypedIntrinsicFunctionKind::SizeOfType { .. } => {} - TypedIntrinsicFunctionKind::IsRefType { .. } => {} - TypedIntrinsicFunctionKind::GetStorageKey => {} +fn handle_intrinsic_function( + TypedIntrinsicFunctionKind { arguments, .. }: &TypedIntrinsicFunctionKind, + tokens: &mut TokenMap, +) { + for arg in arguments { + handle_expression(arg, tokens); } } diff --git a/sway-lsp/src/server.rs b/sway-lsp/src/server.rs index f167fa4af4f..5a66c1d9182 100644 --- a/sway-lsp/src/server.rs +++ b/sway-lsp/src/server.rs @@ -242,7 +242,7 @@ impl LanguageServer for Backend { #[cfg(test)] mod tests { use serde_json::json; - use std::{env, fs::File, io::Write}; + use std::{env, fs, io::Read}; use tower::{Service, ServiceExt}; use super::*; @@ -250,46 +250,20 @@ mod tests { use tower_lsp::jsonrpc::{self, Request, Response}; use tower_lsp::LspService; - // Simple sway script used for testing LSP capabilites - const SWAY_PROGRAM: &str = r#"script; - -//use std::*; - -/// A simple Particle struct -struct Particle { - position: [u64; 3], - velocity: [u64; 3], - acceleration: [u64; 3], - mass: u64, -} - -impl Particle { - /// Creates a new Particle with the given position, velocity, acceleration, and mass - fn new(position: [u64; 3], velocity: [u64; 3], acceleration: [u64; 3], mass: u64) -> Particle { - Particle { - position: position, - velocity: velocity, - acceleration: acceleration, - mass: mass, - } - } -} + fn load_sway_example() -> (Url, String) { + let manifest_dir = env::current_dir() + .unwrap() + .parent() + .unwrap() + .join("examples/liquidity_pool"); + let src_path = manifest_dir.join("src/main.sw"); + let mut file = fs::File::open(&src_path).unwrap(); + let mut sway_program = String::new(); + file.read_to_string(&mut sway_program).unwrap(); -fn main() { - let position = [0, 0, 0]; - let velocity = [0, 1, 0]; - let acceleration = [1, 1, 0]; - let mass = 10; - let p = ~Particle::new(position, velocity, acceleration, mass); -} -"#; + let uri = Url::from_file_path(src_path).unwrap(); - fn load_test_sway_file(sway_file: &str) -> Url { - let file_name = "tmp_sway_test_file.sw"; - let dir = env::temp_dir().join(file_name); - let mut file = File::create(&dir).unwrap(); - file.write_all(sway_file.as_bytes()).unwrap(); - Url::from_file_path(dir.as_os_str().to_str().unwrap()).unwrap() + (uri, sway_program) } async fn initialize_request(service: &mut LspService) -> Request { @@ -440,10 +414,10 @@ fn main() { // ignore the "window/logMessage" notification: "Initializing the Sway Language Server" messages.next().await.unwrap(); - let uri = load_test_sway_file(SWAY_PROGRAM); + let (uri, sway_program) = load_sway_example(); // send "textDocument/didOpen" notification for `uri` - did_open_notification(&mut service, &uri, SWAY_PROGRAM).await; + did_open_notification(&mut service, &uri, &sway_program).await; // ignore the "textDocument/publishDiagnostics" notification messages.next().await.unwrap(); @@ -465,10 +439,10 @@ fn main() { // send "initialized" notification initialized_notification(&mut service).await; - let uri = load_test_sway_file(SWAY_PROGRAM); + let (uri, sway_program) = load_sway_example(); // send "textDocument/didOpen" notification for `uri` - did_open_notification(&mut service, &uri, SWAY_PROGRAM).await; + did_open_notification(&mut service, &uri, &sway_program).await; // send "textDocument/didClose" notification for `uri` did_close_notification(&mut service).await; diff --git a/sway-parse/Cargo.toml b/sway-parse/Cargo.toml index 0c867c4489a..004735fb86a 100644 --- a/sway-parse/Cargo.toml +++ b/sway-parse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sway-parse" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -12,7 +12,7 @@ description = "Sway's parser" extension-trait = "1.0.1" num-bigint = "0.4.3" num-traits = "0.2.14" -sway-types = { version = "0.16.1", path = "../sway-types" } +phf = { version = "0.10.1", features = ["macros"] } +sway-types = { version = "0.16.2", path = "../sway-types" } thiserror = "1.0" unicode-xid = "0.2.2" - diff --git a/sway-parse/src/attribute.rs b/sway-parse/src/attribute.rs index d3851ece214..851e911cede 100644 --- a/sway-parse/src/attribute.rs +++ b/sway-parse/src/attribute.rs @@ -71,7 +71,12 @@ impl Spanned for Attribute { impl Parse for Attribute { fn parse(parser: &mut Parser) -> ParseResult { - let name = parser.parse()?; + let storage = parser.take::(); + let name = if let Some(storage) = storage { + Ident::from(storage) + } else { + parser.parse()? + }; let args = Parens::try_parse(parser)?; Ok(Attribute { name, args }) } diff --git a/sway-parse/src/error.rs b/sway-parse/src/error.rs index d356c777c18..07cf0d0d5f0 100644 --- a/sway-parse/src/error.rs +++ b/sway-parse/src/error.rs @@ -64,6 +64,10 @@ pub enum ParseErrorKind { UnexpectedTokenAfterAttribute, #[error("Identifiers cannot begin with a double underscore, as that naming convention is reserved for compiler intrinsics.")] InvalidDoubleUnderscore, + #[error("Unexpected rest token, must be at the end of pattern.")] + UnexpectedRestPattern, + #[error("Identifiers cannot be a reserved keyword.")] + ReservedKeywordIdentifier, } #[derive(Debug, Error, Clone, PartialEq, Hash)] diff --git a/sway-parse/src/expr/asm.rs b/sway-parse/src/expr/asm.rs index 46ac7692b19..0805d29ab2d 100644 --- a/sway-parse/src/expr/asm.rs +++ b/sway-parse/src/expr/asm.rs @@ -121,14 +121,13 @@ impl ParseToEnd for AsmBlockContents { impl Parse for AsmImmediate { fn parse(parser: &mut Parser) -> ParseResult { let ident = parser.parse::()?; - let digits = match ident.as_str().strip_prefix('i') { - Some(digits) => digits, - None => return Err(parser.emit_error(ParseErrorKind::MalformedAsmImmediate)), - }; - let parsed = match BigUint::from_str(digits).ok() { - Some(parsed) => parsed, - None => return Err(parser.emit_error(ParseErrorKind::MalformedAsmImmediate)), - }; + let digits = ident + .as_str() + .strip_prefix('i') + .ok_or_else(|| parser.emit_error(ParseErrorKind::MalformedAsmImmediate))?; + let parsed = BigUint::from_str(digits) + .ok() + .ok_or_else(|| parser.emit_error(ParseErrorKind::MalformedAsmImmediate))?; Ok(AsmImmediate { span: ident.span(), parsed, diff --git a/sway-parse/src/expr/mod.rs b/sway-parse/src/expr/mod.rs index 67b322c418d..38864df33bd 100644 --- a/sway-parse/src/expr/mod.rs +++ b/sway-parse/src/expr/mod.rs @@ -1056,14 +1056,14 @@ fn parse_atom(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult { ); } if parser.peek::().is_some() { - let ident = parser.parse::()?; + let ident = parser.parse::()?; return Ok(Expr::Literal(Literal::Bool(LitBool { span: ident.span(), kind: LitBoolType::True, }))); } if parser.peek::().is_some() { - let ident = parser.parse::()?; + let ident = parser.parse::()?; return Ok(Expr::Literal(Literal::Bool(LitBool { span: ident.span(), kind: LitBoolType::False, diff --git a/sway-parse/src/intrinsics.rs b/sway-parse/src/intrinsics.rs index 7271d8adcc1..ac2640fb455 100644 --- a/sway-parse/src/intrinsics.rs +++ b/sway-parse/src/intrinsics.rs @@ -1,9 +1,25 @@ -#[derive(Eq, PartialEq)] +use std::fmt; + +#[derive(Eq, PartialEq, Debug, Clone)] pub enum Intrinsic { GetStorageKey, IsReferenceType, - SizeOf, + SizeOfType, SizeOfVal, + Eq, +} + +impl fmt::Display for Intrinsic { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s = match self { + Intrinsic::GetStorageKey => "get_storage_key", + Intrinsic::IsReferenceType => "is_reference_type", + Intrinsic::SizeOfType => "size_of", + Intrinsic::SizeOfVal => "size_of_val", + Intrinsic::Eq => "eq", + }; + write!(f, "{}", s) + } } impl Intrinsic { @@ -12,8 +28,9 @@ impl Intrinsic { Some(match raw { "__get_storage_key" => GetStorageKey, "__is_reference_type" => IsReferenceType, - "__size_of" => SizeOf, + "__size_of" => SizeOfType, "__size_of_val" => SizeOfVal, + "__eq" => Eq, _ => return None, }) } diff --git a/sway-parse/src/item/item_use.rs b/sway-parse/src/item/item_use.rs index fe7262a184e..5b4e4629fc7 100644 --- a/sway-parse/src/item/item_use.rs +++ b/sway-parse/src/item/item_use.rs @@ -51,10 +51,9 @@ impl Parse for UseTree { if let Some(star_token) = parser.take() { return Ok(UseTree::Glob { star_token }); } - let name = match parser.take() { - Some(name) => name, - None => return Err(parser.emit_error(ParseErrorKind::ExpectedImportNameGroupOrGlob)), - }; + let name = parser + .take() + .ok_or_else(|| parser.emit_error(ParseErrorKind::ExpectedImportNameGroupOrGlob))?; if let Some(as_token) = parser.take() { let alias = parser.parse()?; return Ok(UseTree::Rename { diff --git a/sway-parse/src/keywords.rs b/sway-parse/src/keywords.rs index c3789febea2..9cafb2fba1d 100644 --- a/sway-parse/src/keywords.rs +++ b/sway-parse/src/keywords.rs @@ -13,6 +13,18 @@ macro_rules! define_keyword ( } } + impl $ty_name { + pub fn ident(&self) -> Ident { + Ident::new(self.span()) + } + } + + impl From<$ty_name> for Ident { + fn from(o: $ty_name) -> Ident { + o.ident() + } + } + impl Peek for $ty_name { fn peek(peeker: Peeker<'_>) -> Option<$ty_name> { let ident = peeker.peek_ident().ok()?; @@ -119,6 +131,42 @@ macro_rules! define_token ( }; ); +// Keep this in sync with the list above defined by define_keyword! +pub(crate) const RESERVED_KEYWORDS: phf::Set<&'static str> = phf::phf_set! { + "script", + "contract", + "predicate", + "library", + "dep", + "pub", + "use", + "as", + "struct", + "enum", + "self", + "fn", + "trait", + "impl", + "for", + "abi", + "const", + "storage", + "str", + "asm", + "return", + "if", + "else", + "match", + "mut", + "let", + "while", + "where", + "ref", + "deref", + "true", + "false", +}; + define_token!(SemicolonToken, "a semicolon", [Semicolon], []); define_token!( ForwardSlashToken, @@ -165,6 +213,7 @@ define_token!( [GreaterThan, Equals] ); define_token!(DotToken, "`.`", [Dot], []); +define_token!(DoubleDotToken, "`..`", [Dot, Dot], [Dot]); define_token!(BangToken, "`!`", [Bang], [Equals]); define_token!(PercentToken, "`%`", [Percent], []); define_token!(AddToken, "`+`", [Add], [Equals]); diff --git a/sway-parse/src/lib.rs b/sway-parse/src/lib.rs index c453b005d01..a5b71a2bef7 100644 --- a/sway-parse/src/lib.rs +++ b/sway-parse/src/lib.rs @@ -17,7 +17,7 @@ pub mod pattern; mod priv_prelude; pub mod punctuated; pub mod statement; -mod token; +pub mod token; pub mod ty; pub mod where_clause; @@ -55,8 +55,8 @@ pub use crate::{ path::{PathExpr, PathExprSegment, PathType, PathTypeSegment, QualifiedPathRoot}, pattern::{Pattern, PatternStructField}, statement::{Statement, StatementLet}, - token::lex, token::LexError, + token::{lex, lex_commented}, ty::Ty, where_clause::{WhereBound, WhereClause}, }; diff --git a/sway-parse/src/literal.rs b/sway-parse/src/literal.rs index 9e911887c17..efe76f4954b 100644 --- a/sway-parse/src/literal.rs +++ b/sway-parse/src/literal.rs @@ -68,10 +68,9 @@ impl Peek for Literal { impl Parse for Literal { fn parse(parser: &mut Parser) -> ParseResult { - match parser.take() { - Some(literal) => Ok(literal), - None => Err(parser.emit_error(ParseErrorKind::ExpectedLiteral)), - } + parser + .take() + .ok_or_else(|| parser.emit_error(ParseErrorKind::ExpectedLiteral)) } } diff --git a/sway-parse/src/parse.rs b/sway-parse/src/parse.rs index d91023aeb9a..c3aaa5c4bb6 100644 --- a/sway-parse/src/parse.rs +++ b/sway-parse/src/parse.rs @@ -97,6 +97,13 @@ impl Parse for Ident { )); } + if !ident.is_raw_ident() && RESERVED_KEYWORDS.contains(ident_str) { + return Err(parser.emit_error_with_span( + ParseErrorKind::ReservedKeywordIdentifier, + ident.span(), + )); + } + Ok(ident) } None => Err(parser.emit_error(ParseErrorKind::ExpectedIdent)), diff --git a/sway-parse/src/path.rs b/sway-parse/src/path.rs index 60e73d809c1..6038c5a9b4e 100644 --- a/sway-parse/src/path.rs +++ b/sway-parse/src/path.rs @@ -90,10 +90,24 @@ impl Parse for PathExpr { } } +fn parse_ident(parser: &mut Parser) -> ParseResult { + if parser.peek::().is_some() { + let token = parser.parse::()?; + let ident: Ident = Ident::from(token); + Ok(ident) + } else if parser.peek::().is_some() { + let token = parser.parse::()?; + let ident: Ident = Ident::from(token); + Ok(ident) + } else { + parser.parse::() + } +} + impl Parse for PathExprSegment { fn parse(parser: &mut Parser) -> ParseResult { let fully_qualified = parser.take(); - let name = parser.parse()?; + let name = parse_ident(parser)?; let generics_opt = if parser .peek2::() .is_some() @@ -198,7 +212,7 @@ impl Parse for PathType { impl Parse for PathTypeSegment { fn parse(parser: &mut Parser) -> ParseResult { let fully_qualified = parser.take(); - let name = parser.parse()?; + let name = parse_ident(parser)?; let generics_opt = if parser.peek::().is_some() { let generics = parser.parse()?; Some((None, generics)) diff --git a/sway-parse/src/pattern.rs b/sway-parse/src/pattern.rs index c7d2ef3814f..c5f3f1e6f29 100644 --- a/sway-parse/src/pattern.rs +++ b/sway-parse/src/pattern.rs @@ -47,14 +47,14 @@ impl Parse for Pattern { return Ok(Pattern::Var { mutable, name }); } if parser.peek::().is_some() { - let ident = parser.parse::()?; + let ident = parser.parse::()?; return Ok(Pattern::Literal(Literal::Bool(LitBool { span: ident.span(), kind: LitBoolType::True, }))); } if parser.peek::().is_some() { - let ident = parser.parse::()?; + let ident = parser.parse::()?; return Ok(Pattern::Literal(Literal::Bool(LitBool { span: ident.span(), kind: LitBoolType::False, @@ -75,6 +75,19 @@ impl Parse for Pattern { return Ok(Pattern::Constructor { path, args }); } if let Some(fields) = Braces::try_parse(parser)? { + let inner_fields: &Punctuated<_, _> = fields.get(); + let rest_pattern = inner_fields + .value_separator_pairs + .iter() + .find(|(p, _)| matches!(p, PatternStructField::Rest { token: _ })); + + if let Some((rest_pattern, _)) = rest_pattern { + return Err(parser.emit_error_with_span( + ParseErrorKind::UnexpectedRestPattern, + rest_pattern.span(), + )); + } + return Ok(Pattern::Struct { path, fields }); } match path.try_into_ident() { @@ -88,22 +101,39 @@ impl Parse for Pattern { } #[derive(Clone, Debug)] -pub struct PatternStructField { - pub field_name: Ident, - pub pattern_opt: Option<(ColonToken, Box)>, +pub enum PatternStructField { + Rest { + token: DoubleDotToken, + }, + Field { + field_name: Ident, + pattern_opt: Option<(ColonToken, Box)>, + }, } impl Spanned for PatternStructField { fn span(&self) -> Span { - match &self.pattern_opt { - Some((_colon_token, pattern)) => Span::join(self.field_name.span(), pattern.span()), - None => self.field_name.span(), + use PatternStructField::*; + match &self { + Rest { token } => token.span(), + Field { + field_name, + pattern_opt, + } => match pattern_opt { + Some((_colon_token, pattern)) => Span::join(field_name.span(), pattern.span()), + None => field_name.span(), + }, } } } impl Parse for PatternStructField { fn parse(parser: &mut Parser) -> ParseResult { + if parser.peek::().is_some() { + let token = parser.parse()?; + return Ok(PatternStructField::Rest { token }); + } + let field_name = parser.parse()?; let pattern_opt = match parser.take() { Some(colon_token) => { @@ -112,7 +142,7 @@ impl Parse for PatternStructField { } None => None, }; - Ok(PatternStructField { + Ok(PatternStructField::Field { field_name, pattern_opt, }) diff --git a/sway-parse/src/token.rs b/sway-parse/src/token.rs index 972ce4dd4f8..3b63a750126 100644 --- a/sway-parse/src/token.rs +++ b/sway-parse/src/token.rs @@ -69,13 +69,16 @@ impl PunctKind { } #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)] -pub struct Group { +pub struct GenericGroup { pub delimiter: Delimiter, - pub token_stream: TokenStream, + pub token_stream: T, pub span: Span, } -impl Spanned for Group { +pub type Group = GenericGroup; +pub type CommentedGroup = GenericGroup; + +impl Spanned for GenericGroup { fn span(&self) -> Span { self.span.clone() } @@ -96,33 +99,122 @@ impl Delimiter { Delimiter::Bracket => '[', } } + pub fn as_close_char(self) -> char { + match self { + Delimiter::Parenthesis => ')', + Delimiter::Brace => '}', + Delimiter::Bracket => ']', + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)] +pub struct Comment { + pub span: Span, +} + +impl Spanned for Comment { + fn span(&self) -> Span { + self.span.clone() + } } +/// Allows for generalizing over commented and uncommented token streams. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)] -pub enum TokenTree { +pub enum GenericTokenTree { Punct(Punct), Ident(Ident), - Group(Group), + Group(GenericGroup), Literal(Literal), } -impl Spanned for TokenTree { +pub type TokenTree = GenericTokenTree; +pub type CommentedTree = GenericTokenTree; + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)] +pub enum CommentedTokenTree { + Comment(Comment), + Tree(CommentedTree), +} + +impl CommentedGroup { + pub fn strip_comments(self) -> Group { + Group { + delimiter: self.delimiter, + token_stream: self.token_stream.strip_comments(), + span: self.span, + } + } +} + +impl Spanned for GenericTokenTree { + fn span(&self) -> Span { + match self { + Self::Punct(punct) => punct.span(), + Self::Ident(ident) => ident.span(), + Self::Group(group) => group.span(), + Self::Literal(literal) => literal.span(), + } + } +} + +impl Spanned for CommentedTokenTree { fn span(&self) -> Span { match self { - TokenTree::Punct(punct) => punct.span(), - TokenTree::Ident(ident) => ident.span(), - TokenTree::Group(group) => group.span(), - TokenTree::Literal(literal) => literal.span(), + Self::Comment(cmt) => cmt.span(), + Self::Tree(tt) => tt.span(), } } } +impl From for GenericTokenTree { + fn from(punct: Punct) -> Self { + Self::Punct(punct) + } +} + +impl From for GenericTokenTree { + fn from(ident: Ident) -> Self { + Self::Ident(ident) + } +} + +impl From> for GenericTokenTree { + fn from(group: GenericGroup) -> Self { + Self::Group(group) + } +} + +impl From for GenericTokenTree { + fn from(lit: Literal) -> Self { + Self::Literal(lit) + } +} + +impl From for CommentedTokenTree { + fn from(comment: Comment) -> Self { + Self::Comment(comment) + } +} + +impl From for CommentedTokenTree { + fn from(tree: CommentedTree) -> Self { + Self::Tree(tree) + } +} + #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)] pub struct TokenStream { token_trees: Vec, full_span: Span, } +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)] +pub struct CommentedTokenStream { + token_trees: Vec, + full_span: Span, +} + #[derive(Error, Debug, Clone, PartialEq, Eq, PartialOrd, Hash)] #[error("{}", kind)] pub struct LexError { @@ -270,14 +362,23 @@ pub fn lex( end: usize, path: Option>, ) -> Result { + lex_commented(src, start, end, path).map(|stream| stream.strip_comments()) +} + +pub fn lex_commented( + src: &Arc, + start: usize, + end: usize, + path: Option>, +) -> Result { let mut char_indices = CharIndicesInner { src: &src[..end], position: start, } .peekable(); let mut parent_token_trees = Vec::new(); - let mut token_trees = Vec::new(); - while let Some((index, character)) = char_indices.next() { + let mut token_trees: Vec = Vec::new(); + while let Some((mut index, mut character)) = char_indices.next() { if character.is_whitespace() { continue; } @@ -285,8 +386,11 @@ pub fn lex( match char_indices.peek() { Some((_, '/')) => { let _ = char_indices.next(); - for (_, character) in char_indices.by_ref() { + for (end, character) in char_indices.by_ref() { if character == '\n' { + let span = Span::new(src.clone(), index, end, path.clone()).unwrap(); + let comment = Comment { span }; + token_trees.push(comment.into()); break; } } @@ -294,42 +398,33 @@ pub fn lex( Some((_, '*')) => { let _ = char_indices.next(); let mut unclosed_indices = vec![index]; + + let unclosed_multiline_comment = |unclosed_indices: Vec<_>| { + let span = Span::new( + src.clone(), + *unclosed_indices.last().unwrap(), + src.len(), + path.clone(), + ) + .unwrap(); + LexError { + kind: LexErrorKind::UnclosedMultilineComment { unclosed_indices }, + span, + } + }; + loop { match char_indices.next() { - None => { - let span = Span::new( - src.clone(), - *unclosed_indices.last().unwrap(), - src.len(), - path.clone(), - ) - .unwrap(); - return Err(LexError { - kind: LexErrorKind::UnclosedMultilineComment { - unclosed_indices, - }, - span, - }); - } + None => return Err(unclosed_multiline_comment(unclosed_indices)), Some((_, '*')) => match char_indices.next() { - None => { - let span = Span::new( - src.clone(), - *unclosed_indices.last().unwrap(), - src.len(), - path.clone(), - ) - .unwrap(); - return Err(LexError { - kind: LexErrorKind::UnclosedMultilineComment { - unclosed_indices, - }, - span, - }); - } - Some((_, '/')) => { + None => return Err(unclosed_multiline_comment(unclosed_indices)), + Some((end, '/')) => { let _ = char_indices.next(); - unclosed_indices.pop(); + let start = unclosed_indices.pop().unwrap(); + let span = + Span::new(src.clone(), start, end, path.clone()).unwrap(); + let comment = Comment { span }; + token_trees.push(comment.into()); if unclosed_indices.is_empty() { break; } @@ -337,21 +432,7 @@ pub fn lex( Some((_, _)) => (), }, Some((next_index, '/')) => match char_indices.next() { - None => { - let span = Span::new( - src.clone(), - *unclosed_indices.last().unwrap(), - src.len(), - path.clone(), - ) - .unwrap(); - return Err(LexError { - kind: LexErrorKind::UnclosedMultilineComment { - unclosed_indices, - }, - span, - }); - } + None => return Err(unclosed_multiline_comment(unclosed_indices)), Some((_, '*')) => { unclosed_indices.push(next_index); } @@ -373,7 +454,7 @@ pub fn lex( spacing, span, }; - token_trees.push(TokenTree::Punct(punct)); + token_trees.push(CommentedTokenTree::Tree(punct.into())); } None => { let span = Span::new(src.clone(), start, end, path.clone()).unwrap(); @@ -382,12 +463,22 @@ pub fn lex( spacing: Spacing::Alone, span, }; - token_trees.push(TokenTree::Punct(punct)); + token_trees.push(CommentedTokenTree::Tree(punct.into())); } } continue; } if character.is_xid_start() || character == '_' { + let is_raw_ident = character == 'r' && matches!(char_indices.peek(), Some((_, '#'))); + if is_raw_ident { + char_indices.next(); + if let Some((_, next_character)) = char_indices.peek() { + character = *next_character; + if let Some((next_index, _)) = char_indices.next() { + index = next_index; + } + } + } let is_single_underscore = character == '_' && match char_indices.peek() { Some((_, next_character)) => !next_character.is_xid_continue(), @@ -401,8 +492,8 @@ pub fn lex( let _ = char_indices.next(); } let span = span_until(src, index, &mut char_indices, &path); - let ident = Ident::new(span); - token_trees.push(TokenTree::Ident(ident)); + let ident = Ident::new_with_raw(span, is_raw_ident); + token_trees.push(CommentedTokenTree::Tree(ident.into())); continue; } } @@ -450,15 +541,15 @@ pub fn lex( let start_index = open_index + open_delimiter.as_open_char().len_utf8(); let full_span = Span::new(src.clone(), start_index, index, path.clone()).unwrap(); - let group = Group { - token_stream: TokenStream { + let group = CommentedGroup { + token_stream: CommentedTokenStream { token_trees: parent, full_span, }, delimiter: close_delimiter, span: span_until(src, open_index, &mut char_indices, &path), }; - token_trees.push(TokenTree::Group(group)); + token_trees.push(CommentedTokenTree::Tree(group.into())); } } continue; @@ -506,7 +597,7 @@ pub fn lex( } let span = span_until(src, index, &mut char_indices, &path); let literal = Literal::String(LitString { span, parsed }); - token_trees.push(TokenTree::Literal(literal)); + token_trees.push(CommentedTokenTree::Tree(literal.into())); continue; } if character == '\'' { @@ -558,7 +649,7 @@ pub fn lex( } let span = span_until(src, index, &mut char_indices, &path); let literal = Literal::Char(LitChar { span, parsed }); - token_trees.push(TokenTree::Literal(literal)); + token_trees.push(CommentedTokenTree::Tree(literal.into())); continue; } if let Some(digit) = character.to_digit(10) { @@ -738,7 +829,7 @@ pub fn lex( parsed: big_uint, ty_opt, }); - token_trees.push(TokenTree::Literal(literal)); + token_trees.push(CommentedTokenTree::Tree(literal.into())); continue; } if let Some(kind) = character.as_punct_kind() { @@ -754,7 +845,7 @@ pub fn lex( spacing, span, }; - token_trees.push(TokenTree::Punct(punct)); + token_trees.push(CommentedTokenTree::Tree(punct.into())); continue; } return Err(LexError { @@ -787,7 +878,7 @@ pub fn lex( }); } let full_span = Span::new(src.clone(), start, end, path).unwrap(); - let token_stream = TokenStream { + let token_stream = CommentedTokenStream { token_trees, full_span, }; @@ -966,3 +1057,91 @@ impl Spanned for TokenStream { self.full_span.clone() } } + +impl CommentedTokenTree { + pub fn strip_comments(self) -> Option { + let commented_tt = match self { + Self::Comment(_) => return None, + Self::Tree(commented_tt) => commented_tt, + }; + let tt = match commented_tt { + CommentedTree::Punct(punct) => punct.into(), + CommentedTree::Ident(ident) => ident.into(), + CommentedTree::Group(group) => group.strip_comments().into(), + CommentedTree::Literal(lit) => lit.into(), + }; + Some(tt) + } +} + +impl CommentedTokenStream { + pub fn token_trees(&self) -> &[CommentedTokenTree] { + &self.token_trees + } + + pub fn strip_comments(self) -> TokenStream { + let token_trees = self + .token_trees + .into_iter() + .filter_map(|tree| tree.strip_comments()) + .collect(); + TokenStream { + token_trees, + full_span: self.full_span, + } + } +} + +impl Spanned for CommentedTokenStream { + fn span(&self) -> Span { + self.full_span.clone() + } +} + +#[cfg(test)] +mod tests { + use super::{lex_commented, CommentedTokenTree, CommentedTree}; + use crate::priv_prelude::*; + use std::sync::Arc; + + #[test] + fn lex_commented_token_stream() { + let input = r#" + // Single-line comment. + struct Foo { + /* multi- + * line- + * comment */ + bar: i32, + } + "#; + let start = 0; + let end = input.len(); + let path = None; + let stream = lex_commented(&Arc::from(input), start, end, path).unwrap(); + let mut tts = stream.token_trees().iter(); + assert_eq!( + tts.next().unwrap().span().as_str(), + "// Single-line comment." + ); + assert_eq!(tts.next().unwrap().span().as_str(), "struct"); + assert_eq!(tts.next().unwrap().span().as_str(), "Foo"); + { + let group = match tts.next() { + Some(CommentedTokenTree::Tree(CommentedTree::Group(group))) => group, + _ => panic!("expected group"), + }; + let mut tts = group.token_stream.token_trees().iter(); + assert_eq!( + tts.next().unwrap().span().as_str(), + "/* multi-\n * line-\n * comment *", + ); + assert_eq!(tts.next().unwrap().span().as_str(), "bar"); + assert_eq!(tts.next().unwrap().span().as_str(), ":"); + assert_eq!(tts.next().unwrap().span().as_str(), "i32"); + assert_eq!(tts.next().unwrap().span().as_str(), ","); + assert!(tts.next().is_none()); + } + assert!(tts.next().is_none()); + } +} diff --git a/sway-types/Cargo.toml b/sway-types/Cargo.toml index 7ad4ed637da..005fa01ad9c 100644 --- a/sway-types/Cargo.toml +++ b/sway-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sway-types" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" @@ -11,6 +11,6 @@ description = "Sway core types." [dependencies] fuel-asm = "0.5" fuel-crypto = "0.5" -fuel-tx = "0.12" +fuel-tx = "0.13" lazy_static = "1.4" serde = { version = "1.0", features = ["derive"] } diff --git a/sway-types/src/ident.rs b/sway-types/src/ident.rs index fda2a7c466e..c0382ab21ac 100644 --- a/sway-types/src/ident.rs +++ b/sway-types/src/ident.rs @@ -11,6 +11,7 @@ use std::{ pub struct Ident { name_override_opt: Option<&'static str>, span: Span, + is_raw_ident: bool, } // custom implementation of Hash so that namespacing isn't reliant on the span itself, which will @@ -61,11 +62,25 @@ impl Ident { } } + pub fn is_raw_ident(&self) -> bool { + self.is_raw_ident + } + pub fn new(span: Span) -> Ident { let span = span.trim(); Ident { name_override_opt: None, span, + is_raw_ident: false, + } + } + + pub fn new_with_raw(span: Span, is_raw_ident: bool) -> Ident { + let span = span.trim(); + Ident { + name_override_opt: None, + span, + is_raw_ident, } } @@ -73,6 +88,7 @@ impl Ident { Ident { name_override_opt: Some(name_override), span, + is_raw_ident: false, } } @@ -80,6 +96,7 @@ impl Ident { Ident { name_override_opt: Some(name), span: Span::dummy(), + is_raw_ident: false, } } } diff --git a/sway-types/src/span.rs b/sway-types/src/span.rs index 6ac02a066f2..bae29f8a5fb 100644 --- a/sway-types/src/span.rs +++ b/sway-types/src/span.rs @@ -96,6 +96,11 @@ impl Span { }) } + pub fn from_string(source: String) -> Span { + let len = source.len(); + Span::new(Arc::from(source), 0, len, None).unwrap() + } + pub fn src(&self) -> &Arc { &self.src } @@ -156,12 +161,6 @@ impl Span { /// This panics if the spans are not from the same file. This should /// only be used on spans that are actually next to each other. pub fn join(s1: Span, s2: Span) -> Span { - // FIXME(canndrew): This is horrifying. Where did it come from and why is it needed? - // FIXME(sezna): I don't know, but I'm on the blame for it. Ah. We should remove this. - if s1.as_str() == "core" { - return s2; - } - assert!( Arc::ptr_eq(&s1.src, &s2.src) && s1.path == s2.path, "Spans from different files cannot be joined.", diff --git a/sway-utils/Cargo.toml b/sway-utils/Cargo.toml index 7db1685c9db..9571d9e5a07 100644 --- a/sway-utils/Cargo.toml +++ b/sway-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sway-utils" -version = "0.16.1" +version = "0.16.2" authors = ["Fuel Labs "] edition = "2021" homepage = "https://fuel.network/" diff --git a/test-sig-gen-util/Cargo.toml b/test-sig-gen-util/Cargo.toml index c8a176f8bea..677818e1ae1 100644 --- a/test-sig-gen-util/Cargo.toml +++ b/test-sig-gen-util/Cargo.toml @@ -7,9 +7,9 @@ publish = false [dependencies] anyhow = "1.0.39" fuel-crypto = "0.5" -fuel-tx = "0.12" +fuel-tx = "0.13" fuel-types = { version = "0.5", default-features = false } -fuel-vm = "0.11" +fuel-vm = "0.12" hex = "0.4" secp256k1 = { version = "0.20", features = ["recovery"] } sha3 = "0.10" diff --git a/test/Cargo.toml b/test/Cargo.toml index 190d3e68921..f6758a9b495 100644 --- a/test/Cargo.toml +++ b/test/Cargo.toml @@ -7,14 +7,17 @@ publish = false [dependencies] anyhow = "1.0.41" -assert_matches = "1.5.0" +filecheck = "0.5" forc = { path = "../forc", features = ["test"], default-features = false } +forc-pkg = { path = "../forc-pkg" } forc-util = { path = "../forc-util" } fuel-asm = "0.5" -fuel-tx = "0.12" -fuel-vm = { version = "0.11", features = ["random"] } +fuel-tx = "0.13" +fuel-vm = { version = "0.12", features = ["random"] } +gag = "1.0" rand = "0.8" regex = "1" serde_json = "1.0.73" tokio = "1.12" +toml = "0.5" tracing = "0.1" diff --git a/test/src/e2e_vm_tests/harness.rs b/test/src/e2e_vm_tests/harness.rs index 023d89105a9..c1e5e83fc5d 100644 --- a/test/src/e2e_vm_tests/harness.rs +++ b/test/src/e2e_vm_tests/harness.rs @@ -1,12 +1,9 @@ use anyhow::{bail, Result}; -use forc::test::{ - forc_abi_json, forc_build, forc_deploy, forc_run, BuildCommand, DeployCommand, JsonAbiCommand, - RunCommand, -}; +use forc::test::{forc_build, forc_deploy, forc_run, BuildCommand, DeployCommand, RunCommand}; +use forc_pkg::Compiled; use fuel_tx::Transaction; use fuel_vm::interpreter::Interpreter; use fuel_vm::prelude::*; -use serde_json::Value; use std::fs; pub(crate) fn deploy_contract(file_name: &str, locked: bool) -> ContractId { @@ -67,12 +64,12 @@ pub(crate) fn runs_on_node( /// Very basic check that code does indeed run in the VM. /// `true` if it does, `false` if not. -pub(crate) fn runs_in_vm(file_name: &str, locked: bool) -> ProgramState { +pub(crate) fn runs_in_vm(file_name: &str, locked: bool) -> (ProgramState, Compiled) { let storage = MemoryStorage::default(); let script = compile_to_bytes(file_name, locked).unwrap(); let gas_price = 10; - let gas_limit = fuel_tx::default_parameters::MAX_GAS_PER_TX; + let gas_limit = fuel_tx::ConsensusParameters::DEFAULT.max_gas_per_tx; let byte_price = 0; let maturity = 0; let script_data = vec![]; @@ -84,7 +81,7 @@ pub(crate) fn runs_in_vm(file_name: &str, locked: bool) -> ProgramState { gas_limit, byte_price, maturity, - script, + script.bytecode.clone(), script_data, inputs, outputs, @@ -95,25 +92,54 @@ pub(crate) fn runs_in_vm(file_name: &str, locked: bool) -> ProgramState { .validate(block_height, &Default::default()) .unwrap(); let mut i = Interpreter::with_storage(storage, Default::default()); - *i.transact(tx_to_test).unwrap().state() + (*i.transact(tx_to_test).unwrap().state(), script) } -/// Panics if code _does_ compile, used for test cases where the source -/// code should have been rejected by the compiler. -pub(crate) fn does_not_compile(file_name: &str, locked: bool) { - assert!( - compile_to_bytes(file_name, locked).is_err(), - "{} should not have compiled.", - file_name, - ) +/// Returns Err(()) if code _does_ compile, used for test cases where the source +/// code should have been rejected by the compiler. When it fails to compile the +/// captured stdout is returned. +pub(crate) fn does_not_compile(file_name: &str, locked: bool) -> Result { + use std::io::Read; + + tracing::info!(" Compiling {}", file_name); + + // Capture stdout to a buffer, compile the test and save stdout to a string. + let mut buf = gag::BufferRedirect::stdout().unwrap(); + let result = compile_to_bytes_verbose(file_name, locked, true); + let mut output = String::new(); + buf.read_to_string(&mut output).unwrap(); + drop(buf); + + // If verbosity is requested then print it out. + if get_test_config_from_env() { + tracing::info!("{output}"); + } + + // Invert the result; if it succeeds then return an Err. + match result { + Ok(_) => Err(()), + Err(e) => { + // Capture the result of the compilation (i.e., any errors Forc produces) and append to + // the stdout from the compiler. + output.push_str(&format!("\n{e}")); + Ok(output) + } + } } /// Returns `true` if a file compiled without any errors or warnings, /// and `false` if it did not. -pub(crate) fn compile_to_bytes(file_name: &str, locked: bool) -> Result> { +pub(crate) fn compile_to_bytes(file_name: &str, locked: bool) -> Result { + compile_to_bytes_verbose(file_name, locked, get_test_config_from_env()) +} + +pub(crate) fn compile_to_bytes_verbose( + file_name: &str, + locked: bool, + verbose: bool, +) -> Result { tracing::info!(" Compiling {}", file_name); let manifest_dir = env!("CARGO_MANIFEST_DIR"); - let verbose = get_test_config_from_env(); forc_build::build(BuildCommand { path: Some(format!( "{}/src/e2e_vm_tests/test_programs/{}", @@ -123,11 +149,10 @@ pub(crate) fn compile_to_bytes(file_name: &str, locked: bool) -> Result> silent_mode: !verbose, ..Default::default() }) - .map(|compiled| compiled.bytecode) } -pub(crate) fn test_json_abi(file_name: &str) -> Result<()> { - let _compiled_res = compile_to_json_abi(file_name)?; +pub(crate) fn test_json_abi(file_name: &str, compiled: &Compiled) -> Result<()> { + emit_json_abi(file_name, compiled)?; let manifest_dir = env!("CARGO_MANIFEST_DIR"); let oracle_path = format!( "{}/src/e2e_vm_tests/test_programs/{}/{}", @@ -153,21 +178,59 @@ pub(crate) fn test_json_abi(file_name: &str) -> Result<()> { Ok(()) } -fn compile_to_json_abi(file_name: &str) -> Result { +fn emit_json_abi(file_name: &str, compiled: &Compiled) -> Result<()> { tracing::info!(" ABI gen {}", file_name); + let json_abi = serde_json::json!(compiled.json_abi); let manifest_dir = env!("CARGO_MANIFEST_DIR"); - forc_abi_json::build(JsonAbiCommand { - path: Some(format!( - "{}/src/e2e_vm_tests/test_programs/{}", - manifest_dir, file_name - )), - json_outfile: Some(format!( - "{}/src/e2e_vm_tests/test_programs/{}/{}", - manifest_dir, file_name, "json_abi_output.json" - )), - silent_mode: true, - ..Default::default() - }) + let file = std::fs::File::create(format!( + "{}/src/e2e_vm_tests/test_programs/{}/{}", + manifest_dir, file_name, "json_abi_output.json" + )) + .map_err(|e| e)?; + let res = serde_json::to_writer_pretty(&file, &json_abi); + res.map_err(|e| e)?; + Ok(()) +} + +pub(crate) fn test_json_storage_slots(file_name: &str, compiled: &Compiled) -> Result<()> { + emit_json_storage_slots(file_name, compiled)?; + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let oracle_path = format!( + "{}/src/e2e_vm_tests/test_programs/{}/{}", + manifest_dir, file_name, "json_storage_slots_oracle.json" + ); + let output_path = format!( + "{}/src/e2e_vm_tests/test_programs/{}/{}", + manifest_dir, file_name, "json_storage_slots_output.json" + ); + if fs::metadata(oracle_path.clone()).is_err() { + bail!("JSON storage slots oracle file does not exist for this test."); + } + if fs::metadata(output_path.clone()).is_err() { + bail!("JSON storage slots output file does not exist for this test."); + } + let oracle_contents = + fs::read_to_string(oracle_path).expect("Something went wrong reading the file."); + let output_contents = + fs::read_to_string(output_path).expect("Something went wrong reading the file."); + if oracle_contents != output_contents { + bail!("Mismatched storage slots JSON output."); + } + Ok(()) +} + +fn emit_json_storage_slots(file_name: &str, compiled: &Compiled) -> Result<()> { + tracing::info!(" storage slots JSON gen {}", file_name); + let json_storage_slots = serde_json::json!(compiled.storage_slots); + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let file = std::fs::File::create(format!( + "{}/src/e2e_vm_tests/test_programs/{}/{}", + manifest_dir, file_name, "json_storage_slots_output.json" + )) + .map_err(|e| e)?; + let res = serde_json::to_writer_pretty(&file, &json_storage_slots); + res.map_err(|e| e)?; + Ok(()) } fn get_test_config_from_env() -> bool { diff --git a/test/src/e2e_vm_tests/mod.rs b/test/src/e2e_vm_tests/mod.rs index b528ad411cb..4df29596d7d 100644 --- a/test/src/e2e_vm_tests/mod.rs +++ b/test/src/e2e_vm_tests/mod.rs @@ -1,730 +1,396 @@ +// Please take a look in test_programs/README.md for details on how these tests work. + mod harness; -use assert_matches::assert_matches; + use forc_util::init_tracing_subscriber; use fuel_vm::prelude::*; + +use std::{ + collections::HashMap, + path::{Path, PathBuf}, +}; + +#[derive(PartialEq)] +enum TestCategory { + Compiles, + FailsToCompile, + Runs, + RunsWithContract, + Disabled, +} + +#[derive(Debug)] +enum TestResult { + Result(Word), + Return(u64), + ReturnData(Bytes32), + Revert(u64), +} + +struct TestDescription { + name: String, + category: TestCategory, + expected_result: Option, + contract_paths: Vec, + validate_abi: bool, + validate_storage_slots: bool, + checker: filecheck::Checker, +} + pub fn run(locked: bool, filter_regex: Option) { init_tracing_subscriber(); - let filter = |name| { - filter_regex + + let configured_tests = discover_test_configs().unwrap_or_else(|e| { + panic!("Discovering tests {e}"); + }); + + let total_number_of_tests = configured_tests.len(); + let mut number_of_tests_executed = 0; + let mut number_of_disabled_tests = 0; + + let mut deployed_contracts = HashMap::::new(); + + for TestDescription { + name, + category, + expected_result, + contract_paths, + validate_abi, + validate_storage_slots, + checker, + } in configured_tests + { + if !filter_regex .as_ref() - .map(|regex| regex.is_match(name)) + .map(|regex| regex.is_match(&name)) .unwrap_or(true) - }; + { + continue; + } - // Predicate programs that should successfully compile and terminate - // with some known state. Note that if you are adding a non-predicate, it may pass by mistake. - // Please add non-predicates to `positive_project_names_with_abi`. - let positive_project_names_no_abi = vec![( - "should_pass/language/basic_predicate", - ProgramState::Return(1), - )]; - - let mut number_of_tests_run = - positive_project_names_no_abi - .iter() - .fold(0, |acc, (name, res)| { - if filter(name) { - assert_eq!(crate::e2e_vm_tests::harness::runs_in_vm(name, locked), *res); - acc + 1 - } else { - acc + match category { + TestCategory::Runs => { + let res = match expected_result { + Some(TestResult::Return(v)) => ProgramState::Return(v), + Some(TestResult::ReturnData(bytes)) => ProgramState::ReturnData(bytes), + Some(TestResult::Revert(v)) => ProgramState::Revert(v), + + _ => panic!( + "For {name}:\n\ + Invalid expected result for a 'runs' test: {expected_result:?}." + ), + }; + + let result = crate::e2e_vm_tests::harness::runs_in_vm(&name, locked); + assert_eq!(result.0, res); + if validate_abi { + assert!(crate::e2e_vm_tests::harness::test_json_abi(&name, &result.1).is_ok()); } - }); - - // Programs that should successfully compile, include abi and terminate - // with some known state. Note that if a predicate is included - // it will be rejected during assertion. Please move it to - // `positive_project_names_no_abi` above. - let positive_project_names_with_abi = vec![ - ( - "should_pass/forc/dependency_package_field", - ProgramState::Return(0), - ), - ( - "should_pass/language/asm_expr_basic", - ProgramState::Return(6), - ), - ( - "should_pass/language/basic_func_decl", - ProgramState::Return(1), // 1 == true - ), - ( - "should_pass/language/builtin_type_method_call", - ProgramState::Return(3), - ), - ("should_pass/language/dependencies", ProgramState::Return(0)), // 0 == false - ( - "should_pass/language/if_elseif_enum", - ProgramState::Return(10), - ), - ( - "should_pass/language/tuple_types", - ProgramState::Return(123), - ), - ( - "should_pass/language/out_of_order_decl", - ProgramState::Return(1), - ), - ( - "should_pass/language/struct_field_reassignment", - ProgramState::Return(0), - ), - ( - "should_pass/language/tuple_field_reassignment", - ProgramState::Return(320), - ), - ( - "should_pass/language/enum_in_fn_decl", - ProgramState::Return(255), - ), - ( - "should_pass/language/main_returns_unit", - ProgramState::Return(0), - ), - ( - "should_pass/language/unary_not_basic", - ProgramState::Return(1), // 1 == true - ), - ( - "should_pass/language/unary_not_basic_2", - ProgramState::Return(1), // 1 == true - ), - ( - "should_pass/language/fix_opcode_bug", - ProgramState::Return(30), - ), - ( - "should_pass/language/retd_b256", - ProgramState::ReturnData(Bytes32::from([ - 102, 104, 122, 173, 248, 98, 189, 119, 108, 143, 193, 139, 142, 159, 142, 32, 8, - 151, 20, 133, 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, 41, 37, - ])), - ), - ( - "should_pass/language/retd_struct", - ProgramState::ReturnData(Bytes32::from([ - 251, 57, 24, 241, 63, 94, 17, 102, 252, 182, 8, 110, 140, 105, 102, 105, 138, 202, - 155, 39, 97, 32, 94, 129, 141, 144, 190, 142, 33, 32, 33, 75, - ])), - ), - ( - "should_pass/language/op_precedence", - ProgramState::Return(0), - ), - ( - "should_pass/language/asm_without_return", - ProgramState::Return(0), - ), - ( - "should_pass/language/b256_bad_jumps", - ProgramState::Return(1), - ), - ( - "should_pass/language/b256_bitwise_ops", - ProgramState::Return(1), - ), - ("should_pass/language/b256_ops", ProgramState::Return(100)), - ( - "should_pass/language/struct_field_access", - ProgramState::Return(43), - ), - ("should_pass/language/bool_and_or", ProgramState::Return(42)), - ("should_pass/language/eq_and_neq", ProgramState::Return(1)), - ( - "should_pass/language/local_impl_for_ord", - ProgramState::Return(1), // true - ), - ("should_pass/language/const_decl", ProgramState::Return(100)), - ( - "should_pass/language/const_decl_in_library", - ProgramState::Return(1), // true - ), - ( - "should_pass/language/aliased_imports", - ProgramState::Return(42), - ), - ( - "should_pass/language/empty_method_initializer", - ProgramState::Return(1), // true - ), - ( - "should_pass/stdlib/b512_struct_alignment", - ProgramState::Return(1), // true - ), - ( - "should_pass/stdlib/contract_id_type", - ProgramState::Return(1), - ), // true - ("should_pass/stdlib/evm_ecr", ProgramState::Return(1)), // true - ( - "should_pass/stdlib/exponentiation_test", - ProgramState::Return(1), - ), // true - ("should_pass/stdlib/ge_test", ProgramState::Return(1)), // true - ("should_pass/stdlib/identity_eq", ProgramState::Return(1)), // true - ("should_pass/stdlib/intrinsics", ProgramState::Return(1)), // true - ("should_pass/stdlib/option", ProgramState::Return(1)), // true - ("should_pass/stdlib/require", ProgramState::Return(1)), // true - ("should_pass/stdlib/result", ProgramState::Return(1)), // true - ("should_pass/stdlib/u128_test", ProgramState::Return(1)), // true - ("should_pass/stdlib/u128_div_test", ProgramState::Return(1)), // true - ("should_pass/stdlib/u128_mul_test", ProgramState::Return(1)), // true - ("should_pass/stdlib/alloc", ProgramState::Return(1)), // true - ("should_pass/stdlib/mem", ProgramState::Return(1)), // true - ( - "should_pass/language/generic_structs", - ProgramState::Return(1), // true - ), - ( - "should_pass/language/generic_functions", - ProgramState::Return(1), // true - ), - ("should_pass/language/generic_enum", ProgramState::Return(1)), // true - ( - "should_pass/language/numeric_constants", - ProgramState::Return(1), - ), // true - ("should_pass/language/u64_ops", ProgramState::Return(1)), // true - ( - "should_pass/language/import_method_from_other_file", - ProgramState::Return(10), // true - ), - ( - "should_pass/stdlib/ec_recover_test", - ProgramState::Return(1), // true - ), - ("should_pass/stdlib/address_test", ProgramState::Return(1)), // true - ( - "should_pass/language/generic_struct", - ProgramState::Return(1), // true - ), - ( - "should_pass/language/zero_field_types", - ProgramState::Return(10), // true - ), - ("should_pass/stdlib/assert_test", ProgramState::Return(1)), // true - ( - "should_pass/language/match_expressions", - ProgramState::Return(42), - ), - ("should_pass/language/array_basics", ProgramState::Return(1)), // true - // Disabled, pending decision on runtime OOB checks. ("array_dynamic_oob", ProgramState::Revert(1)), - ( - "should_pass/language/abort_control_flow_good", - ProgramState::Revert(42), - ), - ( - "should_pass/language/array_generics", - ProgramState::Return(1), // true - ), - ( - "should_pass/language/match_expressions_structs", - ProgramState::Return(4), - ), - ("should_pass/stdlib/b512_test", ProgramState::Return(1)), // true - ("should_pass/stdlib/block_height", ProgramState::Return(1)), // true - ("should_pass/stdlib/vec", ProgramState::Return(1)), // true - ( - "should_pass/language/trait_override_bug", - ProgramState::Return(7), - ), - ( - "should_pass/language/if_implicit_unit", - ProgramState::Return(0), - ), - ( - "should_pass/language/modulo_uint_test", - ProgramState::Return(1), // true - ), - ( - "should_pass/language/trait_import_with_star", - ProgramState::Return(0), - ), - ( - "should_pass/language/tuple_desugaring", - ProgramState::Return(9), - ), - ( - "should_pass/language/multi_item_import", - ProgramState::Return(0), // false - ), - ( - "should_pass/language/use_full_path_names", - ProgramState::Return(1), - ), - ( - "should_pass/language/tuple_indexing", - ProgramState::Return(1), - ), - ( - "should_pass/language/tuple_access", - ProgramState::Return(42), - ), - ( - "should_pass/language/funcs_with_generic_types", - ProgramState::Return(1), // true - ), - ( - "should_pass/language/enum_if_let", - ProgramState::Return(143), - ), - ( - "should_pass/language/enum_destructuring", - ProgramState::Return(15), - ), - ( - "should_pass/language/enum_if_let_large_type", - ProgramState::Return(15), - ), - ( - "should_pass/language/enum_type_inference", - ProgramState::Return(5), - ), - ("should_pass/language/size_of", ProgramState::Return(1)), - ("should_pass/language/supertraits", ProgramState::Return(1)), - ( - "should_pass/language/new_allocator_test", - ProgramState::Return(42), // true - ), - ( - "should_pass/language/chained_if_let", - ProgramState::Return(5), // true - ), - ( - "should_pass/language/inline_if_expr_const", - ProgramState::Return(0), - ), - ( - "should_pass/language/method_on_empty_struct", - ProgramState::Return(1), - ), - ( - "should_pass/language/tuple_in_struct", - ProgramState::Return(1), - ), - ( - "should_pass/language/nested_structs", - ProgramState::Return(1), - ), - ("should_pass/language/while_loops", ProgramState::Return(1)), - ( - "should_pass/language/retd_small_array", - ProgramState::ReturnData(Bytes32::from([ - 0xcd, 0x26, 0x62, 0x15, 0x4e, 0x6d, 0x76, 0xb2, 0xb2, 0xb9, 0x2e, 0x70, 0xc0, 0xca, - 0xc3, 0xcc, 0xf5, 0x34, 0xf9, 0xb7, 0x4e, 0xb5, 0xb8, 0x98, 0x19, 0xec, 0x50, 0x90, - 0x83, 0xd0, 0x0a, 0x50, - ])), - ), - ( - "should_pass/language/retd_zero_len_array", - ProgramState::ReturnData(Bytes32::from([ - 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, - 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, - 0x78, 0x52, 0xb8, 0x55, - ])), - ), - ("should_pass/language/is_prime", ProgramState::Return(1)), - ( - "should_pass/language/generic_impl_self", - ProgramState::Return(10), - ), - ( - "should_pass/language/enum_init_fn_call", - ProgramState::Return(1), - ), - ( - "should_pass/language/nested_while_and_if", - ProgramState::Return(1), - ), - ( - "should_pass/language/is_reference_type", - ProgramState::Return(1), - ), - ( - "should_pass/language/contract_caller_as_type", - ProgramState::Return(42), - ), - ( - "should_pass/language/non_literal_const_decl", - ProgramState::Return(42), - ), - ( - "should_pass/language/self_impl_reassignment", - ProgramState::Return(1), - ), - ( - "should_pass/language/import_trailing_comma", - ProgramState::Return(0), - ), - ( - "should_pass/language/primitive_type_argument", - ProgramState::Return(5), - ), - ( - "should_pass/language/generic-type-inference", - ProgramState::Return(0), - ), - ( - "should_pass/language/ret_small_string", - ProgramState::ReturnData(Bytes32::from([ - 0x6a, 0x4e, 0x01, 0xe9, 0x40, 0xab, 0xc0, 0x04, 0x30, 0xfe, 0x21, 0x62, 0xed, 0x69, - 0xc0, 0xe2, 0x31, 0x04, 0xf9, 0xfd, 0xa7, 0x81, 0x59, 0x09, 0x2f, 0xea, 0x8f, 0x7e, - 0xcb, 0x7f, 0x6d, 0xd4, - ])), - ), - ( - "should_pass/language/many_stack_variables", - ProgramState::Return(10), - ), - ( - "should_pass/language/ret_string_in_struct", - ProgramState::ReturnData(Bytes32::from([ - 0xaa, 0x5e, 0xfc, 0xa8, 0xda, 0xaf, 0x6e, 0xe6, 0x3f, 0x44, 0x93, 0xb2, 0x88, 0xb3, - 0x85, 0xd7, 0x60, 0xb8, 0xef, 0x93, 0xdc, 0x70, 0xe0, 0xfb, 0xc3, 0x06, 0xed, 0x9b, - 0x67, 0x6e, 0x5f, 0x13, - ])), - ), - ( - "should_pass/language/match_expressions_simple", - ProgramState::Return(42), - ), - ( - "should_pass/language/multi_impl_self", - ProgramState::Return(42), - ), - ( - "should_pass/language/implicit_return", - ProgramState::Return(42), - ), - ( - "should_pass/language/match_expressions_enums", - ProgramState::Return(42), - ), - ( - "should_pass/language/match_expressions_nested", - ProgramState::Return(123), - ), - ( - "should_pass/language/match_expressions_mismatched", - ProgramState::Return(5), - ), - ( - "should_pass/language/match_expressions_inside_generic_functions", - ProgramState::Return(1), - ), - ( - "should_pass/language/generic_inside_generic", - ProgramState::Return(7), - ), - ( - "should_pass/language/tuple_single_element", - ProgramState::Return(1), - ), - ( - "should_pass/language/reassignment_operators", - ProgramState::Return(1), - ), - ( - "should_pass/language/valid_impurity", - ProgramState::Revert(0), // false - ), - ("should_pass/language/const_inits", ProgramState::Return(1)), - ( - "should_pass/language/enum_padding", - ProgramState::ReturnData(Bytes32::from([ - 0xce, 0x55, 0xff, 0x05, 0x11, 0x3a, 0x24, 0x2e, 0xc7, 0x9a, 0x23, 0x75, 0x0c, 0x7e, - 0x2b, 0xab, 0xaf, 0x98, 0xa8, 0xdc, 0x41, 0x66, 0x90, 0xc8, 0x57, 0xdd, 0x31, 0x72, - 0x0c, 0x74, 0x82, 0xb6, - ])), - ), - ( - "should_pass/language/unit_type_variants", - ProgramState::ReturnData(Bytes32::from([ - 0xcd, 0x04, 0xa4, 0x75, 0x44, 0x98, 0xe0, 0x6d, 0xb5, 0xa1, 0x3c, 0x5f, 0x37, 0x1f, - 0x1f, 0x04, 0xff, 0x6d, 0x24, 0x70, 0xf2, 0x4a, 0xa9, 0xbd, 0x88, 0x65, 0x40, 0xe5, - 0xdc, 0xe7, 0x7f, 0x70, - ])), // "ReturnData":{"data":"0000000000000002", .. } - ), - ( - "should_pass/language/match_expressions_with_self", - ProgramState::Return(1), - ), - ( - "should_pass/test_contracts/auth_testing_contract", - ProgramState::Revert(0), - ), - ( - "should_pass/test_contracts/balance_test_contract", - ProgramState::Revert(0), - ), - ( - "should_pass/test_contracts/basic_storage", - ProgramState::Revert(0), - ), - ( - "should_pass/test_contracts/context_testing_contract", - ProgramState::Revert(0), - ), - ( - "should_pass/test_contracts/increment_contract", - ProgramState::Revert(0), - ), - ( - "should_pass/test_contracts/storage_access_contract", - ProgramState::Revert(0), - ), - ( - "should_pass/test_contracts/test_fuel_coin_contract", - ProgramState::Revert(0), - ), - ( - "should_pass/test_contracts/nested_struct_args_contract", - ProgramState::Revert(0), - ), - ( - "should_pass/test_contracts/issue_1512_repro", - ProgramState::Revert(0), - ), - ( - "should_pass/test_contracts/array_of_structs_contract", - ProgramState::Revert(0), - ), - ( - "should_pass/test_contracts/abi_with_tuples_contract", - ProgramState::Revert(0), - ), - ( - "should_pass/test_contracts/get_storage_key_contract", - ProgramState::Revert(0), - ), - ( - "should_pass/test_contracts/multiple_impl", - ProgramState::Revert(0), - ), - ]; - - number_of_tests_run += positive_project_names_with_abi - .iter() - .fold(0, |acc, (name, res)| { - if filter(name) { - assert_eq!(crate::e2e_vm_tests::harness::runs_in_vm(name, locked), *res); - assert_matches!(crate::e2e_vm_tests::harness::test_json_abi(name), Ok(_)); - acc + 1 - } else { - acc + number_of_tests_executed += 1; } - }); - - // source code that should _not_ compile - let negative_project_names = vec![ - "should_fail/cyclic_dependency/dependency_a", - "should_fail/recursive_calls", - "should_fail/asm_missing_return", - "should_fail/asm_should_not_have_return", - "should_fail/missing_fn_arguments", - "should_fail/excess_fn_arguments", - // the feature for the below test, detecting inf deps, was reverted - // when that is re-implemented we should reenable this test - //"should_fail/infinite_dependencies", - "should_fail/top_level_vars", - "should_fail/dependency_parsing_error", - "should_fail/disallowed_gm", - "should_fail/bad_generic_annotation", - "should_fail/bad_generic_var_annotation", - "should_fail/unify_identical_unknowns", - "should_fail/array_oob", - "should_fail/array_bad_index", - "should_fail/name_shadowing", - "should_fail/match_expressions_wrong_struct", - "should_fail/match_expressions_enums", - "should_fail/pure_calls_impure", - "should_fail/nested_impure", - "should_fail/predicate_calls_impure", - "should_fail/script_calls_impure", - "should_fail/contract_pure_calls_impure", - "should_fail/literal_too_large_for_type", - "should_fail/star_import_alias", - "should_fail/item_used_without_import", - "should_fail/shadow_import", - "should_fail/missing_supertrait_impl", - "should_fail/enum_if_let_invalid_variable", - "should_fail/enum_bad_type_inference", - "should_fail/missing_func_from_supertrait_impl", - "should_fail/supertrait_does_not_exist", - "should_fail/chained_if_let_missing_branch", - "should_fail/abort_control_flow_bad", - "should_fail/match_expressions_non_exhaustive", - "should_fail/empty_impl", - "should_fail/disallow_turbofish", - "should_fail/generics_unhelpful_error", - "should_fail/generic_shadows_generic", - "should_fail/different_contract_caller_types", - "should_fail/insufficient_type_info", - "should_fail/primitive_type_argument", - "should_fail/double_underscore_fn", - "should_fail/double_underscore_trait_fn", - "should_fail/double_underscore_impl_self_fn", - "should_fail/double_underscore_var", - "should_fail/double_underscore_struct", - "should_fail/double_underscore_enum", - "should_fail/assign_to_field_of_non_mutable_struct", - "should_fail/abi_method_signature_mismatch", - "should_fail/trait_method_signature_mismatch", - "should_fail/impure_read_calls_impure_write", - "should_fail/abi_impl_purity_mismatch", - "should_fail/abi_pure_calls_impure", - "should_fail/impure_abi_read_calls_impure_write", - "should_fail/impure_trait_read_calls_impure_write", - "should_fail/trait_impl_purity_mismatch", - "should_fail/trait_pure_calls_impure", - "should_fail/match_expressions_empty_arms", - "should_fail/type_mismatch_error_message", - "should_fail/recursive_enum", - "should_fail/recursive_struct", - "should_fail/recursive_type_chain", - "should_fail/better_type_error_message", - "should_fail/storage_in_library", - "should_fail/storage_in_predicate", - "should_fail/storage_in_script", - "should_fail/multiple_impl_abi", - "should_fail/multiple_impl_fns", - "should_fail/repeated_enum_variant", - "should_fail/repeated_storage_field", - "should_fail/repeated_struct_field", - "should_fail/method_requires_mut_var", - "should_fail/impl_with_bad_generic", - "should_fail/storage_conflict", - ]; - number_of_tests_run += negative_project_names.iter().fold(0, |acc, name| { - if filter(name) { - crate::e2e_vm_tests::harness::does_not_compile(name, locked); - acc + 1 - } else { - acc - } - }); - // ---- Tests paired with contracts upon which they depend which must be pre-deployed. - let contract_and_project_names = &[ - ( - ( - "should_pass/test_contracts/basic_storage", - "should_pass/require_contract_deployment/call_basic_storage", - ), - 4242, - ), - ( - ( - "should_pass/test_contracts/increment_contract", - "should_pass/require_contract_deployment/call_increment_contract", - ), - 1, // true - ), - ( - ( - "should_pass/test_contracts/auth_testing_contract", - "should_pass/require_contract_deployment/caller_auth_test", - ), - 1, // true - ), - ( - ( - "should_pass/test_contracts/context_testing_contract", - "should_pass/require_contract_deployment/caller_context_test", - ), - 1, // true - ), - ( - ( - "should_pass/test_contracts/balance_test_contract", - "should_pass/require_contract_deployment/bal_opcode", - ), - 1, // true - ), - ( - ( - "should_pass/test_contracts/test_fuel_coin_contract", - "should_pass/require_contract_deployment/token_ops_test", - ), - 1, // true - ), - ( - ( - "should_pass/test_contracts/storage_access_contract", - "should_pass/require_contract_deployment/storage_access_caller", - ), - 1, // true - ), - ( - ( - "should_pass/test_contracts/get_storage_key_contract", - "should_pass/require_contract_deployment/get_storage_key_caller", - ), - 1, - ), - ( - ( - "should_pass/test_contracts/array_of_structs_contract", - "should_pass/require_contract_deployment/array_of_structs_caller", - ), - 1, - ), - ( - ( - "should_pass/test_contracts/abi_with_tuples_contract", - "should_pass/require_contract_deployment/call_abi_with_tuples", - ), - 1, - ), - ]; - - let total_number_of_tests = positive_project_names_no_abi.len() - + positive_project_names_with_abi.len() - + negative_project_names.len() - + contract_and_project_names.len(); - - // Filter them first. - let (contracts_and_projects, vals): (Vec<_>, Vec<_>) = contract_and_project_names - .iter() - .filter(|names| filter(names.0 .1)) - .cloned() - .unzip(); - - let (contracts, projects): (Vec<_>, Vec<_>) = contracts_and_projects.iter().cloned().unzip(); - - // Deploy and then test. - number_of_tests_run += projects.len(); - let mut contract_ids = Vec::::with_capacity(contracts.len()); - for name in contracts { - let contract_id = harness::deploy_contract(name, locked); - contract_ids.push(contract_id); - } + TestCategory::Compiles => { + let result = crate::e2e_vm_tests::harness::compile_to_bytes(&name, locked); + assert!(result.is_ok()); + let compiled = result.unwrap(); + if validate_abi { + assert!(crate::e2e_vm_tests::harness::test_json_abi(&name, &compiled).is_ok()); + } + if validate_storage_slots { + assert!(crate::e2e_vm_tests::harness::test_json_storage_slots( + &name, &compiled + ) + .is_ok()); + } + number_of_tests_executed += 1; + } - for (name, val) in projects.iter().zip(vals.iter()) { - let result = harness::runs_on_node(name, locked, &contract_ids); - assert!(result.iter().all(|r| !matches!( - r, - fuel_tx::Receipt::Revert { .. } | fuel_tx::Receipt::Panic { .. } - ))); - assert!( - result.len() >= 2 - && matches!(result[result.len() - 2], fuel_tx::Receipt::Return { .. }) - && result[result.len() - 2].val().unwrap() == *val - ); + TestCategory::FailsToCompile => { + match crate::e2e_vm_tests::harness::does_not_compile(&name, locked) { + Ok(output) => match checker.explain(&output, filecheck::NO_VARIABLES) { + Ok((success, report)) if !success => { + panic!("For {name}:\nFilecheck failed:\n{report}"); + } + Err(e) => { + panic!("For {name}:\nFilecheck directive error: {e}"); + } + _ => (), + }, + Err(_) => { + panic!("For {name}:\nFailing test did not fail."); + } + } + number_of_tests_executed += 1; + } + + TestCategory::RunsWithContract => { + let val = if let Some(TestResult::Result(val)) = expected_result { + val + } else { + panic!( + "For {name}:\nExpecting a 'result' action for a 'run_on_node' test, \ + found: {expected_result:?}." + ) + }; + + if contract_paths.is_empty() { + panic!( + "For {name}\n\ + One or more ontract paths are required for 'run_on_node' tests." + ); + } + + let contract_ids = contract_paths + .into_iter() + .map(|contract_path| { + *deployed_contracts + .entry(contract_path.clone()) + .or_insert_with(|| { + harness::deploy_contract(contract_path.as_str(), locked) + }) + }) + .collect::>(); + + let result = harness::runs_on_node(&name, locked, &contract_ids); + assert!(result.iter().all(|res| !matches!( + res, + fuel_tx::Receipt::Revert { .. } | fuel_tx::Receipt::Panic { .. } + ))); + assert!( + result.len() >= 2 + && matches!(result[result.len() - 2], fuel_tx::Receipt::Return { .. }) + && result[result.len() - 2].val().unwrap() == val + ); + + number_of_tests_executed += 1; + } + + TestCategory::Disabled => { + number_of_disabled_tests += 1; + } + } } - if number_of_tests_run == 0 { + if number_of_tests_executed == 0 { tracing::info!( "No tests were run. Regex filter \"{}\" filtered out all {} tests.", - filter_regex.map(|x| x.to_string()).unwrap_or_default(), + filter_regex + .map(|regex| regex.to_string()) + .unwrap_or_default(), total_number_of_tests ); } else { tracing::info!("_________________________________\nTests passed."); tracing::info!( - "{} tests run ({} skipped)", - number_of_tests_run, - total_number_of_tests - number_of_tests_run + "{} tests run ({} skipped, {} disabled)", + number_of_tests_executed, + total_number_of_tests - number_of_tests_executed - number_of_disabled_tests, + number_of_disabled_tests, ); } } + +fn discover_test_configs() -> Result, String> { + fn recursive_search(path: &Path, configs: &mut Vec) -> Result<(), String> { + let wrap_err = |e| { + let relative_path = path + .iter() + .skip_while(|part| part.to_string_lossy() != "test_programs") + .skip(1) + .collect::(); + format!("{}: {}", relative_path.display(), e) + }; + if path.is_dir() { + for entry in std::fs::read_dir(path).unwrap() { + recursive_search(&entry.unwrap().path(), configs)?; + } + } else if path.is_file() && path.file_name() == Some(std::ffi::OsStr::new("test.toml")) { + configs.push(parse_test_toml(path).map_err(wrap_err)?); + } + Ok(()) + } + + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let tests_root_dir = format!("{manifest_dir}/src/e2e_vm_tests/test_programs"); + + let mut configs = Vec::new(); + recursive_search(&PathBuf::from(tests_root_dir), &mut configs)?; + Ok(configs) +} + +fn parse_test_toml(path: &Path) -> Result { + let (toml_content, checker) = std::fs::read_to_string(path) + .map_err(|e| e.to_string()) + .and_then(|toml_content_str| { + // Parse the file for FileCheck directives and_then parse the file into TOML. + filecheck::CheckerBuilder::new() + .text(&toml_content_str) + .map_err(|e| e.to_string()) + .and_then(|checker| { + toml_content_str + .parse::() + .map_err(|e| e.to_string()) + .map(|toml_content| (toml_content, checker.finish())) + }) + }) + .map_err(|e| format!("Failed to parse: {e}"))?; + + if !toml_content.is_table() { + return Err("Malformed test description.".to_owned()); + } + + let category = toml_content + .get("category") + .ok_or_else(|| "Missing mandatory 'category' entry.".to_owned()) + .and_then(|category_val| match category_val.as_str() { + Some("run") => Ok(TestCategory::Runs), + Some("run_on_node") => Ok(TestCategory::RunsWithContract), + Some("fail") => Ok(TestCategory::FailsToCompile), + Some("compile") => Ok(TestCategory::Compiles), + Some("disabled") => Ok(TestCategory::Disabled), + None => Err(format!( + "Malformed category '{category_val}', should be a string." + )), + Some(other) => Err(format!("Unknown category '{}'.", other,)), + })?; + + // Abort early if we find a FailsToCompile test without any Checker directives. + if category == TestCategory::FailsToCompile && checker.is_empty() { + return Err("'fail' tests must contain some FileCheck verification directives.".to_owned()); + } + + let expected_result = match &category { + TestCategory::Runs | TestCategory::RunsWithContract => { + Some(get_expected_result(&toml_content)?) + } + TestCategory::Compiles | TestCategory::FailsToCompile | TestCategory::Disabled => None, + }; + + let contract_paths = match toml_content.get("contracts") { + None => Vec::new(), + Some(contracts) => contracts + .as_array() + .ok_or_else(|| "Contracts must be an array of strings.".to_owned()) + .and_then(|vals| { + vals.iter() + .map(|val| { + val.as_str() + .ok_or_else(|| "Contracts must be path strings.".to_owned()) + .map(|path_str| path_str.to_owned()) + }) + .collect::, _>>() + })?, + }; + + let validate_abi = toml_content + .get("validate_abi") + .map(|v| v.as_bool().unwrap_or(false)) + .unwrap_or(false); + + let validate_storage_slots = toml_content + .get("validate_storage_slots") + .map(|v| v.as_bool().unwrap_or(false)) + .unwrap_or(false); + + // We need to adjust the path to start relative to `test_programs`. + let name = path + .iter() + .skip_while(|part| part.to_string_lossy() != "test_programs") + .skip(1) + .collect::(); + + // And it needs to chop off the `test.toml` and convert to a String. + let name = name + .parent() + .unwrap() + .to_str() + .map(|s| s.to_owned()) + .unwrap(); + + Ok(TestDescription { + name, + category, + expected_result, + contract_paths, + validate_abi, + validate_storage_slots, + checker, + }) +} + +fn get_expected_result(toml_content: &toml::Value) -> Result { + fn get_action_value( + action: &toml::Value, + expected_value: &toml::Value, + ) -> Result { + match (action.as_str(), expected_value) { + // A simple integer value. + (Some("return"), toml::Value::Integer(v)) => Ok(TestResult::Return(*v as u64)), + + // Also a simple integer value, but is a result from a contract call. + (Some("result"), toml::Value::Integer(v)) => Ok(TestResult::Result(*v as Word)), + + // A bytes32 value. + (Some("return_data"), toml::Value::Array(ary)) => ary + .iter() + .map(|byte_val| { + byte_val.as_integer().ok_or_else(|| { + format!( + "Return data must only contain integer values; \ + found {byte_val}." + ) + }) + }) + .collect::, _>>() + .and_then(|bytes| { + if bytes.iter().any(|byte| *byte < 0 || *byte > 255) { + Err("Return data byte values must be less than 256.".to_owned()) + } else if bytes.len() != 32 { + Err(format!( + "Return data must be a 32 byte array; \ + found {} values.", + bytes.len() + )) + } else { + Ok(bytes.iter().map(|byte| *byte as u8).collect()) + } + }) + .map(|bytes: Vec| { + let fixed_byte_array = + bytes + .iter() + .enumerate() + .fold([0_u8; 32], |mut ary, (idx, byte)| { + ary[idx] = *byte; + ary + }); + TestResult::ReturnData(Bytes32::from(fixed_byte_array)) + }), + + // Revert with a specific code. + (Some("revert"), toml::Value::Integer(v)) => Ok(TestResult::Revert(*v as u64)), + + _otherwise => Err(format!("Malformed action value: {action} {expected_value}")), + } + } + + toml_content + .get("expected_result") + .ok_or_else(|| "Could not find mandatory 'expected_result' entry.".to_owned()) + .and_then(|expected_result_table| { + expected_result_table + .get("action") + .ok_or_else(|| { + "Could not find mandatory 'action' field in 'expected_result' entry.".to_owned() + }) + .and_then(|action| { + expected_result_table + .get("value") + .ok_or_else(|| { + "Could not find mandatory 'value' field in 'expected_result' entry." + .to_owned() + }) + .and_then(|expected_value| get_action_value(action, expected_value)) + }) + }) +} diff --git a/test/src/e2e_vm_tests/test_programs/README.md b/test/src/e2e_vm_tests/test_programs/README.md new file mode 100644 index 00000000000..3f3e734b054 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/README.md @@ -0,0 +1,115 @@ +# Config Driven End To End Testing. + +Each of the tests in this suite are controlled by a TOML descriptor file which describes how the +test should be run and what result to expect if any. + +## test.toml + +To add a new test to the E2E suite place a `test.toml` file at the root of the test Forc package, +i.e., next to the `Forc.toml` file. This file may contain a few basic fields. + +## category + +The `category` field is mandatory and must be one of the following strings: + +* `"run"` - The test is compiled and run in a VM. +* `"run_on_node"` - The test is compiled and run on a local Fuel Core node. +* `"compile"` - The test is expected to succeed compiling, but isn't run in any way. +* `"fail"` - The test is expected to fail to compile. +* `"disabled"` - The test is disabled. + +## expected_result + +The `expected_result` field is mandatory for `"run"` and `"run_on_node"` tests. It is a table with +two fields, `action` and `value`. + +The `action` field describe what sort of result to expect: + +* `"return"` - An integer value returned by success in the VM. +* `"return_data"` - An array of bytes returned by the VM. +* `"result"` - An integer word returned by the Fuel Core node. +* `"revert"` - An integer value returned by failure in the VM. + +The `value` field is the actual expected value. For `"return"`, `"result"` and `"revert"` actions +it must be an integer. + +For `"return_data"` actions it must be an array of byte values, each an integer between 0 and 255. + +## contracts + +Tests in the `"run_on_node"` category will usually specify one or more contracts which must be +deployed to the node prior to deploying and running the test code. These are specified with the +`contracts` field. + +It must be an array of strings each containing only the path to the Forc project for the contract to +be compiled and deployed. It is important that these paths remain relative to the +`test/src/e2e_vm_tests/test_programs` directory. + +## validate_abi + +Some tests also require their ABI is verified. To indicate this the `validate_abi` field may be +specified, as a boolean value. + +# FileCheck for 'fail' tests + +The tests in the `fail` category _must_ employ verification using pattern matching via the [FileCheck](https://docs.rs/filecheck/latest/filecheck/) +crate. The checker directives are specified in comments (lines beginning with `#`) in the `test.toml` +file. + +Typically this is as simple as just adding a `# check: ...` line to the line specifying the full +error or warning message expected from compiling the test. `FileCheck` also has other directives for +fancier pattern matching, as specified in the [FileCheck docs](https://docs.rs/filecheck/latest/filecheck/). + +**Note:** The output from the compiler is colorized, usually to red or yellow, and this involves +printing ANSI escape sequences to the terminal. These sequences can confuse `FileCheck` as it tries +to match patterns on 'word' boundaries. The first word in an error message is most likely prefixed +with an escape sequence and can cause the check to fail. + +To avoid this problem one may either not use the first word in the error message, or use the 'empty +string' pattern `$()` to direct the matcher as to where the pattern starts. + +E.g, `# check: $()The name "S" shadows another symbol with the same name.` + +# Examples + +The following is a common example for tests in the `should_pass/language` directory. The test +should be compiled, run on the VM, should expect a return value of 42 and should also validate the +ABI generation. + +```toml +category = "run" +expected_result = { action = "return", value = 42 } +validate_abi = true +``` + +And this example is similar but expects return data. + +```toml +category = "run" +expected_result = { action = "return_data", value = [ 102, 104, 122, 173, 248, 98, 189, 119, 108, 143, 193, 139, 142, 159, 142, 32, 8, 151, 20, 133, 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, 41, 37 ] } +validate_abi = true +``` + +The following tests a contract on a Fuel Core node. + +```toml +category = "run_on_node" +expected_result = { action = "result", value = 11 } +contracts = ["should_pass/test_contracts/test_contract_a", "should_pass/test_contracts/test_contract_b"] +``` + +Tests which fail can have fairly elaborate checks. + +```toml +category = "fail" + +# check: // this asm block should return unit, i.e. nothing +# nextln: asm(r1: 5) { +# check: $()Mismatched types. +# nextln: $()expected: () +# nextln: $()found: u64. +# nextln: $()help: Implicit return must match up with block's type. +``` + +And there are already hundreds of existing tests with `test.toml` descriptors which may be consulted +when adding a new test. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/abi_impl_purity_mismatch/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/abi_impl_purity_mismatch/test.toml new file mode 100644 index 00000000000..e2cad27ba68 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/abi_impl_purity_mismatch/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()Storage attribute access mismatch. The trait function "test_function" in trait "MyContract" requires the storage attribute(s) #[storage(read)]. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/abi_method_signature_mismatch/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/abi_method_signature_mismatch/test.toml new file mode 100644 index 00000000000..7e008750474 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/abi_method_signature_mismatch/test.toml @@ -0,0 +1,5 @@ +category = "fail" + +# check: fn foo(s: str[7]) -> str[7] { +# nextln: $()Expected: u64 +# nextln: $()found: str[7]. The definition of this function must match the one in the trait declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/abi_pure_calls_impure/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/abi_pure_calls_impure/test.toml new file mode 100644 index 00000000000..03bbc908cd3 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/abi_pure_calls_impure/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: f() +# nextln: $()Storage attribute access mismatch. Try giving the surrounding function more access by adding "#[storage(read)]" to the function declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/abort_control_flow_bad/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/abort_control_flow_bad/test.toml new file mode 100644 index 00000000000..95441264e4e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/abort_control_flow_bad/test.toml @@ -0,0 +1,16 @@ +category = "fail" + +# check: return 42; +# nextln: $()Mismatched types. +# nextln: $()expected: () +# nextln: $()found: u64. +# nextln: $()help: Return statement must return the declared function return type. + +# This 'return true' line appears in both error messages.. +# check: return true; + +# check: return true; +# nextln: $()Mismatched types. +# nextln: $()expected: () +# nextln: $()found: bool. +# nextln: $()help: Return statement must return the declared function return type. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/array_bad_index/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/array_bad_index/test.toml new file mode 100644 index 00000000000..366684b2f51 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/array_bad_index/test.toml @@ -0,0 +1,6 @@ +category = "fail" + +# check: ary[false] +# nextln: $()Mismatched types. +# nextln: $()expected: u64 +# nextln: $()found: bool. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/array_oob/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/array_oob/test.toml new file mode 100644 index 00000000000..f4fb799b640 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/array_oob/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()Array index out of bounds; the length is 3 but the index is 4. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/asm_missing_return/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/asm_missing_return/test.toml new file mode 100644 index 00000000000..81f51f41dc3 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/asm_missing_return/test.toml @@ -0,0 +1,13 @@ +category = "fail" + +# check: asm(r1: 5) { +# check: $()Mismatched types. +# nextln: $()expected: u64 +# nextln: $()found: (). +# nextln: $()help: Implicit return must match up with block's type. + +# check: asm(r1: 5) { +# check: $()Mismatched types. +# nextln: $()expected: u64 +# nextln: $()found: (). +# nextln: $()help: Function body's return type does not match up with its return type annotation. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/asm_should_not_have_return/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/asm_should_not_have_return/test.toml new file mode 100644 index 00000000000..fd0513db60e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/asm_should_not_have_return/test.toml @@ -0,0 +1,15 @@ +category = "fail" + +# check: // this asm block should return unit, i.e. nothing +# nextln: asm(r1: 5) { +# check: $()Mismatched types. +# nextln: $()expected: () +# nextln: $()found: u64. +# nextln: $()help: Implicit return must match up with block's type. + +# check: // this asm block should return unit, i.e. nothing +# nextln: asm(r1: 5) { +# check: $()Mismatched types. +# nextln: $()expected: () +# nextln: $()found: u64. +# nextln: $()help: Function body's return type does not match up with its return type annotation. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/assign_to_field_of_non_mutable_struct/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/assign_to_field_of_non_mutable_struct/test.toml new file mode 100644 index 00000000000..2cdba2605b9 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/assign_to_field_of_non_mutable_struct/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()Assignment to immutable variable. Variable thing is not declared as mutable. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/bad_generic_annotation/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/bad_generic_annotation/test.toml new file mode 100644 index 00000000000..f76942c087b --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/bad_generic_annotation/test.toml @@ -0,0 +1,7 @@ +category = "fail" + +# check: let g: u32 = three_generics(true, "foo", 10); +# nextln: $()Mismatched types. +# nextln: $()expected: u32 +# nextln: $()found: str[3]. +# nextln: $()help: Variable declaration's type annotation does not match up with the assigned expression's type. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/bad_generic_var_annotation/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/bad_generic_var_annotation/test.toml new file mode 100644 index 00000000000..8e710db7414 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/bad_generic_var_annotation/test.toml @@ -0,0 +1,13 @@ +category = "fail" + +# check: let g: str[3] = three_generics(true, "foo", 10); +# nextln: $()Mismatched types. +# nextln: $()expected: bool +# nextln: $()found: str[3]. +# nextln: $()help: The argument that has been provided to this function's type does not match the declared type of the parameter in the function declaration. + +# check: let g: str[3] = three_generics(true, "foo", 10); +# nextln: $()Mismatched types. +# nextln: $()expected: str[3] +# nextln: $()found: bool. +# nextln: $()help: Variable declaration's type annotation does not match up with the assigned expression's type. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/better_type_error_message/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/better_type_error_message/test.toml new file mode 100644 index 00000000000..50c676d74ab --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/better_type_error_message/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: $()Could not find symbol "Result" in this scope. +# check: $()Unknown type name "Result". diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/chained_if_let_missing_branch/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/chained_if_let_missing_branch/test.toml new file mode 100644 index 00000000000..6a45df6f7c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/chained_if_let_missing_branch/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()Variable "num" does not exist in this scope. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/Forc.lock new file mode 100644 index 00000000000..fce30ef9643 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/Forc.lock @@ -0,0 +1,9 @@ +[[package]] +name = 'const_nonconst_init' +source = 'root' +dependencies = ['core'] + +[[package]] +name = 'core' +source = 'path+from-root-E57A3612ABF8CF11' +dependencies = [] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/Forc.toml new file mode 100644 index 00000000000..8c981ae7e1b --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "const_nonconst_init" + +[dependencies] +core = { path = "../../../../../../sway-lib-core" } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/src/main.sw new file mode 100644 index 00000000000..207339315f9 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/src/main.sw @@ -0,0 +1,10 @@ +script; + +fn bla(x: u64) -> u64 { + x + 1 +} + +fn main() -> u64 { + const X = bla(0); + X +} diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/test.toml new file mode 100644 index 00000000000..e92e4b0b7ee --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/const_nonconst_init/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: $()const X = bla(0); +# nextln: $()Could not evaluate initializer to a const declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/contract_pure_calls_impure/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/contract_pure_calls_impure/test.toml new file mode 100644 index 00000000000..27781afe7eb --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/contract_pure_calls_impure/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: foo(); +# nextln: $()Storage attribute access mismatch. Try giving the surrounding function more access by adding "#[storage(read, write)]" to the function declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/cyclic_dependency/dependency_a/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/cyclic_dependency/dependency_a/test.toml new file mode 100644 index 00000000000..51bdfacac1a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/cyclic_dependency/dependency_a/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: dependency cycle detected: dependency_a -> dependency_b -> dependency_a diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/dependency_parsing_error/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/dependency_parsing_error/test.toml new file mode 100644 index 00000000000..bc59bcc1856 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/dependency_parsing_error/test.toml @@ -0,0 +1,5 @@ +category = "fail" + +# Not sure if this is the originally expected error: +# check: let baz = 43; +# nextln: $()Expected an item. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/different_contract_caller_types/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/different_contract_caller_types/test.toml new file mode 100644 index 00000000000..355316b3291 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/different_contract_caller_types/test.toml @@ -0,0 +1,15 @@ +category = "fail" + +# check: let caller = abi(OtherAbi, ADDRESS); +# nextln: caller +# nextln: $()Mismatched types. +# nextln: $()expected: contract caller SomeAbi +# nextln: $()found: contract caller OtherAbi. +# nextln: $()help: Implicit return must match up with block's type. + +# check: let caller = abi(OtherAbi, ADDRESS); +# nextln: caller +# nextln: $()Mismatched types. +# nextln: $()expected: contract caller SomeAbi +# nextln: $()found: contract caller OtherAbi. +# nextln: $()help: Function body's return type does not match up with its return type annotation. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/disallow_turbofish/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/disallow_turbofish/test.toml new file mode 100644 index 00000000000..a4948439baa --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/disallow_turbofish/test.toml @@ -0,0 +1,10 @@ +category = "fail" + +# check: let data = Data:: { +# nextln: $()"Data" does not take type arguments. + +# check: let res1 = Result:: { +# nextln: $()Expected 2 type arguments, but instead found 1. + +# check: foo::(); +# nextln: $()"foo" does not take type arguments. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/disallowed_gm/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/disallowed_gm/test.toml new file mode 100644 index 00000000000..bb1c25bdea2 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/disallowed_gm/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: gm r1 i1; +# nextln: $()The GM (get-metadata) opcode, when called from an external context, will cause the VM to panic. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_enum/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_enum/test.toml new file mode 100644 index 00000000000..7154cc6c101 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_enum/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: enum __MyEnum { +# nextln: $()Identifiers cannot begin with a double underscore, as that naming convention is reserved for compiler intrinsics. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_fn/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_fn/test.toml new file mode 100644 index 00000000000..4543ad5a87d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_fn/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: __test() +# nextln: $()Identifiers cannot begin with a double underscore, as that naming convention is reserved for compiler intrinsics. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_impl_self_fn/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_impl_self_fn/test.toml new file mode 100644 index 00000000000..951e04dfc1f --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_impl_self_fn/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: fn __double_underscore(self, x: bool) -> bool { +# nextln: $()Identifiers cannot begin with a double underscore, as that naming convention is reserved for compiler intrinsics. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_struct/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_struct/test.toml new file mode 100644 index 00000000000..ebbda21f9d3 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_struct/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: struct __MyStruct { +# nextln: $()Identifiers cannot begin with a double underscore, as that naming convention is reserved for compiler intrinsics. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_trait_fn/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_trait_fn/test.toml new file mode 100644 index 00000000000..4543ad5a87d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_trait_fn/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: __test() +# nextln: $()Identifiers cannot begin with a double underscore, as that naming convention is reserved for compiler intrinsics. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_var/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_var/test.toml new file mode 100644 index 00000000000..a083e9620bb --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/double_underscore_var/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: __a +# nextln: $()Identifiers cannot begin with a double underscore, as that naming convention is reserved for compiler intrinsics. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/empty_impl/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/empty_impl/test.toml new file mode 100644 index 00000000000..60d4ed90b21 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/empty_impl/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()Could not find symbol "Coin" in this scope. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/enum_bad_type_inference/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/enum_bad_type_inference/Forc.toml index f47a8d75a5b..fdf0ae59d95 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/enum_bad_type_inference/Forc.toml +++ b/test/src/e2e_vm_tests/test_programs/should_fail/enum_bad_type_inference/Forc.toml @@ -5,4 +5,4 @@ license = "Apache-2.0" name = "enum_bad_type_inference" [dependencies] -core = { path = "../../../../../../../sway-lib-core" } +core = { path = "../../../../../../sway-lib-core" } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/enum_bad_type_inference/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/enum_bad_type_inference/test.toml new file mode 100644 index 00000000000..c0a3049c75d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/enum_bad_type_inference/test.toml @@ -0,0 +1,12 @@ +category = "fail" + + +# check: Ok: T, +# nextln: $()Mismatched types. +# nextln: $()expected: bool +# nextln: $()found: u64. + +# check: enum Result { +# nextln: $()Mismatched types. +# nextln: $()expected: bool +# nextln: $()found: u64. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/enum_if_let_invalid_variable/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/enum_if_let_invalid_variable/test.toml new file mode 100644 index 00000000000..48fb7c32872 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/enum_if_let_invalid_variable/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: if let +# nextln: $()Variable "y" does not exist in this scope. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/Forc.lock new file mode 100644 index 00000000000..63ae381216c --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-987CA0C143EB9BCC' +dependencies = [] + +[[package]] +name = 'eq_intrinsic' +source = 'root' +dependencies = ['std'] + +[[package]] +name = 'std' +source = 'path+from-root-987CA0C143EB9BCC' +dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/Forc.toml new file mode 100644 index 00000000000..e84dbdc4d76 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "eq_intrinsic" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/json_abi_oracle.json new file mode 100644 index 00000000000..905c3bd1034 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/json_abi_oracle.json @@ -0,0 +1,14 @@ +[ + { + "inputs": [], + "name": "main", + "outputs": [ + { + "components": null, + "name": "", + "type": "u64" + } + ], + "type": "function" + } +] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/src/main.sw new file mode 100644 index 00000000000..f0af6b19049 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/src/main.sw @@ -0,0 +1,23 @@ +script; + +struct A { + a: u64, +} + +enum B { + First: (), + Second: u64 +} + +fn main() { + let _ = __eq("hi", "ho"); + let _ = __eq(false, 11); + let _ = __eq(A { a: 1 }, B { a: 1 }); + let _ = __eq((1, 2), (1, 2)); + let _ = __eq([1, 2], [1, 2]); + let _ = __eq(B::First, B::First); + let _ = __eq(B::Second(1), B::Second(1)); + let my_number1: b256 = 0x000000000000000000000000000000000000000000000000000000000000002A; + let my_number2: b256 = 0x000000000000000000000000000000000000000000000000000000000000002A; + let _ = __eq(my_number1, my_number1); +} diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/test.toml new file mode 100644 index 00000000000..299b8ccd092 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/eq_intrinsic/test.toml @@ -0,0 +1,25 @@ +category = "fail" + +# check: $()__eq("hi", "ho"); +# nextln: $()Unsupported argument type to intrinsic "eq". + +# check: $()__eq(false, 11); +# check: $()Mismatched types. + +# check: $()__eq(A { a: 1 }, B { a: 1 }); +# check: $()Unsupported argument type to intrinsic "eq". + +# check: $()__eq((1, 2), (1, 2)); +# check: $()Unsupported argument type to intrinsic "eq". + +# check: $()__eq([1, 2], [1, 2]); +# check: $()Unsupported argument type to intrinsic "eq". + +# check: $()__eq(B::First, B::First); +# check: $()Unsupported argument type to intrinsic "eq". + +# check: $()__eq(B::Second(1), B::Second(1)); +# check: $()Unsupported argument type to intrinsic "eq". + +# check: $()__eq(my_number1, my_number1); +# check: $()Unsupported argument type to intrinsic "eq". \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/excess_fn_arguments/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/excess_fn_arguments/Forc.lock index c4169651b66..94668d10be6 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/excess_fn_arguments/Forc.lock +++ b/test/src/e2e_vm_tests/test_programs/should_fail/excess_fn_arguments/Forc.lock @@ -1,4 +1,9 @@ +[[package]] +name = 'core' +source = 'path+from-root-8EECC8A749908BB3' +dependencies = [] + [[package]] name = 'excess_fn_arguments' source = 'root' -dependencies = [] +dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/excess_fn_arguments/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/excess_fn_arguments/Forc.toml index 52df234df91..71302867fd4 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/excess_fn_arguments/Forc.toml +++ b/test/src/e2e_vm_tests/test_programs/should_fail/excess_fn_arguments/Forc.toml @@ -3,4 +3,6 @@ authors = ["Fuel Labs "] license = "Apache-2.0" name = "excess_fn_arguments" entry = "main.sw" -implicit-std = false + +[dependencies] +core = { path = "../../../../../../sway-lib-core" } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/excess_fn_arguments/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/excess_fn_arguments/test.toml new file mode 100644 index 00000000000..a220620ac5d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/excess_fn_arguments/test.toml @@ -0,0 +1,5 @@ +# This test should be a "fail" but it's currently passing. +# See https://github.com/FuelLabs/sway/issues/2081 +category = "compile" + +# check: ... something about too many args ... diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/generic_shadows_generic/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/generic_shadows_generic/test.toml new file mode 100644 index 00000000000..f76f70db80e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/generic_shadows_generic/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()The name "T" is already used for a generic parameter in this scope. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/generics_unhelpful_error/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/generics_unhelpful_error/test.toml new file mode 100644 index 00000000000..a41fe303372 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/generics_unhelpful_error/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: fn f(a: DoubleIdentity) { +# nextln: $()Expected 2 type arguments, but instead found 1. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_bad_generic/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_bad_generic/test.toml new file mode 100644 index 00000000000..0550b590a9d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_bad_generic/test.toml @@ -0,0 +1,7 @@ +category = "fail" + +# check: impl S { +# nextln: $()The generic type parameter "T" is unconstrained. + +# check: (S{}).f(true); +# nextln: $()No method named "f" found for type "S". diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/.gitignore b/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/Forc.lock new file mode 100644 index 00000000000..39a70d597e7 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-C569FB5C26218A1B' +dependencies = [] + +[[package]] +name = 'impl_with_semantic_type_constraints' +source = 'root' +dependencies = ['std'] + +[[package]] +name = 'std' +source = 'path+from-root-C569FB5C26218A1B' +dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/Forc.toml new file mode 100644 index 00000000000..e21f59c2882 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "impl_with_semantic_type_constraints" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/src/main.sw new file mode 100644 index 00000000000..bfdc1398d1a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/src/main.sw @@ -0,0 +1,54 @@ +script; + +struct DoubleIdentity { + first: T, + second: F, +} + +impl DoubleIdentity { + fn get_first(self) -> T { + self.first + } +} + +impl DoubleIdentity { + fn get_second(self) -> F { + self.second + } +} + +impl DoubleIdentity { + fn add(self) -> u8 { + self.first + self.second + } +} + +fn main() { + let a = DoubleIdentity { + first: 0u8, + second: 1u8 + }; + let b = DoubleIdentity { + first: true, + second: false, + }; + let c = DoubleIdentity { + first: 0u64, + second: "hi" + }; + + let d = a.get_first(); + let e = a.get_second(); + let f = a.add(); + + let g = b.get_first(); + let h = b.get_second(); + // should fail + let i = b.add(); + + // should fail + let j = c.get_first(); + let k = c.get_second(); + // should fail + let l = c.add(); +} diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/test.toml new file mode 100644 index 00000000000..70f231d938e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/impl_with_semantic_type_constraints/test.toml @@ -0,0 +1,10 @@ +category = "fail" + +# check: let i = b.add(); +# nextln: $()No method named "add" found for type "DoubleIdentity". + +# check: let j = c.get_first(); +# nextln: $()No method named "get_first" found for type "DoubleIdentity". + +# check: let l = c.add(); +# nextln: $()No method named "add" found for type "DoubleIdentity". diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/impure_abi_read_calls_impure_write/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/impure_abi_read_calls_impure_write/test.toml new file mode 100644 index 00000000000..d4b070cc54f --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/impure_abi_read_calls_impure_write/test.toml @@ -0,0 +1,5 @@ +category = "fail" + +# check: fn test_function() -> bool { +# nextln: f() +# nextln: $()Storage attribute access mismatch. Try giving the surrounding function more access by adding "#[storage(read, write)]" to the function declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/impure_read_calls_impure_write/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/impure_read_calls_impure_write/test.toml new file mode 100644 index 00000000000..1c9fcacfc24 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/impure_read_calls_impure_write/test.toml @@ -0,0 +1,5 @@ +category = "fail" + +# check: fn can_read() { +# nextln: can_write(); +# nextln: $()Storage attribute access mismatch. Try giving the surrounding function more access by adding "#[storage(read, write)]" to the function declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/impure_trait_read_calls_impure_write/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/impure_trait_read_calls_impure_write/test.toml new file mode 100644 index 00000000000..59172c85dfc --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/impure_trait_read_calls_impure_write/test.toml @@ -0,0 +1,5 @@ +category = "fail" + +# check: pub fn g() -> bool { +# nextln: true.f() +# nextln: $()Storage attribute access mismatch. Try giving the surrounding function more access by adding "#[storage(read, write)]" to the function declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/infinite_dependencies/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/infinite_dependencies/Forc.lock index 2e6d2d8ead1..3dd8c426e89 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/infinite_dependencies/Forc.lock +++ b/test/src/e2e_vm_tests/test_programs/should_fail/infinite_dependencies/Forc.lock @@ -1,3 +1,4 @@ [[package]] name = 'infinite_dependencies' +source = 'root' dependencies = [] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/infinite_dependencies/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/infinite_dependencies/test.toml new file mode 100644 index 00000000000..73cf88a0b5b --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/infinite_dependencies/test.toml @@ -0,0 +1,5 @@ +# The feature for this test, detecting infinite deps, was reverted. When that is re-implemented we +# should re-enable this test. + +#category = "fail" +category = "disabled" diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/insufficient_type_info/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/insufficient_type_info/src/main.sw index 92aaab678c8..ea156f19381 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/insufficient_type_info/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_fail/insufficient_type_info/src/main.sw @@ -1,7 +1,7 @@ script; fn foo() { - let x = size_of::(); + let x = __size_of::(); } fn main() { diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/insufficient_type_info/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/insufficient_type_info/test.toml new file mode 100644 index 00000000000..2c9e7e9e3ed --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/insufficient_type_info/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: __size_of::(); +# nextln: $()Cannot infer type for type parameter "T". Insufficient type information provided. Try annotating its type. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/item_used_without_import/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/item_used_without_import/test.toml new file mode 100644 index 00000000000..1d634fdaae6 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/item_used_without_import/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()Could not find symbol "Bar" in this scope. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/literal_too_large_for_type/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/literal_too_large_for_type/test.toml new file mode 100644 index 00000000000..2b0c9358bb7 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/literal_too_large_for_type/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: let x:u8 = 256; +# nextln: $()Literal value is too large for type u8. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_empty_arms/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_empty_arms/test.toml new file mode 100644 index 00000000000..b6567b12686 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_empty_arms/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: match foo { +# check: $()Non-exhaustive match expression. Missing patterns `_` diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/Forc.lock new file mode 100644 index 00000000000..9d09ce0f0ce --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/Forc.lock @@ -0,0 +1,4 @@ +[[package]] +name = 'match_expressions_multiple_rest' +source = 'root' +dependencies = [] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/Forc.toml new file mode 100644 index 00000000000..4fa8087584a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/Forc.toml @@ -0,0 +1,6 @@ +[project] +authors = ["Fuel Labs "] +license = "Apache-2.0" +name = "match_expressions_multiple_rest" +entry = "main.sw" +implicit-std = false diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/src/main.sw new file mode 100644 index 00000000000..435271e4ea8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/src/main.sw @@ -0,0 +1,21 @@ +script; + +struct Point { + x: u64, + y: u64 +} + +// this should fail because of multiple rest patterns + +fn main() -> u64 { + let p = Point { + x: 1u64, + y: 2u64, + }; + + match p { + Point { x, .., .. } => { x }, + }; + + 0 +} diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/test.toml new file mode 100644 index 00000000000..04dc0251c08 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_multiple_rest/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: Point { x, .., .. } => { x }, +# nextln: $()Unexpected rest token, must be at the end of pattern. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_non_exhaustive/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_non_exhaustive/Forc.toml index afca886f469..fcbca473c18 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_non_exhaustive/Forc.toml +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_non_exhaustive/Forc.toml @@ -6,4 +6,4 @@ entry = "main.sw" implicit-std = false [dependencies] -core = { path = "../../../../../../../sway-lib-core" } +core = { path = "../../../../../../sway-lib-core" } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_non_exhaustive/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_non_exhaustive/test.toml new file mode 100644 index 00000000000..dc269da044e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_non_exhaustive/test.toml @@ -0,0 +1,34 @@ +category = "fail" + +# check: match_expressions_non_exhaustive/src/main.sw:41:9 +# check: $()This match arm is unreachable. + +# check: match_expressions_non_exhaustive/src/main.sw:61:9 +# check: $()This match arm is unreachable. + +# check: match_expressions_non_exhaustive/src/main.sw:90:9 +# check: $()This match arm is unreachable. + +# check: match_expressions_non_exhaustive/src/main.sw:95:9 +# check: $()This match arm is unreachable. + +# check: match_expressions_non_exhaustive/src/main.sw:101:9 +# check: $()This match arm is unreachable. + +# check: match_expressions_non_exhaustive/src/main.sw:107:9 +# check: $()This match arm is unreachable. + +# check: match_expressions_non_exhaustive/src/main.sw:37:13 +# check: $()Non-exhaustive match expression. Missing patterns `[1...4]`, `[6...9]`, `[11...MAX]` + +# check: match_expressions_non_exhaustive/src/main.sw:58:13 +# check: $()Non-exhaustive match expression. Missing patterns `(_, [2...MAX])` + +# check: match_expressions_non_exhaustive/src/main.sw:88:15 +# check: $()Non-exhaustive match expression. Missing patterns `Point { x: [MIN...2], ... }`, `Point { x: [4...MAX], ... }` + +# check: match_expressions_non_exhaustive/src/main.sw:122:15 +# check: $()Non-exhaustive match expression. Missing patterns `CrazyPoint { p1: Point { x: [1...MAX], ... }, ... }` + +# check: match_expressions_non_exhaustive/src/main.sw:128:16 +# check: $()Variable "newvariable" does not exist in this scope. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/Forc.lock new file mode 100644 index 00000000000..6ac4d6904b7 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/Forc.lock @@ -0,0 +1,4 @@ +[[package]] +name = 'match_expressions_rest' +source = 'root' +dependencies = [] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/Forc.toml new file mode 100644 index 00000000000..45f46589afa --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/Forc.toml @@ -0,0 +1,6 @@ +[project] +authors = ["Fuel Labs "] +license = "Apache-2.0" +name = "match_expressions_rest" +entry = "main.sw" +implicit-std = false \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/src/main.sw new file mode 100644 index 00000000000..c5e59de34ba --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/src/main.sw @@ -0,0 +1,21 @@ +script; + +struct Point { + x: u64, + y: u64 +} + +// this should fail because rest patterns must appear at the end + +fn main() -> u64 { + let p = Point { + x: 1u64, + y: 2u64, + }; + + match p { + Point { .., x } => { x }, + }; + + 0 +} diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/test.toml new file mode 100644 index 00000000000..7501cdefb60 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_rest/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: Point { .., x } => { x }, +# nextnl: $()Unexpected rest token, must be at the end of pattern. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/Forc.lock new file mode 100644 index 00000000000..8e5e18d3779 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/Forc.lock @@ -0,0 +1,4 @@ +[[package]] +name = 'match_expressions_struct_missing_fields' +source = 'root' +dependencies = [] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/Forc.toml new file mode 100644 index 00000000000..d1567bb5d7f --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/Forc.toml @@ -0,0 +1,6 @@ +[project] +authors = ["Fuel Labs "] +license = "Apache-2.0" +name = "match_expressions_struct_missing_fields" +entry = "main.sw" +implicit-std = false diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/src/main.sw new file mode 100644 index 00000000000..e02dfadc65f --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/src/main.sw @@ -0,0 +1,21 @@ +script; + +struct Point { + x: u64, + y: u64 +} + +// this should fail because the pattern is missing the y field + +fn main() -> u64 { + let p = Point { + x: 1u64, + y: 2u64, + }; + + match p { + Point { x } => { x }, + }; + + 0 +} diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/test.toml new file mode 100644 index 00000000000..ccbb454563e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_struct_missing_fields/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: Point { x } => { x }, +# nextln: $()Pattern does not mention field: y diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_wrong_struct/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_wrong_struct/test.toml new file mode 100644 index 00000000000..e252282fdeb --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/match_expressions_wrong_struct/test.toml @@ -0,0 +1,21 @@ +category = "fail" + +# check: Point { x: 3, y } => { y }, +# nextln: $()Mismatched types. +# nextln: $()expected: u64 +# nextln: $()found: Point. + +# check: Point { x: 3, y: 4 } => { 24 }, + +# check: Point { x: 3, y: 4 } => { 24 }, +# nextln: $()Mismatched types. +# nextln: $()expected: u64 +# nextln: $()found: Point. + +# check: Data { value: 1u64 } => { false }, +# nextln: $()Mismatched types. +# nextln: $()expected: bool +# nextln: $()found: u64. + +# check: Bar(x) => x, +# nextln: $()Enum with name "Bar" could not be found in this scope. Perhaps you need to import it? diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/method_requires_mut_var/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/method_requires_mut_var/test.toml new file mode 100644 index 00000000000..3aed4430d63 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/method_requires_mut_var/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()Cannot call method "f" on variable "a" because "a" is not declared as mutable. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/missing_fn_arguments/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/missing_fn_arguments/Forc.lock index e70083b0957..8251330264b 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/missing_fn_arguments/Forc.lock +++ b/test/src/e2e_vm_tests/test_programs/should_fail/missing_fn_arguments/Forc.lock @@ -1,4 +1,9 @@ +[[package]] +name = 'core' +source = 'path+from-root-535272951E66DE82' +dependencies = [] + [[package]] name = 'missing_fn_arguments' source = 'root' -dependencies = [] +dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/missing_fn_arguments/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/missing_fn_arguments/Forc.toml index 29c68a014d5..9884bd8cdf0 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/missing_fn_arguments/Forc.toml +++ b/test/src/e2e_vm_tests/test_programs/should_fail/missing_fn_arguments/Forc.toml @@ -3,4 +3,6 @@ authors = ["Fuel Labs "] license = "Apache-2.0" name = "missing_fn_arguments" entry = "main.sw" -implicit-std = false + +[dependencies] +core = { path = "../../../../../../sway-lib-core" } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/missing_fn_arguments/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/missing_fn_arguments/test.toml new file mode 100644 index 00000000000..78706fc66b8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/missing_fn_arguments/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: fn bar(a: bool, b: u64) -> u64 { +# check: $()Function "bar" expects 2 arguments but you provided 1. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/missing_func_from_supertrait_impl/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/missing_func_from_supertrait_impl/test.toml new file mode 100644 index 00000000000..58d89c982d4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/missing_func_from_supertrait_impl/test.toml @@ -0,0 +1,6 @@ +category = "fail" + +# check: impl A for Y { +# nextln: fn a1() { } +# nextln: } +# nextln: $()Functions are missing from this trait implementation: a2 diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/missing_supertrait_impl/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/missing_supertrait_impl/test.toml new file mode 100644 index 00000000000..767b0f221fb --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/missing_supertrait_impl/test.toml @@ -0,0 +1,7 @@ +category = "fail" + +# check: missing_supertrait_impl/src/main.sw:38:1 +# check: $()The trait "A" is not implemented for type "Y" + +# check: missing_supertrait_impl/src/main.sw:7:7 +# check: $()Implementation of trait "A" is required by this bound in "B" diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/multiple_impl_abi/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/multiple_impl_abi/test.toml new file mode 100644 index 00000000000..7cefb4fc483 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/multiple_impl_abi/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()Function "test_function" was already defined in scope. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/multiple_impl_fns/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/multiple_impl_fns/test.toml new file mode 100644 index 00000000000..44eed002998 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/multiple_impl_fns/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: $()Function "foo" was already defined in scope. +# check: $()Function "bar" was already defined in scope. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/name_shadowing/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/name_shadowing/test.toml new file mode 100644 index 00000000000..5fe291769f2 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/name_shadowing/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: struct S +# nextln: $()The name "S" shadows another symbol with the same name. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/nested_impure/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/nested_impure/test.toml new file mode 100644 index 00000000000..3d74ee999ca --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/nested_impure/test.toml @@ -0,0 +1,10 @@ +category = "fail" + +# check: baz(); +# nextln: $()This returns a value of type u64, which is not assigned to anything and is ignored. + +# check: let z = baz(); +# nextln: $()Storage attribute access mismatch. Try giving the surrounding function more access by adding "#[storage(read)]" to the function declaration. + +# check: baz(); +# nextln: $()Storage attribute access mismatch. Try giving the surrounding function more access by adding "#[storage(read)]" to the function declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/Forc.lock new file mode 100644 index 00000000000..a7f26464081 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/Forc.lock @@ -0,0 +1,9 @@ +[[package]] +name = 'core' +source = 'path+from-root-BC4E87DB22234D76' +dependencies = [] + +[[package]] +name = 'repeated_storage_field' +source = 'root' +dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/Forc.toml new file mode 100644 index 00000000000..38cf33b2e6f --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "repeated_storage_field" + +[dependencies] +core = { path = "../../../../../../sway-lib-core" } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/src/main.sw new file mode 100644 index 00000000000..45059447327 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/src/main.sw @@ -0,0 +1,19 @@ +contract; + +use core::*; + +storage { + x: u64 = 5 + 5, + y: u64 = 5 + 5, +} + +abi Test { + fn foo(); +} + +impl Test for Contract { + fn foo() { + storage.x += 1; + storage.y += 1; + } +} diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/test.toml new file mode 100644 index 00000000000..590c5b515ca --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/nonconst_storage_init/test.toml @@ -0,0 +1,9 @@ +category = "fail" + +# check: x: u64 = 5 + 5 +# nextln: $()Could not evaluate initializer to a const declaration. +# nextln: y: u64 = 5 + 5 + +# check: x: u64 = 5 + 5 +# nextln: y: u64 = 5 + 5 +# nextln: $()Could not evaluate initializer to a const declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/predicate_calls_impure/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/predicate_calls_impure/test.toml new file mode 100644 index 00000000000..821441f552a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/predicate_calls_impure/test.toml @@ -0,0 +1,9 @@ +category = "fail" + +# check: #[storage(read,write)] +# nextln: fn foo() { +# nextln: $()Impure function inside of non-contract. Contract storage is only accessible from contracts. + +# check: #[storage(read, write)] +# nextln: fn main() -> bool { +# nextln: $()Impure function inside of non-contract. Contract storage is only accessible from contracts. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/primitive_type_argument/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/primitive_type_argument/test.toml new file mode 100644 index 00000000000..d571364518f --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/primitive_type_argument/test.toml @@ -0,0 +1,7 @@ +category = "fail" + +# check: let b = foo::baz::ExampleStruct:: { a_field: 5u64 }; +# nextln: $()Mismatched types. +# nextln: $()expected: bool +# nextln: $()found: u64. +# nextln: $()help: Struct field's type must match up with the type specified in its declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/pure_calls_impure/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/pure_calls_impure/test.toml new file mode 100644 index 00000000000..03b6bb19cd1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/pure_calls_impure/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: impure_function(); +# nextln: $()Storage attribute access mismatch. Try giving the surrounding function more access by adding "#[storage(write)]" to the function declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/recursive_calls/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/recursive_calls/test.toml new file mode 100644 index 00000000000..a8f5ea67fc5 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/recursive_calls/test.toml @@ -0,0 +1,8 @@ +category = "fail" + +# check: $()Function a is recursive, which is unsupported at this time. +# check: $()Function b is recursive via c, which is unsupported at this time. +# check: $()Function c is recursive via b, which is unsupported at this time. +# check: $()Function d is recursive via e and f, which is unsupported at this time. +# check: $()Function e is recursive via f and d, which is unsupported at this time. +# check: $()Function f is recursive via d and e, which is unsupported at this time. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/recursive_enum/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/recursive_enum/test.toml new file mode 100644 index 00000000000..bd9a57f4949 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/recursive_enum/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()recursive types are not supported diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/recursive_struct/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/recursive_struct/test.toml new file mode 100644 index 00000000000..bd9a57f4949 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/recursive_struct/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()recursive types are not supported diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/recursive_type_chain/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/recursive_type_chain/test.toml new file mode 100644 index 00000000000..144ac44e200 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/recursive_type_chain/test.toml @@ -0,0 +1,12 @@ +category = "fail" + +# check: $()Type F is recursive via G and E, which is unsupported at this time. +# check: $()Type G is recursive via E and F, which is unsupported at this time. +# check: $()Type E is recursive via F and G, which is unsupported at this time. +# check: $()Type I is recursive via H, which is unsupported at this time. +# check: $()Type H is recursive via I, which is unsupported at this time. +# check: $()Type T is recursive via S, which is unsupported at this time. +# check: $()Type S is recursive via T, which is unsupported at this time. +# check: $()Type Y is recursive via Z and X, which is unsupported at this time. +# check: $()Type Z is recursive via X and Y, which is unsupported at this time. +# check: $()Type X is recursive via Y and Z, which is unsupported at this time. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/repeated_enum_variant/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/repeated_enum_variant/test.toml new file mode 100644 index 00000000000..2a730600ada --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/repeated_enum_variant/test.toml @@ -0,0 +1,10 @@ +category = "fail" + +# check: A: u64, +# nextln: A: b256, +# nextln: $()enum variant "A" already declared +# nextln: A: str[4], + +# check: A: b256, +# nextln: A: str[4], +# nextln: $()enum variant "A" already declared diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/repeated_storage_field/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/repeated_storage_field/test.toml new file mode 100644 index 00000000000..10152bc4100 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/repeated_storage_field/test.toml @@ -0,0 +1,10 @@ +category = "fail" + +# check: x: u64, +# nextln: x: b256, +# nextln: $()storage field "x" already declared +# nextln: x: str[4], + +# check: x: b256, +# nextln: x: str[4], +# nextln: $()storage field "x" already declared diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/repeated_struct_field/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/repeated_struct_field/test.toml new file mode 100644 index 00000000000..30361780425 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/repeated_struct_field/test.toml @@ -0,0 +1,9 @@ +category = "fail" + +# check: x: b256, +# nextln: $()struct field "x" already declared +# nextln: x: str[4], + +# check: x: b256, +# nextln: x: str[4], +# nextln: $()struct field "x" already declared diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/Forc.lock new file mode 100644 index 00000000000..d85ecc65184 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/Forc.lock @@ -0,0 +1,4 @@ +[[package]] +name = 'reserved_identifiers' +source = 'root' +dependencies = [] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/Forc.toml new file mode 100644 index 00000000000..a5c653793d8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/Forc.toml @@ -0,0 +1,6 @@ +[project] +authors = ["Fuel Labs "] +license = "Apache-2.0" +name = "reserved_identifiers" +entry = "main.sw" +implicit-std = false diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/src/main.sw new file mode 100644 index 00000000000..00f81f2f5a9 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/src/main.sw @@ -0,0 +1,39 @@ +script; + +// this should fail with an `Identifiers cannot be a reserved keyword.` error + +fn main() { + let mut script = 0; + let mut contract = 0; + let mut predicate = 0; + let mut library = 0; + let mut dep = 0; + let mut pub = 0; + let mut use = 0; + let mut as = 0; + let mut struct = 0; + let mut enum = 0; + let mut self = 0; + let mut fn = 0; + let mut trait = 0; + let mut impl = 0; + let mut for = 0; + let mut abi = 0; + let mut const = 0; + let mut storage = 0; + let mut str = 0; + let mut asm = 0; + let mut return = 0; + let mut if = 0; + let mut else = 0; + let mut match = 0; + let mut mut = 0; + let mut let = 0; + let mut while = 0; + let mut where = 0; + let mut ref = 0; + let mut deref = 0; + let mut true = 0; + let mut false = 0; +} + diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/test.toml new file mode 100644 index 00000000000..139bed5c848 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/reserved_identifiers/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: let mut script = 0; +# nextln: $()Identifiers cannot be a reserved keyword. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/script_calls_impure/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/script_calls_impure/test.toml new file mode 100644 index 00000000000..6f476a5773d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/script_calls_impure/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: fn main() {} +# nextln: $()Impure function inside of non-contract. Contract storage is only accessible from contracts. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/shadow_import/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/shadow_import/test.toml new file mode 100644 index 00000000000..c7089fb2650 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/shadow_import/test.toml @@ -0,0 +1,6 @@ +category = "fail" + +# check: $()The name "Foo" shadows another symbol with the same name. +# check: $()The name "Bar2" shadows another symbol with the same name. +# check: $()The name "Bar1" imported through `*` shadows another symbol with the same name. +# check: $()The name "Bar2" imported through `*` shadows another symbol with the same name. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/star_import_alias/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/star_import_alias/src/main.sw index 02c9c0381e9..53184b8514f 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/star_import_alias/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_fail/star_import_alias/src/main.sw @@ -3,7 +3,7 @@ script; dep bar; // This should not compile but `use ::bar::*;` should -use ::bar::{* as all); +use ::bar::{* as all}; fn main() -> bool { false diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/star_import_alias/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/star_import_alias/test.toml new file mode 100644 index 00000000000..9cfcdfdfcb2 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/star_import_alias/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: use ::bar::{* as all}; +# nextln: $()Expected `,`. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/storage_conflict/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/storage_conflict/test.toml new file mode 100644 index 00000000000..1e3038ea24f --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/storage_conflict/test.toml @@ -0,0 +1,49 @@ +category = "fail" + +# check: storage_conflict/src/main.sw:103:4 +# check: $()This function performs a storage read but does not have the required attribute(s). Try adding "#[storage(read)]" to the function declaration. + +# check: storage_conflict/src/main.sw:46:4 +# check: $()This function performs a storage read but does not have the required attribute(s). Try adding "#[storage(read)]" to the function declaration. + +# check: storage_conflict/src/main.sw:33:4 +# check: $()This function performs a storage read but does not have the required attribute(s). Try adding "#[storage(read)]" to the function declaration. + +# check: storage_conflict/src/main.sw:13:5 +# check: $()This function performs a storage read but does not have the required attribute(s). Try adding "#[storage(read)]" to the function declaration. + +# check: storage_conflict/src/main.sw:112:4 +# check: $()This function performs a storage read but does not have the required attribute(s). Try adding "#[storage(read)]" to the function declaration. + +# check: storage_conflict/src/main.sw:57:4 +# check: $()This function performs a storage read but does not have the required attribute(s). Try adding "#[storage(read)]" to the function declaration. + +# check: storage_conflict/src/main.sw:53:4 +# check: $()This function performs a storage read but does not have the required attribute(s). Try adding "#[storage(read)]" to the function declaration. + +# check: storage_conflict/src/main.sw:16:5 +# check: $()This function performs a storage read but does not have the required attribute(s). Try adding "#[storage(read)]" to the function declaration. + +# check: storage_conflict/src/main.sw:123:4 +# check: $()This function performs a storage write but does not have the required attribute(s). Try adding "#[storage(write)]" to the function declaration. + +# check: storage_conflict/src/main.sw:71:4 +# check: $()This function performs a storage write but does not have the required attribute(s). Try adding "#[storage(write)]" to the function declaration. + +# check: storage_conflict/src/main.sw:64:4 +# check: $()This function performs a storage write but does not have the required attribute(s). Try adding "#[storage(write)]" to the function declaration. + +# check: storage_conflict/src/main.sw:19:5 +# check: $()This function performs a storage write but does not have the required attribute(s). Try adding "#[storage(write)]" to the function declaration. + +# check: storage_conflict/src/main.sw:129:4 +# check: $()This function performs a storage write but does not have the required attribute(s). Try adding "#[storage(write)]" to the function declaration. + +# check: storage_conflict/src/main.sw:87:4 +# check: $()This function performs a storage write but does not have the required attribute(s). Try adding "#[storage(write)]" to the function declaration. + +# check: storage_conflict/src/main.sw:82:4 +# check: $()This function performs a storage write but does not have the required attribute(s). Try adding "#[storage(write)]" to the function declaration. + +# check: storage_conflict/src/main.sw:22:5 +# check: $()This function performs a storage write but does not have the required attribute(s). Try adding "#[storage(write)]" to the function declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/storage_in_library/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/storage_in_library/test.toml new file mode 100644 index 00000000000..7c702fd78b3 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/storage_in_library/test.toml @@ -0,0 +1,9 @@ +category = "fail" + +# Skip the first warning. +# check: storage { + +# check: storage { +# nextln: item: u64, +# nextln: } +# nextln: $()Declaring storage in a library is not allowed. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/storage_in_predicate/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/storage_in_predicate/test.toml new file mode 100644 index 00000000000..35eb83848ea --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/storage_in_predicate/test.toml @@ -0,0 +1,9 @@ +category = "fail" + +# Skip the warning. +# check: storage { + +# check: storage { +# nextln: item: u64, +# nextln: } +# nextln: $()Declaring storage in a predicate is not allowed. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/storage_in_script/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/storage_in_script/test.toml new file mode 100644 index 00000000000..31e74c5d3a9 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/storage_in_script/test.toml @@ -0,0 +1,9 @@ +category = "fail" + +# Skip the warning. +# check: storage { + +# check: storage { +# nextln: item: u64, +# nextln: } +# nextln: $()Declaring storage in a script is not allowed. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/storage_ops_in_library/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/storage_ops_in_library/test.toml new file mode 100644 index 00000000000..118b1b04091 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/storage_ops_in_library/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: do_storage::side_effects(); +# nextln: $()Storage attribute access mismatch. Try giving the surrounding function more access by adding "#[storage(read, write)]" to the function declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/supertrait_does_not_exist/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/supertrait_does_not_exist/test.toml new file mode 100644 index 00000000000..80361299483 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/supertrait_does_not_exist/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()Could not find symbol "C" in this scope. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/top_level_vars/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/top_level_vars/test.toml new file mode 100644 index 00000000000..2fe9a82d29e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/top_level_vars/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: let mut forbidden = true; +# nextln: $()Expected an item. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/trait_impl_purity_mismatch/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/trait_impl_purity_mismatch/test.toml new file mode 100644 index 00000000000..b637b2660de --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/trait_impl_purity_mismatch/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +# check: $()Storage attribute access mismatch. The trait function "f" in trait "A" requires the storage attribute(s) #[storage(read)]. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/trait_method_signature_mismatch/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/trait_method_signature_mismatch/test.toml new file mode 100644 index 00000000000..7e008750474 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/trait_method_signature_mismatch/test.toml @@ -0,0 +1,5 @@ +category = "fail" + +# check: fn foo(s: str[7]) -> str[7] { +# nextln: $()Expected: u64 +# nextln: $()found: str[7]. The definition of this function must match the one in the trait declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/trait_pure_calls_impure/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/trait_pure_calls_impure/test.toml new file mode 100644 index 00000000000..4df8d76a952 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/trait_pure_calls_impure/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: self.f() +# nextln: $()Storage attribute access mismatch. Try giving the surrounding function more access by adding "#[storage(read)]" to the function declaration. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/type_mismatch_error_message/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/type_mismatch_error_message/test.toml new file mode 100644 index 00000000000..4ebee880ac8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/type_mismatch_error_message/test.toml @@ -0,0 +1,4 @@ +category = "fail" + +# check: foo.does_not_exist(); +# nextln: $()No method named "does_not_exist" found for type "Result, str[4]>". diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/unify_identical_unknowns/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/unify_identical_unknowns/test.toml new file mode 100644 index 00000000000..a7fd835cbe0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/unify_identical_unknowns/test.toml @@ -0,0 +1,8 @@ +category = "fail" + +# check: impl Foo for NonExistant { +# nextln: $()Could not find symbol "NonExistant" in this scope. + +# check: impl Foo for NonExistant { +# nextln: $()Unknown type name "NonExistant". + diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/vec/.gitignore b/test/src/e2e_vm_tests/test_programs/should_fail/vec/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/vec/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/vec/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/vec/Forc.lock new file mode 100644 index 00000000000..3916e287d8f --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/vec/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-E8B33641BFB485A7' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-E8B33641BFB485A7' +dependencies = ['core'] + +[[package]] +name = 'vec' +source = 'root' +dependencies = ['std'] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/vec/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/vec/Forc.toml new file mode 100644 index 00000000000..13a336e9b6a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/vec/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "vec" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/vec/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/vec/src/main.sw new file mode 100644 index 00000000000..f8ce94627b0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/vec/src/main.sw @@ -0,0 +1,113 @@ +script; + +use std::{assert::assert, hash::sha256, option::Option, revert::revert, vec::Vec}; + +struct SimpleStruct { + x: u32, + y: b256, +} + +enum SimpleEnum { + X: (), + Y: b256, + Z: (b256, + b256), +} + +fn main() -> bool { + test_vector_new_u8(); + true +} + +fn test_vector_new_u8() { + let mut vector = ~Vec::new(); + + let number0 = 0u8; + let number1 = 1u8; + let number2 = 2u8; + let number3 = 3u8; + let number4 = 4u8; + let number5 = 5u8; + let number6 = 6u8; + let number7 = 7u8; + let number8 = 8u8; + + assert(vector.len() == 0); + assert(vector.capacity() == 0); + assert(vector.is_empty()); + + vector.push(number0); + vector.push(number1); + vector.push(number2); + vector.push(number3); + vector.push(number4); + vector.push(false); + + assert(vector.len() == 5); + assert(vector.capacity() == 8); + assert(vector.is_empty() == false); + + match vector.get(0) { + Option::Some(val) => assert(val == number0), Option::None => revert(0), + } + + // Push after get + vector.push(number5); + vector.push(number6); + vector.push(number7); + vector.push(number8); + vector.push("this should break it 1"); + + match vector.get(4) { + Option::Some(val) => assert(val == number4), Option::None => revert(0), + } + + match vector.get(number6) { + Option::Some(val) => assert(val == number6), Option::None => revert(0), + } + + assert(vector.len() == 9); + assert(vector.capacity() == 16); + assert(!vector.is_empty()); + + // Test after capacity change + match vector.get(4) { + Option::Some(val) => assert(val == number4), Option::None => revert(0), + } + + match vector.get(6) { + Option::Some(val) => assert(val == number6), Option::None => revert(0), + } + + vector.clear(); + + // Empty after clear + assert(vector.len() == 0); + assert(vector.capacity() == 16); + assert(vector.is_empty() == true); + + match vector.get(0) { + Option::Some(val) => revert(0), Option::None => (), + } + + // Make sure pushing again after clear() works + vector.push(number0); + vector.push(number1); + vector.push(number2); + vector.push(number3); + vector.push(number4); + vector.push("this should break it 2"); + + assert(vector.len() == 5); + assert(vector.capacity() == 16); + assert(vector.is_empty() == false); + + match vector.get(4) { + Option::Some(val) => assert(val == number4), Option::None => revert(0), + } + + // Out of bounds access + match vector.get(5) { + Option::Some(val) => revert(0), Option::None => (), + } +} diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/vec/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/vec/test.toml new file mode 100644 index 00000000000..475acca21e9 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/vec/test.toml @@ -0,0 +1,10 @@ +category = "fail" + +# check: vector.push(false); +# nextln: $()This parameter was declared as type u8, but argument of type bool was provided. + +# check: vector.push("this should break it 1"); +# nextln: $()This parameter was declared as type u8, but argument of type str[22] was provided. + +# check: vector.push("this should break it 2"); +# nextln: $()This parameter was declared as type u8, but argument of type str[22] was provided. diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_package_field/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_package_field/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_package_field/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/Forc.lock new file mode 100644 index 00000000000..e77c645a332 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-B0CAE5E4D7DDF437' +dependencies = [] + +[[package]] +name = 'dependency_patching' +source = 'root' +dependencies = ['std'] + +[[package]] +name = 'std' +source = 'path+from-root-B0CAE5E4D7DDF437' +dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/Forc.toml new file mode 100644 index 00000000000..81c9f831690 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/Forc.toml @@ -0,0 +1,10 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "dependency_patching" + +[dependencies] + +[patch.'https://github.com/fuellabs/sway'] +std = { path = "../../../../../../../sway-lib-std" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/json_abi_oracle.json new file mode 100644 index 00000000000..905c3bd1034 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/json_abi_oracle.json @@ -0,0 +1,14 @@ +[ + { + "inputs": [], + "name": "main", + "outputs": [ + { + "components": null, + "name": "", + "type": "u64" + } + ], + "type": "function" + } +] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/src/main.sw new file mode 100644 index 00000000000..d0db44707ba --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/src/main.sw @@ -0,0 +1,5 @@ +script; + +fn main() -> u64 { + 0 +} diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/test.toml new file mode 100644 index 00000000000..6a5d9de5715 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/forc/dependency_patching/test.toml @@ -0,0 +1 @@ +category = "compile" \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/abort_control_flow/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/abort_control_flow/test.toml new file mode 100644 index 00000000000..83885a3255b --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/abort_control_flow/test.toml @@ -0,0 +1 @@ +category = "disabled" diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/abort_control_flow_good/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/abort_control_flow_good/test.toml new file mode 100644 index 00000000000..665debb3bf8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/abort_control_flow_good/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "revert", value = 42 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/aliased_imports/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/aliased_imports/test.toml new file mode 100644 index 00000000000..b7a79f9a8c0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/aliased_imports/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 42 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/array_basics/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/array_basics/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/array_basics/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/array_dynamic_oob/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/array_dynamic_oob/test.toml new file mode 100644 index 00000000000..83885a3255b --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/array_dynamic_oob/test.toml @@ -0,0 +1 @@ +category = "disabled" diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/array_generics/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/array_generics/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/array_generics/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/asm_expr_basic/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/asm_expr_basic/test.toml new file mode 100644 index 00000000000..d8186a90d45 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/asm_expr_basic/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 6 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/asm_without_return/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/asm_without_return/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/asm_without_return/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/b256_bad_jumps/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/b256_bad_jumps/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/b256_bad_jumps/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/b256_bitwise_ops/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/b256_bitwise_ops/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/b256_bitwise_ops/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/b256_ops/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/b256_ops/test.toml new file mode 100644 index 00000000000..2297098e50e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/b256_ops/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 100 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/basic_func_decl/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/basic_func_decl/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/basic_func_decl/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/basic_predicate/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/basic_predicate/test.toml new file mode 100644 index 00000000000..bb916e5c72e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/basic_predicate/test.toml @@ -0,0 +1,2 @@ +category = "run" +expected_result = { action = "return", value = 1 } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/binary_and_hex_literals/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/binary_and_hex_literals/test.toml new file mode 100644 index 00000000000..83885a3255b --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/binary_and_hex_literals/test.toml @@ -0,0 +1 @@ +category = "disabled" diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/bool_and_or/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/bool_and_or/test.toml new file mode 100644 index 00000000000..b7a79f9a8c0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/bool_and_or/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 42 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/builtin_type_method_call/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/builtin_type_method_call/test.toml new file mode 100644 index 00000000000..a9e475bbda3 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/builtin_type_method_call/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 3 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/chained_if_let/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/chained_if_let/test.toml new file mode 100644 index 00000000000..5338339c8cb --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/chained_if_let/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 5 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/const_decl/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/const_decl/test.toml new file mode 100644 index 00000000000..2297098e50e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/const_decl/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 100 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/const_decl_in_library/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/const_decl_in_library/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/const_decl_in_library/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/const_inits/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/const_inits/src/main.sw index d4119b8f76d..ed15138eea7 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/const_inits/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/const_inits/src/main.sw @@ -36,17 +36,22 @@ const EN1c = En1::NoVal; const ETH_ID0_VALUE = ETH_ID0.value; const TUP1_idx2 = TUP1.2; +const INT1 = 1; + fn main() -> u64 { + const int1 = 1; + assert(int1 == INT1); + // initialization through function applications. - let eth_id0 = ~ContractId::from(0x0000000000000000000000000000000000000000000000000000000000000000); - let eth_id1 = ~ContractId::from(0x0000000000000000000000000000000000000000000000000000000000000001); + const eth_id0 = ~ContractId::from(0x0000000000000000000000000000000000000000000000000000000000000000); + const eth_id1 = ~ContractId::from(0x0000000000000000000000000000000000000000000000000000000000000001); assert(eth_id0 == ETH_ID0 && eth_id1 == ETH_ID1); // tuples and arrays. - let t1 = (2, 1, 21); + const t1 = (2, 1, 21); assert(t1.0 == TUP1.0 && t1.1 == TUP1.1 && t1.2 == TUP1.2); assert(t1.0 == TUP2.0 && t1.1 == TUP2.1 && t1.2 == TUP2.2); - let a1 = [1, 2, 3]; + const a1 = [1, 2, 3]; assert(a1[0] == ARR1[0] && a1[1] == ARR1[1] && a1[2] == ARR1[2]); assert(a1[0] == ARR2[0] && a1[1] == ARR2[1] && a1[2] == ARR2[2]); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/const_inits/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/const_inits/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/const_inits/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_caller_as_type/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_caller_as_type/test.toml new file mode 100644 index 00000000000..b7a79f9a8c0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_caller_as_type/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 42 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/dependencies/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/dependencies/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/dependencies/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/doc_strings/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/doc_strings/test.toml new file mode 100644 index 00000000000..83885a3255b --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/doc_strings/test.toml @@ -0,0 +1 @@ +category = "disabled" diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/empty_method_initializer/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/empty_method_initializer/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/empty_method_initializer/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_destructuring/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_destructuring/test.toml new file mode 100644 index 00000000000..be3b58f100f --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_destructuring/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 15 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_if_let/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_if_let/test.toml new file mode 100644 index 00000000000..365860c79fa --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_if_let/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 143 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_if_let_large_type/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_if_let_large_type/test.toml new file mode 100644 index 00000000000..be3b58f100f --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_if_let_large_type/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 15 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_in_fn_decl/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_in_fn_decl/test.toml new file mode 100644 index 00000000000..9820628e6d0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_in_fn_decl/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 255 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_init_fn_call/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_init_fn_call/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_init_fn_call/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_padding/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_padding/test.toml new file mode 100644 index 00000000000..37ba1bb3194 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_padding/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return_data", value = [ 0xce, 0x55, 0xff, 0x05, 0x11, 0x3a, 0x24, 0x2e, 0xc7, 0x9a, 0x23, 0x75, 0x0c, 0x7e, 0x2b, 0xab, 0xaf, 0x98, 0xa8, 0xdc, 0x41, 0x66, 0x90, 0xc8, 0x57, 0xdd, 0x31, 0x72, 0x0c, 0x74, 0x82, 0xb6 ] } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_type_inference/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_type_inference/test.toml new file mode 100644 index 00000000000..5338339c8cb --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/enum_type_inference/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 5 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_and_neq/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_and_neq/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_and_neq/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/Forc.lock new file mode 100644 index 00000000000..63ae381216c --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-987CA0C143EB9BCC' +dependencies = [] + +[[package]] +name = 'eq_intrinsic' +source = 'root' +dependencies = ['std'] + +[[package]] +name = 'std' +source = 'path+from-root-987CA0C143EB9BCC' +dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/Forc.toml new file mode 100644 index 00000000000..9d341be72f6 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "eq_intrinsic" + +[dependencies] +std = { path = "../../../../../../../sway-lib-std" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/json_abi_oracle.json new file mode 100644 index 00000000000..905c3bd1034 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/json_abi_oracle.json @@ -0,0 +1,14 @@ +[ + { + "inputs": [], + "name": "main", + "outputs": [ + { + "components": null, + "name": "", + "type": "u64" + } + ], + "type": "function" + } +] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/src/main.sw new file mode 100644 index 00000000000..9a81fd329d6 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/src/main.sw @@ -0,0 +1,39 @@ +script; + +use std::assert::assert; + +fn main() -> u64 { + + assert(__eq(true, true) == (true == true)); + assert(__eq(true, false) != (true != false)); + assert(__eq(true, true) == (true != false)); + + assert(__eq(1, 22) == (1 == 22)); + assert(__eq(1, 1) == (1 == 1)); + + let a: u8 = 1; + let b: u8 = 22; + let c: u8 = 1; + assert(__eq(a, b) == (a == b)); + assert(__eq(a, c) == (a == c)); + + let a: u16 = 1; + let b: u16 = 22; + let c: u16 = 1; + assert(__eq(a, b) == (a == b)); + assert(__eq(a, c) == (a == c)); + + let a: u32 = 1; + let b: u32 = 22; + let c: u32 = 1; + assert(__eq(a, b) == (a == b)); + assert(__eq(a, c) == (a == c)); + + let a: u64 = 1; + let b: u64 = 22; + let c: u64 = 1; + assert(__eq(a, b) == (a == b)); + assert(__eq(a, c) == (a == c)); + + 2 +} diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/test.toml new file mode 100644 index 00000000000..5617bb5d0a9 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/eq_intrinsic/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 2 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/fix_opcode_bug/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/fix_opcode_bug/test.toml new file mode 100644 index 00000000000..1cb4e3ba6f8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/fix_opcode_bug/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 30 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/funcs_with_generic_types/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/funcs_with_generic_types/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/funcs_with_generic_types/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic-type-inference/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic-type-inference/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic-type-inference/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_enum/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_enum/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_enum/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_functions/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_functions/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_functions/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_impl_self/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_impl_self/test.toml new file mode 100644 index 00000000000..1a37cf3ee4d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_impl_self/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 10 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_inside_generic/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_inside_generic/test.toml new file mode 100644 index 00000000000..b87306a6d45 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_inside_generic/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 7 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_struct/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_struct/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_struct/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_structs/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_structs/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_structs/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/if_elseif_enum/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/if_elseif_enum/test.toml new file mode 100644 index 00000000000..1a37cf3ee4d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/if_elseif_enum/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 10 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/if_implicit_unit/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/if_implicit_unit/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/if_implicit_unit/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/implicit_return/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/implicit_return/test.toml new file mode 100644 index 00000000000..b7a79f9a8c0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/implicit_return/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 42 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/import_method_from_other_file/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/import_method_from_other_file/test.toml new file mode 100644 index 00000000000..1a37cf3ee4d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/import_method_from_other_file/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 10 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/import_trailing_comma/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/import_trailing_comma/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/import_trailing_comma/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/Forc.lock new file mode 100644 index 00000000000..be0b990d571 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'const_inits' +source = 'root' +dependencies = ['std'] + +[[package]] +name = 'core' +source = 'path+from-root-76FD265A93458D61' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-76FD265A93458D61' +dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/Forc.toml new file mode 100644 index 00000000000..cc629f01013 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "const_inits" + +[dependencies] +std = { path = "../../../../../../../sway-lib-std" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/json_abi_oracle.json new file mode 100644 index 00000000000..905c3bd1034 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/json_abi_oracle.json @@ -0,0 +1,14 @@ +[ + { + "inputs": [], + "name": "main", + "outputs": [ + { + "components": null, + "name": "", + "type": "u64" + } + ], + "type": "function" + } +] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/src/main.sw new file mode 100644 index 00000000000..c2e2e8126f3 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/src/main.sw @@ -0,0 +1,90 @@ +script; + +use std::{assert::assert, logging::log}; + +enum Bool { + True: (), + False: (), +} + +fn foo(b: bool) -> u64 { + if b { + 101 + } else { + 102 + } +} + +fn bar(b: bool) -> u64 { + if b { + return 101; + } else { + return 102; + } +} + +fn bell(b: bool) -> u64 { + if b { + return 101; + } else { + 102 + } +} + +fn moo(b: bool) -> u64 { + if b { + 101 + } else { + return 102; + } +} + +fn poo(b: Bool) -> u64 { + if let Bool::True = b { + 101 + } else { + return 102; + } +} + +fn ran_out_of_names(b: Bool) -> u64 { + if let Bool::True = b { + return 101; + } else { + return 102; + } +} + +fn another_fn(b: Bool) -> u64 { + if let Bool::True = b { + return 101; + } else { + 102 + } +} + +fn thats_all(b: Bool) -> u64 { + if let Bool::True = b { + 101 + } else { + 102 + } +} + +fn main() -> u64 { + assert(foo(true) == bar(true)); + assert(foo(false) == bar(false)); + assert(foo(true) == bell(true)); + assert(foo(false) == bell(false)); + assert(foo(true) == moo(true)); + assert(foo(false) == moo(false)); + + assert(thats_all(Bool::True) == poo(Bool::True)); + assert(thats_all(Bool::False) == poo(Bool::False)); + assert(thats_all(Bool::True) == ran_out_of_names(Bool::True)); + assert(thats_all(Bool::False) == ran_out_of_names(Bool::False)); + assert(thats_all(Bool::True) == another_fn(Bool::True)); + assert(thats_all(Bool::False) == another_fn(Bool::False)); + + 2 +} diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/test.toml new file mode 100644 index 00000000000..5617bb5d0a9 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/impure_ifs/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 2 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/inline_if_expr_const/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/inline_if_expr_const/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/inline_if_expr_const/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/is_prime/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/is_prime/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/is_prime/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/is_reference_type/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/is_reference_type/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/is_reference_type/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/local_impl_for_ord/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/local_impl_for_ord/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/local_impl_for_ord/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/main_returns_unit/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/main_returns_unit/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/main_returns_unit/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/many_stack_variables/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/many_stack_variables/test.toml new file mode 100644 index 00000000000..1a37cf3ee4d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/many_stack_variables/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 10 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions/test.toml new file mode 100644 index 00000000000..b7a79f9a8c0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 42 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_enums/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_enums/test.toml new file mode 100644 index 00000000000..b7a79f9a8c0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_enums/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 42 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_inside_generic_functions/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_inside_generic_functions/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_inside_generic_functions/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_mismatched/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_mismatched/test.toml new file mode 100644 index 00000000000..5338339c8cb --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_mismatched/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 5 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_nested/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_nested/test.toml new file mode 100644 index 00000000000..2e6705c76d8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_nested/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 123 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/Forc.lock new file mode 100644 index 00000000000..589d3e975fc --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/Forc.lock @@ -0,0 +1,17 @@ +[[package]] +name = 'core' +source = 'path+from-root-E1D1F5F82094B853' +dependencies = [] + +[[package]] +name = 'match_expressions_rest' +source = 'root' +dependencies = [ + 'core', + 'std', +] + +[[package]] +name = 'std' +source = 'path+from-root-E1D1F5F82094B853' +dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/Forc.toml new file mode 100644 index 00000000000..03981c9887e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/Forc.toml @@ -0,0 +1,10 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "match_expressions_rest" +implicit-std = false + +[dependencies] +core = { path = "../../../../../../../sway-lib-core" } +std = { path = "../../../../../../../sway-lib-std" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/json_abi_oracle.json new file mode 100644 index 00000000000..905c3bd1034 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/json_abi_oracle.json @@ -0,0 +1,14 @@ +[ + { + "inputs": [], + "name": "main", + "outputs": [ + { + "components": null, + "name": "", + "type": "u64" + } + ], + "type": "function" + } +] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/src/main.sw new file mode 100644 index 00000000000..279e19af513 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/src/main.sw @@ -0,0 +1,64 @@ +script; + +struct Point { + x: u64, + y: u64 +} + +struct Point3D { + x: u64, + y: u64, + z: u64 +} + +struct Line { + p1: Point, + p2: Point +} + +enum Kind { + Point: Point, + Point3D: Point3D, + Line: Line +} + +fn main() -> u64 { + let p = Point { + x: 1u64, + y: 2u64, + }; + + match p { + Point { x, .. } => { x }, + }; + + let p2 = Point3D { + x: 1u64, + y: 2u64, + z: 3u64, + }; + + match p2 { + Point3D { x, .. } => { x }, + }; + + let l = Line { p1: p, p2: p }; + + match l { + Line { p1, .. } => {} + } + + match l { + Line { p1: Point { .. }, p2: Point { .. } } => {} + } + + let k = Kind::Point(p); + + match k { + Kind::Point(Point { x, .. }) => {}, + Kind::Point3D(Point3D { z, .. }) => {}, + Kind::Line(Line { p1: Point { .. }, p2: Point { .. } }) => {}, + } + + 0 +} diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_rest/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_simple/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_simple/test.toml new file mode 100644 index 00000000000..b7a79f9a8c0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_simple/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 42 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_structs/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_structs/test.toml new file mode 100644 index 00000000000..25d06220ec6 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_structs/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 4 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_with_self/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_with_self/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_with_self/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/method_on_empty_struct/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/method_on_empty_struct/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/method_on_empty_struct/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/missing_type_parameters/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/missing_type_parameters/test.toml new file mode 100644 index 00000000000..83885a3255b --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/missing_type_parameters/test.toml @@ -0,0 +1 @@ +category = "disabled" diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/modulo_uint_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/modulo_uint_test/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/modulo_uint_test/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/multi_impl_self/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/multi_impl_self/test.toml new file mode 100644 index 00000000000..b7a79f9a8c0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/multi_impl_self/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 42 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/multi_item_import/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/multi_item_import/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/multi_item_import/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/nested_structs/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/nested_structs/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/nested_structs/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/nested_while_and_if/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/nested_while_and_if/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/nested_while_and_if/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/new_allocator_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/new_allocator_test/test.toml new file mode 100644 index 00000000000..b7a79f9a8c0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/new_allocator_test/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 42 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/non_literal_const_decl/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/non_literal_const_decl/test.toml new file mode 100644 index 00000000000..b7a79f9a8c0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/non_literal_const_decl/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 42 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/numeric_constants/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/numeric_constants/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/numeric_constants/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/op_precedence/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/op_precedence/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/op_precedence/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/out_of_order_decl/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/out_of_order_decl/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/out_of_order_decl/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/primitive_type_argument/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/primitive_type_argument/test.toml new file mode 100644 index 00000000000..5338339c8cb --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/primitive_type_argument/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 5 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/Forc.lock new file mode 100644 index 00000000000..71928112b44 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/Forc.lock @@ -0,0 +1,9 @@ +[[package]] +name = 'core' +source = 'path+from-root-D97961F846794409' +dependencies = [] + +[[package]] +name = 'simple' +source = 'root' +dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/Forc.toml new file mode 100644 index 00000000000..fada1e39e43 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +license = "Apache-2.0" +name = "simple" +entry = "main.sw" + +[dependencies] +core = { path = "../../../../../../../sway-lib-core" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/json_abi_oracle.json new file mode 100644 index 00000000000..905c3bd1034 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/json_abi_oracle.json @@ -0,0 +1,14 @@ +[ + { + "inputs": [], + "name": "main", + "outputs": [ + { + "components": null, + "name": "", + "type": "u64" + } + ], + "type": "function" + } +] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/src/main.sw new file mode 100644 index 00000000000..9487c0610f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/src/main.sw @@ -0,0 +1,52 @@ +script; + +enum SomeEnum { + B: bool, +} + +fn main() -> u64 { + let mut r#script = 0; + let mut r#contract = 0; + let mut r#predicate = 0; + let mut r#library = 0; + let mut r#dep = 0; + let mut r#pub = 0; + let mut r#use = 0; + let mut r#as = 0; + let mut r#struct = 0; + let mut r#enum = 0; + let mut r#self = 0; + let mut r#fn = 0; + let mut r#trait = 0; + let mut r#impl = 0; + let mut r#for = 0; + let mut r#abi = 0; + let mut r#const = 0; + let mut r#storage = 0; + let mut r#str = 0; + let mut r#asm = 0; + let mut r#return = 0; + let mut r#if = 0; + let mut r#else = 0; + let mut r#match = 0; + let mut r#mut = 0; + let mut r#let = 0; + let mut r#while = 0; + let mut r#where = 0; + let mut r#ref = 0; + let mut r#deref = 0; + let mut r#true = 0; + let mut r#false = 0; + + let e = SomeEnum::B(false); + let v = match e { + SomeEnum::B(true) => { + 1 + }, + SomeEnum::B(false) => { + 0 + }, + }; + + 0 +} diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_identifiers/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/reassignment_operators/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/reassignment_operators/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/reassignment_operators/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/ret_small_string/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/ret_small_string/test.toml new file mode 100644 index 00000000000..af031908100 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/ret_small_string/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return_data", value = [ 0x6a, 0x4e, 0x01, 0xe9, 0x40, 0xab, 0xc0, 0x04, 0x30, 0xfe, 0x21, 0x62, 0xed, 0x69, 0xc0, 0xe2, 0x31, 0x04, 0xf9, 0xfd, 0xa7, 0x81, 0x59, 0x09, 0x2f, 0xea, 0x8f, 0x7e, 0xcb, 0x7f, 0x6d, 0xd4 ] } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/ret_string_in_struct/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/ret_string_in_struct/test.toml new file mode 100644 index 00000000000..c731ccb8160 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/ret_string_in_struct/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return_data", value = [ 0xaa, 0x5e, 0xfc, 0xa8, 0xda, 0xaf, 0x6e, 0xe6, 0x3f, 0x44, 0x93, 0xb2, 0x88, 0xb3, 0x85, 0xd7, 0x60, 0xb8, 0xef, 0x93, 0xdc, 0x70, 0xe0, 0xfb, 0xc3, 0x06, 0xed, 0x9b, 0x67, 0x6e, 0x5f, 0x13 ] } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/retd_b256/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/retd_b256/test.toml new file mode 100644 index 00000000000..4e4ff1e7d89 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/retd_b256/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return_data", value = [ 102, 104, 122, 173, 248, 98, 189, 119, 108, 143, 193, 139, 142, 159, 142, 32, 8, 151, 20, 133, 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, 41, 37 ] } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/retd_small_array/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/retd_small_array/test.toml new file mode 100644 index 00000000000..3f5cbab52bc --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/retd_small_array/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return_data", value = [ 0xcd, 0x26, 0x62, 0x15, 0x4e, 0x6d, 0x76, 0xb2, 0xb2, 0xb9, 0x2e, 0x70, 0xc0, 0xca, 0xc3, 0xcc, 0xf5, 0x34, 0xf9, 0xb7, 0x4e, 0xb5, 0xb8, 0x98, 0x19, 0xec, 0x50, 0x90, 0x83, 0xd0, 0x0a, 0x50 ] } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/retd_struct/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/retd_struct/test.toml new file mode 100644 index 00000000000..52c540afc9e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/retd_struct/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return_data", value = [ 251, 57, 24, 241, 63, 94, 17, 102, 252, 182, 8, 110, 140, 105, 102, 105, 138, 202, 155, 39, 97, 32, 94, 129, 141, 144, 190, 142, 33, 32, 33, 75 ] } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/retd_zero_len_array/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/retd_zero_len_array/test.toml new file mode 100644 index 00000000000..36374311dfd --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/retd_zero_len_array/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return_data", value = [ 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 ] } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/self_impl_reassignment/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/self_impl_reassignment/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/self_impl_reassignment/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/size_of/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/size_of/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/size_of/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/storage_declaration/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/storage_declaration/test.toml new file mode 100644 index 00000000000..83885a3255b --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/storage_declaration/test.toml @@ -0,0 +1 @@ +category = "disabled" diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/struct_field_access/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/struct_field_access/test.toml new file mode 100644 index 00000000000..652f09bfa94 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/struct_field_access/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 43 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/struct_field_reassignment/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/struct_field_reassignment/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/struct_field_reassignment/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/supertraits/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/supertraits/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/supertraits/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/trait_import_with_star/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/trait_import_with_star/test.toml new file mode 100644 index 00000000000..44ca8ea93c4 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/trait_import_with_star/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 0 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/trait_override_bug/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/trait_override_bug/test.toml new file mode 100644 index 00000000000..b87306a6d45 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/trait_override_bug/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 7 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_access/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_access/test.toml new file mode 100644 index 00000000000..b7a79f9a8c0 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_access/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 42 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_desugaring/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_desugaring/test.toml new file mode 100644 index 00000000000..a0f62749753 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_desugaring/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 9 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_field_reassignment/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_field_reassignment/test.toml new file mode 100644 index 00000000000..83bfb15bf1d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_field_reassignment/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 320 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_in_struct/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_in_struct/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_in_struct/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_indexing/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_indexing/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_indexing/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_single_element/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_single_element/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_single_element/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_types/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_types/test.toml new file mode 100644 index 00000000000..2e6705c76d8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/tuple_types/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 123 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/u64_ops/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/u64_ops/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/u64_ops/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/unary_not_basic/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/unary_not_basic/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/unary_not_basic/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/unary_not_basic_2/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/unary_not_basic_2/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/unary_not_basic_2/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/unit_type_variants/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/unit_type_variants/test.toml new file mode 100644 index 00000000000..28d8c97b878 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/unit_type_variants/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return_data", value = [ 0xcd, 0x04, 0xa4, 0x75, 0x44, 0x98, 0xe0, 0x6d, 0xb5, 0xa1, 0x3c, 0x5f, 0x37, 0x1f, 0x1f, 0x04, 0xff, 0x6d, 0x24, 0x70, 0xf2, 0x4a, 0xa9, 0xbd, 0x88, 0x65, 0x40, 0xe5, 0xdc, 0xe7, 0x7f, 0x70 ] } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/use_full_path_names/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/use_full_path_names/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/use_full_path_names/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/valid_impurity/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/valid_impurity/test.toml new file mode 100644 index 00000000000..6691150d9c8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/valid_impurity/test.toml @@ -0,0 +1,2 @@ +category = "compile" +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/while_loops/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/while_loops/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/while_loops/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/xos_opcode/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/xos_opcode/test.toml new file mode 100644 index 00000000000..83885a3255b --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/xos_opcode/test.toml @@ -0,0 +1 @@ +category = "disabled" diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/zero_field_types/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/zero_field_types/test.toml new file mode 100644 index 00000000000..1a37cf3ee4d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/zero_field_types/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 10 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/test.toml new file mode 100644 index 00000000000..853d71ea545 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/test.toml @@ -0,0 +1,3 @@ +category = "run_on_node" +expected_result = { action = "result", value = 1 } +contracts = ["should_pass/test_contracts/array_of_structs_contract"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/test.toml new file mode 100644 index 00000000000..044cb74c7da --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/test.toml @@ -0,0 +1,3 @@ +category = "run_on_node" +expected_result = { action = "result", value = 1 } +contracts = ["should_pass/test_contracts/balance_test_contract"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/test.toml new file mode 100644 index 00000000000..af526e80a7f --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/test.toml @@ -0,0 +1,3 @@ +category = "run_on_node" +expected_result = { action = "result", value = 1 } +contracts = ["should_pass/test_contracts/abi_with_tuples_contract"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/test.toml new file mode 100644 index 00000000000..6afc375bd5a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/test.toml @@ -0,0 +1,3 @@ +category = "run_on_node" +expected_result = { action = "result", value = 4242 } +contracts = ["should_pass/test_contracts/basic_storage"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/test.toml new file mode 100644 index 00000000000..4e73dff4cd8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/test.toml @@ -0,0 +1,3 @@ +category = "run_on_node" +expected_result = { action = "result", value = 1 } +contracts = ["should_pass/test_contracts/increment_contract"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/test.toml new file mode 100644 index 00000000000..258d74ac5fa --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/test.toml @@ -0,0 +1,3 @@ +category = "run_on_node" +expected_result = { action = "result", value = 1 } +contracts = ["should_pass/test_contracts/auth_testing_contract"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw index 8e44f68dbb1..dbfeb032b9b 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw @@ -8,13 +8,13 @@ fn main() -> bool { let gas: u64 = 1000; let amount: u64 = 11; let other_contract_id = ~ContractId::from(0x189a69c7ffc261ec84769563bdde047e592a33456acc079f189332c2837cba6b); - let base_asset_id = ~ContractId::from(BASE_ASSET_ID); + let base_asset_id = BASE_ASSET_ID; let test_contract = abi(ContextTesting, other_contract_id.into()); // test Context::contract_id(): let returned_contract_id = test_contract.get_id { - gas: gas, coins: 0, asset_id: BASE_ASSET_ID + gas: gas, coins: 0, asset_id: BASE_ASSET_ID.into() } (); assert(returned_contract_id.into() == other_contract_id.into()); @@ -22,14 +22,14 @@ fn main() -> bool { // @todo set up a test contract to mint some tokens for testing balances. // test Context::this_balance(): let returned_this_balance = test_contract.get_this_balance { - gas: gas, coins: 0, asset_id: BASE_ASSET_ID + gas: gas, coins: 0, asset_id: BASE_ASSET_ID.into() } (base_asset_id); assert(returned_this_balance == 0); // test Context::balance_of_contract(): let returned_contract_balance = test_contract.get_balance_of_contract { - gas: gas, coins: 0, asset_id: BASE_ASSET_ID + gas: gas, coins: 0, asset_id: BASE_ASSET_ID.into() } (base_asset_id, other_contract_id); assert(returned_contract_balance == 0); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/test.toml new file mode 100644 index 00000000000..093bb1be264 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/test.toml @@ -0,0 +1,3 @@ +category = "run_on_node" +expected_result = { action = "result", value = 1 } +contracts = ["should_pass/test_contracts/context_testing_contract"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/test.toml new file mode 100644 index 00000000000..559f02e1da5 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/test.toml @@ -0,0 +1,3 @@ +category = "run_on_node" +expected_result = { action = "result", value = 1 } +contracts = ["should_pass/test_contracts/get_storage_key_contract"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/test.toml new file mode 100644 index 00000000000..83885a3255b --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/test.toml @@ -0,0 +1 @@ +category = "disabled" diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw index 3b04f6fd4dc..b27bdd4318b 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw @@ -1,11 +1,55 @@ script; use storage_access_abi::*; -use std::{assert::assert, hash::sha256}; +use std::{assert::assert, hash::sha256, revert::revert}; fn main() -> bool { - let contract_id = 0x41b881e842026ed4f607156ddc0f98866944c4c67478ededb48932c578ddd52c; + let contract_id = 0x1c7c76380ef43c048596b4cda60eff2763d7c081b70d8662a3e1d18a9ee1dc2b; let caller = abi(StorageAccess, contract_id); + // Test initializers + assert(caller.get_x() == 64); + assert(caller.get_y() == 0x0101010101010101010101010101010101010101010101010101010101010101); + assert(caller.get_boolean() == true); + assert(caller.get_int8() == 8); + assert(caller.get_int16() == 16); + assert(caller.get_int32() == 32); + let s = caller.get_s(); + assert(s.x == 1); + assert(s.y == 2); + assert(s.z == 0x0000000000000000000000000000000000000000000000000000000000000003); + assert(s.t.x == 4); + assert(s.t.y == 5); + assert(s.t.z == 0x0000000000000000000000000000000000000000000000000000000000000006); + assert(s.t.boolean == true); + assert(s.t.int8 == 7); + assert(s.t.int16 == 8); + assert(s.t.int32 == 9); + let e = caller.get_e(); + match e { + E::B(t) => { + assert(t.x == 1); + assert(t.y == 2); + assert(t.z == 0x0000000000000000000000000000000000000000000000000000000000000003); + assert(t.boolean == true); + assert(t.int8 == 4); + assert(t.int16 == 5); + assert(t.int32 == 6); + } + _ => { + revert(0) + } + } + let e2 = caller.get_e2(); + match e2 { + E::A(val) => { + assert(val == 777); + } + _ => { + revert(0) + } + } + assert(sha256(caller.get_string()) == sha256("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); + // Test 1 caller.set_x(1); assert(caller.get_x() == 1); @@ -142,6 +186,7 @@ fn main() -> bool { let e = caller.get_e(); match e { E::A(val) => assert(val == 42), _ => { + revert(0) } } @@ -158,6 +203,7 @@ fn main() -> bool { assert(val.int32 == t.int32); } _ => { + revert(0) } }; diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/test.toml new file mode 100644 index 00000000000..c64e79bfb32 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/test.toml @@ -0,0 +1,3 @@ +category = "run_on_node" +expected_result = { action = "result", value = 1 } +contracts = ["should_pass/test_contracts/storage_access_contract"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/token_ops_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/token_ops_test/test.toml new file mode 100644 index 00000000000..c5bf35a1c74 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/token_ops_test/test.toml @@ -0,0 +1,3 @@ +category = "run_on_node" +expected_result = { action = "result", value = 1 } +contracts = ["should_pass/test_contracts/balance_test_contract", "should_pass/test_contracts/test_fuel_coin_contract"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/address_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/address_test/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/address_test/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/alloc/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/alloc/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/alloc/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/assert_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/assert_test/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/assert_test/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/b512_struct_alignment/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/b512_struct_alignment/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/b512_struct_alignment/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/b512_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/b512_test/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/b512_test/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/block_height/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/block_height/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/block_height/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_test/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_test/Forc.lock index 5ffb59921bf..a94f7cffeda 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_test/Forc.lock +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_test/Forc.lock @@ -1,13 +1,14 @@ [[package]] name = 'contract_id_test' -dependencies = ['std git+https://github.com/FuelLabs/sway-lib-std?reference=master#247270e7d8911e754a989b2fe280c462605ae2f6'] +source = 'root' +dependencies = ['std'] [[package]] name = 'core' -source = 'git+https://github.com/FuelLabs/sway-lib-core?reference=master#c331ed20ebc9d646acec6b8ee8f408627ce3b573' +source = 'path+from-root-16F6D7874F5EC2F3' dependencies = [] [[package]] name = 'std' -source = 'git+https://github.com/FuelLabs/sway-lib-std?reference=master#247270e7d8911e754a989b2fe280c462605ae2f6' -dependencies = ['core git+https://github.com/FuelLabs/sway-lib-core?reference=master#c331ed20ebc9d646acec6b8ee8f408627ce3b573'] +source = 'path+from-root-16F6D7874F5EC2F3' +dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_test/test.toml new file mode 100644 index 00000000000..83885a3255b --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_test/test.toml @@ -0,0 +1 @@ +category = "disabled" diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_type/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_type/src/main.sw index 7fd615e65ee..2d808ac7e5a 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_type/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_type/src/main.sw @@ -9,8 +9,8 @@ fn main() -> bool { let id_2 = ~ContractId::from(0x0000000000000000000000000000000000000000000000000000000000000000); assert(id_1 == id_2); - assert(id_1 == ~ContractId::from(BASE_ASSET_ID)); - assert(id_1.into() == BASE_ASSET_ID); + assert(id_1 == BASE_ASSET_ID); + assert(0x0000000000000000000000000000000000000000000000000000000000000000 == id_1.into()); true } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_type/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_type/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/contract_id_type/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/ec_recover_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/ec_recover_test/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/ec_recover_test/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/evm_ecr/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/evm_ecr/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/evm_ecr/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/exponentiation_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/exponentiation_test/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/exponentiation_test/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/ge_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/ge_test/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/ge_test/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/identity_eq/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/identity_eq/src/main.sw index 3fa7807463a..ea583775dc3 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/identity_eq/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/identity_eq/src/main.sw @@ -1,6 +1,6 @@ script; -use std::{address::Address, assert::assert, contract_id::ContractId, identity::*}; +use std::{address::Address, assert::assert, contract_id::ContractId, identity::Identity}; fn main() -> bool { let b1 = 0x0000000000000000000000000000000000000000000000000000000000000001; diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/identity_eq/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/identity_eq/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/identity_eq/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/intrinsics/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/intrinsics/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/intrinsics/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/mem/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/mem/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/mem/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/option/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/option/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/option/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/require/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/require/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/require/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/result/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/result/src/main.sw index 334ff86ed3b..e21600d3b12 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/result/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/result/src/main.sw @@ -1,6 +1,6 @@ script; -use std::result::*; +use std::result::Result; use std::revert::revert; fn main() -> bool { diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/result/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/result/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/result/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_div_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_div_test/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_div_test/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_mul_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_mul_test/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_mul_test/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_test/src/main.sw index 23df01a0746..f6db6ec6351 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_test/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_test/src/main.sw @@ -78,5 +78,30 @@ fn main() -> bool { assert(three_left_shift_one.upper == 0); assert(three_left_shift_one.lower == 6); + // test as_u64() + let eleven = ~U128::from(0, 11); + let unwrapped = eleven.as_u64().unwrap(); + assert(unwrapped == 11); + + let err_1 = ~U128::from(42, 11).as_u64(); + assert(match err_1 { + Result::Err(U128Error::LossOfPrecision) => { + true + }, + _ => { + false + }, + }); + + let err_1 = ~U128::from(42, 0).as_u64(); + assert(match err_1 { + Result::Err(U128Error::LossOfPrecision) => { + true + }, + _ => { + false + }, + }); + true } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_test/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u128_test/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/.gitignore b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/Forc.lock new file mode 100644 index 00000000000..26ae4e45e26 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-31E9CFD36AA5AC17' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-31E9CFD36AA5AC17' +dependencies = ['core'] + +[[package]] +name = 'u256_test' +source = 'root' +dependencies = ['std'] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/Forc.toml new file mode 100644 index 00000000000..b1faffa56f5 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "u256_test" + +[dependencies] +std = { path = "../../../../../../../sway-lib-std" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/json_abi_oracle.json new file mode 100644 index 00000000000..f0586b752c7 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/json_abi_oracle.json @@ -0,0 +1,14 @@ +[ + { + "inputs": [], + "name": "main", + "outputs": [ + { + "components": null, + "name": "", + "type": "bool" + } + ], + "type": "function" + } +] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/src/main.sw new file mode 100644 index 00000000000..4cfe0acfb08 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/src/main.sw @@ -0,0 +1,103 @@ +script; + +use core::num::*; +use std::{assert::assert, result::Result, u256::{U256, U256Error}}; + +fn main() -> bool { + // test new() + let new = ~U256::new(); + let empty = U256 { + a: 0, + b: 0, + c: 0, + d: 0, + }; + assert(new == empty); + + // test from() & into() + let(l, m, n, o) = new.into(); + assert(l == 0); + assert(m == 0); + assert(n == 0); + assert(o == 0); + + let a = 11; + let b = 42; + let c = 101; + let d = 69; + let x = ~U256::from(a, b, c, d); + let y = ~U256::from(a, b, c, d); + + assert(x.a == a); + assert(x.a != b); + assert(x.b == b); + assert(x.b != c); + assert(x.c == c); + assert(x.c != d); + assert(x.d == d); + assert(x.d != a); + + let(e, f, g, h) = x.into(); + assert(e == a); + assert(f == b); + assert(g == c); + assert(h == d); + + assert(x == y); + + // test min() & max() + let max = ~U256::max(); + let min = ~U256::min(); + let(one, two, three, four) = max.into(); + assert(one == ~u64::max()); + assert(two == ~u64::max()); + assert(three == ~u64::max()); + assert(four == ~u64::max()); + + let(min_1, min_2, min_3, min_4) = min.into(); + assert(min_1 == ~u64::min()); + assert(min_2 == ~u64::min()); + assert(min_3 == ~u64::min()); + assert(min_4 == ~u64::min()); + + // test as_u64() + let err_1 = ~U256::from(42, 0, 0, 11).as_u64(); + assert(match err_1 { + Result::Err(U256Error::LossOfPrecision) => { + true + }, + _ => { + false + }, + }); + + let err_2 = ~U256::from(0, 42, 0, 11).as_u64(); + assert(match err_2 { + Result::Err(U256Error::LossOfPrecision) => { + true + }, + _ => { + false + }, + }); + + let err_3 = ~U256::from(0, 0, 42, 11).as_u64(); + assert(match err_3 { + Result::Err(U256Error::LossOfPrecision) => { + true + }, + _ => { + false + }, + }); + + + let eleven = ~U256::from(0, 0, 0, 11); + let unwrapped = eleven.as_u64().unwrap(); + assert(unwrapped == 11); + + // test bits() + assert(~U256::bits() == 256u32); + + true +} diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/u256_test/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec/src/main.sw index 6e580151b97..ea087ca93da 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec/src/main.sw @@ -27,7 +27,7 @@ fn main() -> bool { } fn test_vector_new_u8() { - let mut vector: Vec = ~Vec::new::(); + let mut vector = ~Vec::new(); let number0 = 0u8; let number1 = 1u8; @@ -117,7 +117,7 @@ fn test_vector_new_u8() { } fn test_vector_new_b256() { - let mut vector: Vec = ~Vec::new::(); + let mut vector = ~Vec::new(); let b0 = 0x0000000000000000000000000000000000000000000000000000000000000000; let b1 = 0x0000000000000000000000000000000000000000000000000000000000000001; @@ -207,7 +207,7 @@ fn test_vector_new_b256() { } fn test_vector_new_struct() { - let mut vector: Vec = ~Vec::new::(); + let mut vector = ~Vec::new(); let number0 = 0u32; let number1 = 1u32; @@ -359,7 +359,7 @@ fn test_vector_new_struct() { } fn test_vector_new_enum() { - let mut vector: Vec = ~Vec::new::(); + let mut vector = ~Vec::new(); let b0 = 0x0000000000000000000000000000000000000000000000000000000000000000; let b1 = 0x0000000000000000000000000000000000000000000000000000000000000001; @@ -412,7 +412,7 @@ fn test_vector_new_enum() { } fn test_vector_new_tuple() { - let mut vector: Vec<(u16, b256)> = ~Vec::new::<(u16, b256)>(); + let mut vector = ~Vec::new(); let number0 = 0u16; let number1 = 1u16; @@ -536,7 +536,7 @@ fn test_vector_new_tuple() { } fn test_vector_new_string() { - let mut vector: Vec = ~Vec::new::(); + let mut vector = ~Vec::new(); let s0 = "fuel"; let s1 = "john"; @@ -578,9 +578,7 @@ fn test_vector_new_string() { } fn test_vector_new_array() { - let mut vector: Vec<[u64; - 3]> = ~Vec::new::<[u64; - 3]>(); + let mut vector = ~Vec::new(); let a0 = [0, 1, 2]; let a1 = [3, 4, 5]; @@ -628,7 +626,7 @@ fn test_vector_new_array() { } fn test_vector_with_capacity_u64() { - let mut vector: Vec = ~Vec::with_capacity::(8); + let mut vector = ~Vec::with_capacity(8); let number0 = 0; let number1 = 1; diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/abi_with_tuples/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/abi_with_tuples/Forc.lock index ccbfdf27499..b94f93e5b57 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/abi_with_tuples/Forc.lock +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/abi_with_tuples/Forc.lock @@ -1,3 +1,9 @@ [[package]] -name = 'auth_testing_abi' +name = 'abi_with_tuples' +source = 'root' +dependencies = ['core'] + +[[package]] +name = 'core' +source = 'path+from-root-D1CDC58B8291BA8B' dependencies = [] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/storage_access_abi/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/storage_access_abi/src/main.sw index c9bb33696ee..5fae960988d 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/storage_access_abi/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/storage_access_abi/src/main.sw @@ -105,6 +105,8 @@ abi StorageAccess { #[storage(read)] fn get_e() -> E; #[storage(read)] + fn get_e2() -> E; + #[storage(read)] fn get_string() -> str[40]; // Operations diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/abi_with_tuples_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/abi_with_tuples_contract/json_storage_slots_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/abi_with_tuples_contract/json_storage_slots_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/abi_with_tuples_contract/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/abi_with_tuples_contract/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/abi_with_tuples_contract/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/array_of_structs_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/array_of_structs_contract/json_storage_slots_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/array_of_structs_contract/json_storage_slots_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/array_of_structs_contract/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/array_of_structs_contract/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/array_of_structs_contract/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/auth_testing_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/auth_testing_contract/json_storage_slots_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/auth_testing_contract/json_storage_slots_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/auth_testing_contract/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/auth_testing_contract/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/auth_testing_contract/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/balance_test_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/balance_test_contract/json_storage_slots_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/balance_test_contract/json_storage_slots_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/balance_test_contract/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/balance_test_contract/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/balance_test_contract/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_storage_slots_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_storage_slots_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/context_testing_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/context_testing_contract/json_storage_slots_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/context_testing_contract/json_storage_slots_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/context_testing_contract/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/context_testing_contract/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/context_testing_contract/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/json_storage_slots_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/json_storage_slots_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/json_storage_slots_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/json_storage_slots_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/issue_1512_repro/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/issue_1512_repro/json_storage_slots_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/issue_1512_repro/json_storage_slots_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/issue_1512_repro/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/issue_1512_repro/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/issue_1512_repro/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/multiple_impl/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/multiple_impl/json_storage_slots_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/multiple_impl/json_storage_slots_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/multiple_impl/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/multiple_impl/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/multiple_impl/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/nested_struct_args_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/nested_struct_args_contract/json_storage_slots_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/nested_struct_args_contract/json_storage_slots_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/nested_struct_args_contract/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/nested_struct_args_contract/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/nested_struct_args_contract/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_abi_oracle.json index 032838bc581..e035b1b6003 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_abi_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_abi_oracle.json @@ -867,6 +867,65 @@ ], "type": "function" }, + { + "inputs": [], + "name": "get_e2", + "outputs": [ + { + "components": [ + { + "components": null, + "name": "A", + "type": "u64" + }, + { + "components": [ + { + "components": null, + "name": "x", + "type": "u64" + }, + { + "components": null, + "name": "y", + "type": "u64" + }, + { + "components": null, + "name": "z", + "type": "b256" + }, + { + "components": null, + "name": "boolean", + "type": "bool" + }, + { + "components": null, + "name": "int8", + "type": "u8" + }, + { + "components": null, + "name": "int16", + "type": "u16" + }, + { + "components": null, + "name": "int32", + "type": "u32" + } + ], + "name": "B", + "type": "struct T" + } + ], + "name": "", + "type": "enum E" + } + ], + "type": "function" + }, { "inputs": [], "name": "get_string", diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_storage_slots_oracle.json new file mode 100644 index 00000000000..08c003c88c8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_storage_slots_oracle.json @@ -0,0 +1,106 @@ +[ + { + "key": "02dac99c283f16bc91b74f6942db7f012699a2ad51272b15207b9cc14a70dbae", + "value": "0000000000000001000000000000000000000000000000000000000000000000" + }, + { + "key": "126435532f2d2faed6fdd08cea385e77766b42cebae52c892908ba163ffd9484", + "value": "0000000000000000000000000000000000000000000000000000000000000003" + }, + { + "key": "2e92e2a58ff87833010c4cb205f65aa14fa39f799ffc3809bd4a7014b131bc93", + "value": "0000000000000001000000000000000000000000000000000000000000000000" + }, + { + "key": "57bba8e7ea11ac802968230c7c3c09485b488cc84009e80055f938a2cebeb0e6", + "value": "0000000000000001000000000000000200000000000000000000000000000000" + }, + { + "key": "57bba8e7ea11ac802968230c7c3c09485b488cc84009e80055f938a2cebeb0e7", + "value": "0000000000000000000000000000000300000000000000010000000000000004" + }, + { + "key": "57bba8e7ea11ac802968230c7c3c09485b488cc84009e80055f938a2cebeb0e8", + "value": "0000000000000005000000000000000600000000000000000000000000000000" + }, + { + "key": "6294951dcb0a9111a517be5cf4785670ff4e166fb5ab9c33b17e6881b48e964f", + "value": "0000000000000008000000000000000000000000000000000000000000000000" + }, + { + "key": "678de5d61f6f4690357e7868bca285aa8faf5bc9d2126bd8e5006a3ee54f0003", + "value": "0000000000000005000000000000000000000000000000000000000000000000" + }, + { + "key": "71c50136ce909d575b4bd2b1505b9b166ace9d514e92b0e6f9a04abfea8e649d", + "value": "0000000000000002000000000000000000000000000000000000000000000000" + }, + { + "key": "7f91d1a929dce734e7f930bbb279ccfccdb5474227502ea8845815c74bd930a7", + "value": "0000000000000020000000000000000000000000000000000000000000000000" + }, + { + "key": "94b2b70d20da552763c7614981b2a4d984380d7ed4e54c01b28c914e79e44bd5", + "value": "0000000000000010000000000000000000000000000000000000000000000000" + }, + { + "key": "9d9209c41faa2ab13bef277e30c3d85b2b95a81816d51614e5816c182ac0a66e", + "value": "0000000000000001000000000000000000000000000000000000000000000000" + }, + { + "key": "ad7293bc17e2debf737147d46a68be4c2487150275ed02c8a59c58d1452e9052", + "value": "0000000000000009000000000000000000000000000000000000000000000000" + }, + { + "key": "af75026d46742957dd1a310d00030e0c7099f07760a0f18d84a541ebf8a0c244", + "value": "0000000000000000000000000000000000000000000000000000000000000006" + }, + { + "key": "b0cfa187f470ad0b95c1e20154630783abb9019127755afbe4fb5e2382888ba6", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "key": "b0cfa187f470ad0b95c1e20154630783abb9019127755afbe4fb5e2382888ba7", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "key": "b0cfa187f470ad0b95c1e20154630783abb9019127755afbe4fb5e2382888ba8", + "value": "0000000000000000000000000000030900000000000000000000000000000000" + }, + { + "key": "c28432da64bb717a7d85e34191fc1e50f031b9689c808b653ef3a8328a8e1002", + "value": "0000000000000004000000000000000000000000000000000000000000000000" + }, + { + "key": "c497c29a5cb465e7baae51571dfdcd1d47dae5fb4258de06d4f395487d441468", + "value": "0000000000000007000000000000000000000000000000000000000000000000" + }, + { + "key": "c5e69153be998bc6f957aeb6f8fd46a0e9c5bc2d3dff421a73e02f64a3012fbb", + "value": "4141414141414141414141414141414141414141414141414141414141414141" + }, + { + "key": "c5e69153be998bc6f957aeb6f8fd46a0e9c5bc2d3dff421a73e02f64a3012fbc", + "value": "4141414141414141000000000000000000000000000000000000000000000000" + }, + { + "key": "d55bcd857a8d6a72e6ba8a7aacbf56161e266c2418af5c06c9d1907bbca2624b", + "value": "0000000000000001000000000000000000000000000000000000000000000000" + }, + { + "key": "de9090cb50e71c2588c773487d1da7066d0c719849a7e58dc8b6397a25c567c0", + "value": "0101010101010101010101010101010101010101010101010101010101010101" + }, + { + "key": "e945e3646bf99ebf2a70bf0c8151349dab2a54abac6450f0ee9fad896c308871", + "value": "0000000000000008000000000000000000000000000000000000000000000000" + }, + { + "key": "ea9d1ab55216336383fedadabe3c23a4df23267279ea294a547ca1006371746f", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "key": "f383b0ce51358be57daa3b725fe44acdb2d880604e367199080b4379c41bb6ed", + "value": "0000000000000040000000000000000000000000000000000000000000000000" + } +] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/src/main.sw index b507509cbbd..6b064d88e05 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/src/main.sw @@ -3,205 +3,184 @@ contract; use storage_access_abi::{E, S, StorageAccess, T}; storage { - x: u64, - y: b256, - s: S, - boolean: bool, - int8: u8, - int16: u16, - int32: u32, - e: E, - string: str[40], + x: u64 = 64, + y: b256 = 0x0101010101010101010101010101010101010101010101010101010101010101, + s: S = S { + x: 1, + y: 2, + z: 0x0000000000000000000000000000000000000000000000000000000000000003, + t: T { + x: 4, + y: 5, + z: 0x0000000000000000000000000000000000000000000000000000000000000006, + boolean: true, + int8: 7, + int16: 8, + int32: 9, + }, + }, + boolean: bool = true, + int8: u8 = 8, + int16: u16 = 16, + int32: u32 = 32, + e: E = E::B(T { + x: 1, + y: 2, + z: 0x0000000000000000000000000000000000000000000000000000000000000003, + boolean: true, + int8: 4, + int16: 5, + int32: 6, + }, + ), e2: E = E::A(777), + string: str[40] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", } impl StorageAccess for Contract { // Setters - #[storage(write)] - fn set_x(x: u64) { + #[storage(write)]fn set_x(x: u64) { storage.x = x; } - #[storage(write)] - fn set_y(y: b256) { + #[storage(write)]fn set_y(y: b256) { storage.y = y; } - #[storage(write)] - fn set_s(s: S) { + #[storage(write)]fn set_s(s: S) { storage.s = s; } - #[storage(write)] - fn set_boolean(boolean: bool) { + #[storage(write)]fn set_boolean(boolean: bool) { storage.boolean = boolean; } - #[storage(write)] - fn set_int8(int8: u8) { + #[storage(write)]fn set_int8(int8: u8) { storage.int8 = int8; } - #[storage(write)] - fn set_int16(int16: u16) { + #[storage(write)]fn set_int16(int16: u16) { storage.int16 = int16; } - #[storage(write)] - fn set_int32(int32: u32) { + #[storage(write)]fn set_int32(int32: u32) { storage.int32 = int32; } - #[storage(write)] - fn set_s_dot_x(x: u64) { + #[storage(write)]fn set_s_dot_x(x: u64) { storage.s.x = x; } - #[storage(write)] - fn set_s_dot_y(y: u64) { + #[storage(write)]fn set_s_dot_y(y: u64) { storage.s.y = y; } - #[storage(write)] - fn set_s_dot_z(z: b256) { + #[storage(write)]fn set_s_dot_z(z: b256) { storage.s.z = z; } - #[storage(write)] - fn set_s_dot_t(t: T) { + #[storage(write)]fn set_s_dot_t(t: T) { storage.s.t = t; } - #[storage(write)] - fn set_s_dot_t_dot_x(x: u64) { + #[storage(write)]fn set_s_dot_t_dot_x(x: u64) { storage.s.t.x = x; } - #[storage(write)] - fn set_s_dot_t_dot_y(y: u64) { + #[storage(write)]fn set_s_dot_t_dot_y(y: u64) { storage.s.t.y = y; } - #[storage(write)] - fn set_s_dot_t_dot_z(z: b256) { + #[storage(write)]fn set_s_dot_t_dot_z(z: b256) { storage.s.t.z = z; } - #[storage(write)] - fn set_s_dot_t_dot_boolean(boolean: bool) { + #[storage(write)]fn set_s_dot_t_dot_boolean(boolean: bool) { storage.s.t.boolean = boolean; } - #[storage(write)] - fn set_s_dot_t_dot_int8(int8: u8) { + #[storage(write)]fn set_s_dot_t_dot_int8(int8: u8) { storage.s.t.int8 = int8; } - #[storage(write)] - fn set_s_dot_t_dot_int16(int16: u16) { + #[storage(write)]fn set_s_dot_t_dot_int16(int16: u16) { storage.s.t.int16 = int16; } - #[storage(write)] - fn set_s_dot_t_dot_int32(int32: u32) { + #[storage(write)]fn set_s_dot_t_dot_int32(int32: u32) { storage.s.t.int32 = int32; } - #[storage(write)] - fn set_e(e: E) { + #[storage(write)]fn set_e(e: E) { storage.e = e; } - #[storage(write)] - fn set_string(string: str[40]) { + #[storage(write)]fn set_string(string: str[40]) { storage.string = string; } // Getters - #[storage(read)] - fn get_x() -> u64 { + #[storage(read)]fn get_x() -> u64 { storage.x } - #[storage(read)] - fn get_y() -> b256 { + #[storage(read)]fn get_y() -> b256 { storage.y } - #[storage(read)] - fn get_s() -> S { + #[storage(read)]fn get_s() -> S { storage.s } - #[storage(read)] - fn get_boolean() -> bool { + #[storage(read)]fn get_boolean() -> bool { storage.boolean } - #[storage(read)] - fn get_int8() -> u8 { + #[storage(read)]fn get_int8() -> u8 { storage.int8 } - #[storage(read)] - fn get_int16() -> u16 { + #[storage(read)]fn get_int16() -> u16 { storage.int16 } - #[storage(read)] - fn get_int32() -> u32 { + #[storage(read)]fn get_int32() -> u32 { storage.int32 } - #[storage(read)] - fn get_s_dot_x() -> u64 { + #[storage(read)]fn get_s_dot_x() -> u64 { storage.s.x } - #[storage(read)] - fn get_s_dot_y() -> u64 { + #[storage(read)]fn get_s_dot_y() -> u64 { storage.s.y } - #[storage(read)] - fn get_s_dot_z() -> b256 { + #[storage(read)]fn get_s_dot_z() -> b256 { storage.s.z } - #[storage(read)] - fn get_s_dot_t() -> T { + #[storage(read)]fn get_s_dot_t() -> T { storage.s.t } - #[storage(read)] - fn get_s_dot_t_dot_x() -> u64 { + #[storage(read)]fn get_s_dot_t_dot_x() -> u64 { storage.s.t.x } - #[storage(read)] - fn get_s_dot_t_dot_y() -> u64 { + #[storage(read)]fn get_s_dot_t_dot_y() -> u64 { storage.s.t.y } - #[storage(read)] - fn get_s_dot_t_dot_z() -> b256 { + #[storage(read)]fn get_s_dot_t_dot_z() -> b256 { storage.s.t.z } - #[storage(read)] - fn get_s_dot_t_dot_boolean() -> bool { + #[storage(read)]fn get_s_dot_t_dot_boolean() -> bool { storage.s.t.boolean } - #[storage(read)] - fn get_s_dot_t_dot_int8() -> u8 { + #[storage(read)]fn get_s_dot_t_dot_int8() -> u8 { storage.s.t.int8 } - #[storage(read)] - fn get_s_dot_t_dot_int16() -> u16 { + #[storage(read)]fn get_s_dot_t_dot_int16() -> u16 { storage.s.t.int16 } - #[storage(read)] - fn get_s_dot_t_dot_int32() -> u32 { + #[storage(read)]fn get_s_dot_t_dot_int32() -> u32 { storage.s.t.int32 } - #[storage(read)] - fn get_e() -> E { + #[storage(read)]fn get_e() -> E { storage.e } - #[storage(read)] - fn get_string() -> str[40] { + #[storage(read)]fn get_e2() -> E { + storage.e2 + } + #[storage(read)]fn get_string() -> str[40] { storage.string } // Operations - #[storage(read, write)] - fn add_to_s_dot_t_dot_x(k: u64) { + #[storage(read, write)]fn add_to_s_dot_t_dot_x(k: u64) { storage.s.t.x += k; } - #[storage(read, write)] - fn subtract_from_s_dot_t_dot_x(k: u64) { + #[storage(read, write)]fn subtract_from_s_dot_t_dot_x(k: u64) { storage.s.t.x -= k; } - #[storage(read, write)] - fn multiply_by_s_dot_t_dot_x(k: u64) { + #[storage(read, write)]fn multiply_by_s_dot_t_dot_x(k: u64) { storage.s.t.x *= k; } - #[storage(read, write)] - fn divide_s_dot_t_dot_x(k: u64) { + #[storage(read, write)]fn divide_s_dot_t_dot_x(k: u64) { storage.s.t.x /= k; } - #[storage(read, write)] - fn shift_left_s_dot_t_dot_x(k: u64) { + #[storage(read, write)]fn shift_left_s_dot_t_dot_x(k: u64) { storage.s.t.x <<= k; } - #[storage(read, write)] - fn shift_right_s_dot_t_dot_x(k: u64) { + #[storage(read, write)]fn shift_right_s_dot_t_dot_x(k: u64) { storage.s.t.x >>= k; } } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/test_fuel_coin_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/test_fuel_coin_contract/json_storage_slots_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/test_fuel_coin_contract/json_storage_slots_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/test_fuel_coin_contract/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/test_fuel_coin_contract/test.toml new file mode 100644 index 00000000000..b9d57f4d5f1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/test_fuel_coin_contract/test.toml @@ -0,0 +1,3 @@ +category = "compile" +validate_abi = true +validate_storage_slots = true diff --git a/test/src/sdk-harness/Cargo.toml b/test/src/sdk-harness/Cargo.toml index 2d95faae92b..809b0d68a85 100644 --- a/test/src/sdk-harness/Cargo.toml +++ b/test/src/sdk-harness/Cargo.toml @@ -7,12 +7,11 @@ version = "0.0.0" [dependencies] assert_matches = "1.5.0" -fuel-core = { version = "0.8", default-features = false } -fuel-gql-client = { version = "0.8", default-features = false } +fuel-core = { version = "0.9", default-features = false } +fuel-gql-client = { version = "0.9", default-features = false } fuel-types = "0.5" -fuel-vm = "0.11" -fuels = "0.15" -fuels-abigen-macro = "0.15" +fuel-vm = "0.12" +fuels = { version = "0.16", features = ["fuel-core-lib"] } hex = "0.4.3" sha2 = "0.10" sha3 = "0.10.1" diff --git a/test/src/sdk-harness/test_artifacts/context_testing_abi/src/main.sw b/test/src/sdk-harness/test_artifacts/context_testing_abi/src/main.sw index 1b413717df9..09c82551cf8 100644 --- a/test/src/sdk-harness/test_artifacts/context_testing_abi/src/main.sw +++ b/test/src/sdk-harness/test_artifacts/context_testing_abi/src/main.sw @@ -3,7 +3,7 @@ use std::contract_id::ContractId; abi ContextTesting { fn get_this_balance(asset: ContractId) -> u64; - fn get_balance_of_contract(asset: ContractId, contract: ContractId) -> u64; + fn get_balance_of_contract(asset: ContractId, r#contract: ContractId) -> u64; fn get_amount() -> u64; fn get_asset_id() -> ContractId; fn get_gas() -> u64; diff --git a/test/src/sdk-harness/test_artifacts/methods_abi/Forc.lock b/test/src/sdk-harness/test_artifacts/methods_abi/Forc.lock new file mode 100644 index 00000000000..1fb6b0979c0 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/methods_abi/Forc.lock @@ -0,0 +1,4 @@ +[[package]] +name = 'methods_abi' +source = 'root' +dependencies = [] diff --git a/test/src/sdk-harness/test_artifacts/methods_abi/Forc.toml b/test/src/sdk-harness/test_artifacts/methods_abi/Forc.toml new file mode 100644 index 00000000000..d4c28b1b93a --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/methods_abi/Forc.toml @@ -0,0 +1,6 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "methods_abi" +implicit-std = false diff --git a/test/src/sdk-harness/test_artifacts/methods_abi/src/main.sw b/test/src/sdk-harness/test_artifacts/methods_abi/src/main.sw new file mode 100644 index 00000000000..288efc7153f --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/methods_abi/src/main.sw @@ -0,0 +1,6 @@ +library methods_abi; + +abi MethodsContract { + #[storage(read, write)] + fn test_function() -> bool; +} diff --git a/test/src/sdk-harness/test_artifacts/methods_contract/Forc.lock b/test/src/sdk-harness/test_artifacts/methods_contract/Forc.lock new file mode 100644 index 00000000000..4faa448e08d --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/methods_contract/Forc.lock @@ -0,0 +1,22 @@ +[[package]] +name = 'core' +source = 'path+from-root-051EC93A63B1E039' +dependencies = [] + +[[package]] +name = 'methods_abi' +source = 'path+from-root-051EC93A63B1E039' +dependencies = [] + +[[package]] +name = 'methods_contract' +source = 'root' +dependencies = [ + 'methods_abi', + 'std', +] + +[[package]] +name = 'std' +source = 'path+from-root-051EC93A63B1E039' +dependencies = ['core'] diff --git a/test/src/sdk-harness/test_artifacts/methods_contract/Forc.toml b/test/src/sdk-harness/test_artifacts/methods_contract/Forc.toml new file mode 100644 index 00000000000..19f2d059625 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/methods_contract/Forc.toml @@ -0,0 +1,9 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "methods_contract" + +[dependencies] +std = { path = "../../../../../sway-lib-std" } +methods_abi = { path = "../methods_abi" } diff --git a/test/src/sdk-harness/test_artifacts/methods_contract/src/main.sw b/test/src/sdk-harness/test_artifacts/methods_contract/src/main.sw new file mode 100644 index 00000000000..0ba065a12c1 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/methods_contract/src/main.sw @@ -0,0 +1,41 @@ +contract; + +use methods_abi::MethodsContract; + +use std::result::*; +use std::identity::*; +use std::chain::auth::*; +use std::option::*; +use std::assert::*; + +fn bogus() -> Identity { + let sender = msg_sender(); + sender.unwrap() +} + +fn bogus2() -> Identity { + msg_sender().unwrap() +} + +struct MyStruct { + int_option: Option +} + +storage { + stored_struct: MyStruct, +} + +impl MethodsContract for Contract { + #[storage(read, write)] + fn test_function() -> bool { + let identity = bogus(); + let identity2 = bogus2(); + storage.stored_struct = MyStruct { + int_option: Option::Some(99u64) + }; + let stored_struct = storage.stored_struct; + let stored_option_in_struct = stored_struct.int_option; + require(stored_option_in_struct.is_some(), "Error"); + true + } +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/auth/mod.rs b/test/src/sdk-harness/test_projects/auth/mod.rs index 0500b5c92b7..7e19f74650f 100644 --- a/test/src/sdk-harness/test_projects/auth/mod.rs +++ b/test/src/sdk-harness/test_projects/auth/mod.rs @@ -1,5 +1,4 @@ use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; abigen!( AuthContract, diff --git a/test/src/sdk-harness/test_projects/call_frames/mod.rs b/test/src/sdk-harness/test_projects/call_frames/mod.rs index 4170b015a12..7a31354a131 100644 --- a/test/src/sdk-harness/test_projects/call_frames/mod.rs +++ b/test/src/sdk-harness/test_projects/call_frames/mod.rs @@ -1,6 +1,5 @@ use fuel_vm::consts::VM_MAX_RAM; use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; abigen!( CallFramesTestContract, diff --git a/test/src/sdk-harness/test_projects/context/mod.rs b/test/src/sdk-harness/test_projects/context/mod.rs index 8d17c62c10a..c80298f5384 100644 --- a/test/src/sdk-harness/test_projects/context/mod.rs +++ b/test/src/sdk-harness/test_projects/context/mod.rs @@ -1,6 +1,5 @@ use fuel_vm::consts::VM_MAX_RAM; use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; abigen!( TestContextContract, diff --git a/test/src/sdk-harness/test_projects/context/src/main.sw b/test/src/sdk-harness/test_projects/context/src/main.sw index 02595a02795..46e6e7c362c 100644 --- a/test/src/sdk-harness/test_projects/context/src/main.sw +++ b/test/src/sdk-harness/test_projects/context/src/main.sw @@ -9,8 +9,8 @@ impl ContextTesting for Contract { this_balance(asset) } - fn get_balance_of_contract(asset: ContractId, contract: ContractId) -> u64 { - balance_of(asset, contract) + fn get_balance_of_contract(asset: ContractId, r#contract: ContractId) -> u64 { + balance_of(asset, r#contract) } fn get_amount() -> u64 { diff --git a/test/src/sdk-harness/test_projects/exponentiation/mod.rs b/test/src/sdk-harness/test_projects/exponentiation/mod.rs index 1a711b7fad8..bd81097b056 100644 --- a/test/src/sdk-harness/test_projects/exponentiation/mod.rs +++ b/test/src/sdk-harness/test_projects/exponentiation/mod.rs @@ -1,7 +1,6 @@ use fuels::prelude::*; use fuels::signers::LocalWallet; use fuels::tx::ContractId; -use fuels_abigen_macro::abigen; abigen!(TestPowContract, "test_artifacts/pow/out/debug/pow-abi.json"); diff --git a/test/src/sdk-harness/test_projects/harness.rs b/test/src/sdk-harness/test_projects/harness.rs index 77b72b36c53..462f51e6958 100644 --- a/test/src/sdk-harness/test_projects/harness.rs +++ b/test/src/sdk-harness/test_projects/harness.rs @@ -6,6 +6,7 @@ mod context; mod exponentiation; mod hashing; mod logging; +mod methods; mod reentrancy; mod registers; mod script_data; diff --git a/test/src/sdk-harness/test_projects/hashing/mod.rs b/test/src/sdk-harness/test_projects/hashing/mod.rs index 3133b5e4361..3182d784827 100644 --- a/test/src/sdk-harness/test_projects/hashing/mod.rs +++ b/test/src/sdk-harness/test_projects/hashing/mod.rs @@ -1,5 +1,4 @@ use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; use sha2::{Digest, Sha256}; use sha3::Keccak256; diff --git a/test/src/sdk-harness/test_projects/logging/mod.rs b/test/src/sdk-harness/test_projects/logging/mod.rs index 341435748b8..11be47c43fc 100644 --- a/test/src/sdk-harness/test_projects/logging/mod.rs +++ b/test/src/sdk-harness/test_projects/logging/mod.rs @@ -1,7 +1,7 @@ use fuel_core::service::{Config, FuelService}; use fuel_gql_client::client::FuelClient; use fuels::contract::script::Script; -use fuels::tx::{default_parameters::MAX_GAS_PER_TX, Transaction}; +use fuels::tx::{ConsensusParameters, Transaction}; use hex; #[tokio::test] @@ -12,7 +12,7 @@ async fn run_valid() { let tx = Transaction::Script { gas_price: 0, - gas_limit: MAX_GAS_PER_TX, + gas_limit: ConsensusParameters::DEFAULT.max_gas_per_tx, maturity: 0, byte_price: 0, receipts_root: Default::default(), diff --git a/test/src/sdk-harness/test_projects/methods/mod.rs b/test/src/sdk-harness/test_projects/methods/mod.rs new file mode 100644 index 00000000000..24789d6ba23 --- /dev/null +++ b/test/src/sdk-harness/test_projects/methods/mod.rs @@ -0,0 +1,27 @@ +use fuels::prelude::*; +use fuels::signers::wallet::Wallet; + +abigen!( + MethodsContract, + "test_artifacts/methods_contract/out/debug/methods_contract-abi.json", +); + +#[tokio::test] +async fn run_methods_test() { + let wallet = launch_provider_and_get_single_wallet().await; + let instance = get_methods_instance(wallet).await; + + let result = instance.test_function().call().await.unwrap(); + assert_eq!(result.value, true); +} + +async fn get_methods_instance(wallet: Wallet) -> MethodsContract { + let id = Contract::deploy( + "test_artifacts/methods_contract/out/debug/methods_contract.bin", + &wallet, + TxParameters::default(), + ) + .await + .unwrap(); + MethodsContract::new(id.to_string(), wallet) +} diff --git a/test/src/sdk-harness/test_projects/reentrancy/mod.rs b/test/src/sdk-harness/test_projects/reentrancy/mod.rs index b100f414536..4b0a14d3915 100644 --- a/test/src/sdk-harness/test_projects/reentrancy/mod.rs +++ b/test/src/sdk-harness/test_projects/reentrancy/mod.rs @@ -1,7 +1,6 @@ use fuels::prelude::*; use fuels::signers::wallet::Wallet; -use fuels::tx::{default_parameters::MAX_GAS_PER_TX, ContractId}; -use fuels_abigen_macro::abigen; +use fuels::tx::{ConsensusParameters, ContractId}; abigen!( AttackerContract, @@ -22,7 +21,12 @@ async fn can_detect_reentrancy() { let result = attacker_instance .launch_attack(target_id) .set_contracts(&[target_id]) - .tx_params(TxParameters::new(Some(0), Some(MAX_GAS_PER_TX), None, None)) + .tx_params(TxParameters::new( + Some(0), + Some(ConsensusParameters::DEFAULT.max_gas_per_tx), + None, + None, + )) .call() .await .unwrap(); diff --git a/test/src/sdk-harness/test_projects/registers/mod.rs b/test/src/sdk-harness/test_projects/registers/mod.rs index b5797a9fb6c..26500ff29a8 100644 --- a/test/src/sdk-harness/test_projects/registers/mod.rs +++ b/test/src/sdk-harness/test_projects/registers/mod.rs @@ -1,6 +1,5 @@ use fuel_vm::consts::VM_MAX_RAM; use fuels::prelude::*; -use fuels_abigen_macro::abigen; abigen!( TestRegistersContract, diff --git a/test/src/sdk-harness/test_projects/script_data/mod.rs b/test/src/sdk-harness/test_projects/script_data/mod.rs index 9377f91ead7..84df5a132dd 100644 --- a/test/src/sdk-harness/test_projects/script_data/mod.rs +++ b/test/src/sdk-harness/test_projects/script_data/mod.rs @@ -2,7 +2,7 @@ use assert_matches::assert_matches; use fuel_core::service::{Config, FuelService}; use fuel_gql_client::client::FuelClient; use fuels::contract::script::Script; -use fuels::tx::{default_parameters::MAX_GAS_PER_TX, Receipt, Transaction}; +use fuels::tx::{ConsensusParameters, Receipt, Transaction}; async fn call_script(script_data: Vec) -> Result, fuels::prelude::Error> { let bin = std::fs::read("test_projects/script_data/out/debug/script_data.bin"); @@ -11,7 +11,7 @@ async fn call_script(script_data: Vec) -> Result, fuels::prelud let tx = Transaction::Script { gas_price: 0, - gas_limit: MAX_GAS_PER_TX, + gas_limit: ConsensusParameters::DEFAULT.max_gas_per_tx, maturity: 0, byte_price: 0, receipts_root: Default::default(), diff --git a/test/src/sdk-harness/test_projects/storage/mod.rs b/test/src/sdk-harness/test_projects/storage/mod.rs index 544079f650e..97bf157bd26 100644 --- a/test/src/sdk-harness/test_projects/storage/mod.rs +++ b/test/src/sdk-harness/test_projects/storage/mod.rs @@ -1,5 +1,4 @@ use fuels::prelude::*; -use fuels_abigen_macro::abigen; abigen!( TestStorageContract, diff --git a/test/src/sdk-harness/test_projects/storage_map/mod.rs b/test/src/sdk-harness/test_projects/storage_map/mod.rs index fe72514eda2..a1dc1b1a736 100644 --- a/test/src/sdk-harness/test_projects/storage_map/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_map/mod.rs @@ -1,5 +1,4 @@ use fuels::prelude::*; -use fuels_abigen_macro::abigen; abigen!( TestStorageMapContract, diff --git a/test/src/sdk-harness/test_projects/token_ops/mod.rs b/test/src/sdk-harness/test_projects/token_ops/mod.rs index e4f89152f6c..0127a116517 100644 --- a/test/src/sdk-harness/test_projects/token_ops/mod.rs +++ b/test/src/sdk-harness/test_projects/token_ops/mod.rs @@ -1,7 +1,6 @@ use fuels::prelude::*; use fuels::signers::wallet::Wallet; use fuels::tx::{AssetId, ContractId}; -use fuels_abigen_macro::abigen; abigen!( TestFuelCoinContract, diff --git a/test/src/sdk-harness/test_projects/tx_fields/mod.rs b/test/src/sdk-harness/test_projects/tx_fields/mod.rs index 23bd01aee8a..9c3b6cad763 100644 --- a/test/src/sdk-harness/test_projects/tx_fields/mod.rs +++ b/test/src/sdk-harness/test_projects/tx_fields/mod.rs @@ -1,9 +1,9 @@ use fuel_types::bytes::WORD_SIZE; -use fuel_vm::consts::VM_TX_MEMORY; +use fuel_vm::fuel_tx::ConsensusParameters; use fuels::prelude::*; use fuels::signers::wallet::Wallet; use fuels::tx::{Bytes32, ContractId}; -use fuels_abigen_macro::abigen; +use std::str::FromStr; abigen!( TxContractTest, @@ -92,7 +92,7 @@ async fn can_get_maturity() { async fn can_get_script_length() { let (contract_instance, _, _) = get_contracts().await; // TODO use programmatic script length https://github.com/FuelLabs/fuels-rs/issues/181 - let script_length = 24; + let script_length = 32; let result = contract_instance .get_tx_script_length() @@ -106,7 +106,7 @@ async fn can_get_script_length() { async fn can_get_script_data_length() { let (contract_instance, _, _) = get_contracts().await; // TODO make this programmatic. - let script_data_length = 80; + let script_data_length = 88; let result = contract_instance .get_tx_script_data_length() @@ -158,7 +158,9 @@ async fn can_get_witnesses_count() { #[tokio::test] async fn can_get_receipts_root() { let (contract_instance, _, _) = get_contracts().await; - let zero_receipts_root = Bytes32::default(); + let zero_receipts_root = + Bytes32::from_str("4be973feb50f1dabb9b2e451229135add52f9c0973c11e556fe5bce4a19df470") + .unwrap(); let result = contract_instance .get_tx_receipts_root() @@ -187,7 +189,8 @@ async fn can_get_script_start_offset() { + WORD_SIZE // Outputs size + WORD_SIZE // Witnesses size + Bytes32::LEN; // Receipts root - let script_start_offset = VM_TX_MEMORY + TRANSACTION_SCRIPT_FIXED_SIZE; + let script_start_offset = + ConsensusParameters::DEFAULT.tx_offset() + TRANSACTION_SCRIPT_FIXED_SIZE; let result = contract_instance .get_tx_script_start_offset() From c04be393c376b336384b3c29b0244c5fb24d7230 Mon Sep 17 00:00:00 2001 From: SwayStar123 <46050679+SwayStar123@users.noreply.github.com> Date: Thu, 30 Jun 2022 17:48:56 +0530 Subject: [PATCH 24/59] merge master to storage_vec (#2184) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove extra "the" (#2042) looks like an extra "the" got into this comment * Run `cargo update`. (#2045) * sway-fmt-v2 adds program type to the output (#1997) * Fix couple of bugs in handling returns in if blocks (#2029) * Config driven E2E testing. (#2003) Completely refactor E2E tests to be config driven. Rather than specifying which tests are to be run and how, we now can describe each test with a TOML file. * Handle enums and their impls for item imports (#2034) * Add `Identity` type to Sway Book (#2041) * Add Identity type to Sway Book * Move Identity code to examples directory * Add Forc.lock to gitignore * Update docs/src/basics/blockchain_types.md Co-authored-by: John Adler * Typo * Ran forc fmt * Update Cargo.toml * Update examples/identity/src/main.sw Co-authored-by: Mohammad Fawaz * Delete Cargo.toml * Update Identity docs to use anchor * Fix CI * Add path to std in Forc.toml and update Forc.lock std source * Run forc fmt again Co-authored-by: John Adler Co-authored-by: Mohammad Fawaz * Improve struct patterns with new warnings and rest pattern support. (#2032) * Improve struct patterns with new warnings and rest pattern support. This commit improves a couple aspects of handling of struct patterns. First of all, it adds semantic checking (with a new warning) when patterns are missing usage of all fields: ``` error --> src/main.sw:15:9 | 13 | 14 | let z = match p { 15 | Point { x } => { x }, | ^^^^^^^^^^^ Pattern does not mention field: y 16 | }; | ____ ``` Then it adds support for rest pattern, "..", which can be used as the last token in a pattern to not have to specify all the struct fields. The semantic AST model was updated to support modeling this pattern, and further type checking was added to the code. There is also a new warning for when the rest pattern doesn't appear as the last location, or when it appears multiple times: ``` error --> src/main.sw:17:20 | 15 | 16 | let z = match p { 17 | Point { x, .., .. } => { x }, | ^^ Unexpected rest token, must be at the end of pattern. 18 | }; | ____ ``` And lastly, tests were added to cover the changes and new functionality. Closes https://github.com/FuelLabs/sway/issues/1568. * Do not use an underscored identifier. * Add some more pattern matching tests. * Port to new config-driven tests. Co-authored-by: Mohammad Fawaz * Add the concept of semantic similarity to the type system (#1958) * Do not rely on TypeMapping when type checking declarations. * Prevent leaking types in impls. * Prevent unconstrained type parameters. * WIP * clippy * WIP * Use TypeId in TypeMapping and in TraitMap. * Add semantic type constraints. * Update test case. * fix * Some updates to the known issues section (#2060) Updates to the known issues section * Constants formatting for sway-fmt-v2 (#2021) * Update the check for unresolved types. (#2057) * Update the check for unresolved types. * clippy * Remove calls to log. * fmt * Remove unused file. * Make `resolve_type_with_self` and `resolve_type_without_self` take `TypeId`'s instead of `TypeInfo`'s (#1982) * Do not rely on TypeMapping when type checking declarations. * Prevent leaking types in impls. * Prevent unconstrained type parameters. * WIP * clippy * WIP * Use TypeId in TypeMapping and in TraitMap. * Add semantic type constraints. * Update test case. * fix * Use TypeId inside of resolve_type_with_self and resolve_type_without_self. * clippy * X * Bug is fixed. * Add forc.lock. * update * Move test to inside of the SDK. * Fix test cases. * Add lock files. * Fix test. * Bump non-transitive `dashmap` to v5.3.4. (#2062) Bump explicit `dashmap` to v5.3.4. * comby-rust (#2065) * comby-rust * Fix clippy warning Co-authored-by: Mohammad Fawaz * Adds `attribute` handling to `sway-fmt-v2` (#2061) * wip * add unit test * update tests * updated unimplemented cases to return span * test now passes incorrectly * update AttributeDecl::format() * update test comment * add close paren * update Annotated for consistency * chng return type for Annotated * remove test and add todos * Introduce a type check `Context`. Replaces `TypeCheckArguments`. (#2004) * Introduce a type check `Context`. Replaces `TypeCheckArguments`. * Add missing unknown type annotation. Clean up some formatting. Also adds some resetting of the help text and type annotation (to unknown) in many cases to better match the original behaviour. It's difficult to tell which locations these values were originally used as placeholders, and which locations they're a necessity for correctness. This at least appears to fix an issue with expression return type inference. * Rename semantic_analysis::Context to TypeCheckContext * Improve field doc comments for help_text, self_type * Add doc comment to mode field in TypeCheckContext * Construct TypeCheckContext at Program level, not module level. This should help to clarify how we can pass other type check context (like the declaration and type engines once they're added) through to the submodules. Previously, this was a little unclear as the `TypeCheckContext` was only constructed at the module level. * Add missing namespace field doc comment to TypeCheckContext * Fix TypeCheckContext constructor in IR test * Add `forc check` command (#2026) * wip * moving back to PC computer * adding check function to forc pkg * have ast returning from forc pkg * can now successfully parse all sway examples * fmt * added forc check * tidy up lsp tests * add forc check command * forc ops doesnt need to be public * tidy up lsp tests * remove non relevant code * rebase on master * add Cargo.lock file * add forc check to mdbook * Small fixes to the `storage_map` example (#2079) Small fix to storage_map example * Move `TypeArgument`, `TypeParameter`, and `TraitConstraints` to be conceptually inside of the type engine (#2074) Move the stuff. * Ensure lock is applied when `BuildPlan` validation would require changes (#2090) Ensure lock is applied if BuildPlan validation requires changes While reviewing #2085, I noticed that some recent additions to `BuildPlan` validation could result in some changes to the build plan (and in turn, rewriting the lock file) even in the case that `--locked` was specified. This moves the `--locked` check to the moment before writing the new lock file. This ensures all potential changes that would be required of the `BuildPlan` are caught. It also allows us to provide a "Cause" for *why* the lock file would need updating when `--locked` is passed to prevent it. Closes #2084 Closes #2085 * Add conceptual distinction between replacing `TypeInfo::Self` and monomorphization (#2017) * Do not rely on TypeMapping when type checking declarations. * Prevent leaking types in impls. * Prevent unconstrained type parameters. * WIP * clippy * WIP * Use TypeId in TypeMapping and in TraitMap. * Add semantic type constraints. * Update test case. * fix * Use TypeId inside of resolve_type_with_self and resolve_type_without_self. * clippy * X * Remove self_type from monomorphization. * Add conceptual distinction between replacing TypeInfo::Self and monomorphization. * Bug is fixed. * Add forc.lock. * update * Move test to inside of the SDK. * Fix test cases. * Add lock files. * Fix test. * Add `abi` handling to `sway-fmt-v2` (#2044) * Refactor `forc_pkg::BuildConfig` -> `BuildProfile`, fix CLI arg handling (#2094) Previously, if any of the `print` args were set, the rest of the selected build profile was ignored. This changes the behaviour so that the command line arguments only override their associated build profile fields. Also renames `BuildConfig` to `BuildProfile` and moves it from `forc_pkg::pkg` to `forc_pkg::manifest` along with the rest of the serializable manifest types. * Update all the E2E should_fail tests to verify their output. (#2082) Using the `FileCheck` crate it can now pattern match against the compiler output to be sure the errors and/or warnings are exactly what we expect. * forc: Improve the `print_*_asm` CLI option docs (#2095) Previously, these implied no bytecode was generated if the flag was not set, however this is not the case. * update fuelup related instructions (#2099) * update fuelup instructions * better instructions * better wording for modifying path * Adding `--time-phases` to `forc build` (#2091) * make items under [project] ordered alphabetically in forc.toml * issue #1893store/show bytecode hash * formatted * added cargo lock file * cargo toml dependencies in alphabetical order * hash bin of script or predicate only * format * generating bytecode hash only on scripts and predicates * removed option from Compiled::tree_type * ran clippy * added to forc_build documentation * made filename suffix containing bin hash a constant * get root of predicate bytecode * Apply suggestions from code review Co-authored-by: Mohammad Fawaz * if let to match on program type * Update forc/src/cli/commands/build.rs updating bin-root filename Co-authored-by: mitchmindtree * added benchmarks for compilation process * use macro instead of closure for wrapping parts of compilation process Co-authored-by: Waseem G Co-authored-by: Mohammad Fawaz Co-authored-by: mitchmindtree Co-authored-by: Toby Hutton * Add forc feature for overriding packages in the package graph, akin to cargo's [patch] feature (#1836) * Bump to v0.16.2 (#2105) * bump to v0.16.2 * Fix one test not pointing to local std * Add struct formatting to sway-fmt-v2 (#2058) * internal: Reduce amount of String::new() in sway-fmt-v2 (#2111) * examples: fix renaming to BASE_ASSET_ID in comment (#2120) * Added storage field alignment threshold to formatter config (#2113) * Enable storage initializers and emit a storage initialization JSON (#2078) * Enable storage initializers and dump out a JSON file * Move the new functions into a separate storage module * Use StorageSlot directly from fuel-tx * forc deploy now uses the storage slots * add some tests * lint, change initializers -> slots, and fixing some tests * enhance a comment * Revert unneeded changes to sway-types * add a failing test * Fix failing test * renaming some functions * Test the storage slots JSON in e2e tests and add forc json-storage-slots command * ignore *_output.json * forc documenter changes * Remove forc json-storage-slots and stop relying on forc json-abi * Enhance some comments * Remove unnecessary oracle * Improve reserved keywords checking and add support for raw identifiers. (#2066) Add support for raw identifiers and improve reserved keywords checking. This commit deals with the usage and checking of reserved keywords as identifiers, for code like: ``` fn main() { let mut mut = 0; } It introduces a new error that checks if an identifier is a reserved keyword: ``` error --> /main.sw:4:13 | 2 | 3 | fn main() { 4 | let mut mut = 0; | ^^^ Identifiers cannot be a reserved keyword. 5 | } | ____ ``` There was an existing issue in the standard library, which has a library/module named `storage`. Instead of working around this by renaming it to something else, an alternative solution with raw identifiers is implemented. This raw identifier feature is implemented at the lexer level, and allows you to use keywords as identifiers in places that generally wouldn't be allowed. Rust and a bunch of other modern languages also provide this escape hatch, and it seemed the simplest solution for me to handle the issue. It activates by declaring an identifier prefixed with `r#`, just like Rust. The complexity on the codebase to support this feature is pretty minimal, but if there any objections to this, I can easily remove it, but some other solution to the issue above will need to be figured out. Closes https://github.com/FuelLabs/sway/issues/1996. Co-authored-by: Mohammad Fawaz * remove `fuels-abigen-macro` dependency (#2007) * add remove fuels-abigen-macro dependency * add change dep. versions * add fuel 0.16 * add fuel-core-lib flag * add fuel-core-lib flag fix * add fuel-core-lib flag fix * add fuel-core-lib flag fix * add fuel-core-lib flag fix * add remove -- form forc test command * add replace constants * add expand CI command * add fix tests * add fix tests * Update test/src/sdk-harness/Cargo.toml Co-authored-by: John Adler * Update test/src/sdk-harness/Cargo.toml Co-authored-by: John Adler * Update test/src/sdk-harness/Cargo.toml Co-authored-by: John Adler * add return -- cmd * add remove fuels-abigen-macro from tests * add remove fuel-core-lib flag * add fuel-core-lib flag * add reverte CI file * add remove features * add remove [features] * add merge master Co-authored-by: Mohammad Fawaz Co-authored-by: John Adler * Adds `Generics` handling to `sway-fmt-v2` (#2110) * #2020 - changed BASE_ASSET_ID type to ContractId (#2137) * #2020 - changed BASE_ASSET_ID type to ContractId * Fix identity example * Changes after review * #2039 - add storage keyword highlighting in book (#2141) * #2039 - add storage keyword highlighting in book * Changes after review Co-authored-by: John Adler * Add the U256 type (#2103) * feat: add new bare u256 module to std * feat: Add base type + from,into traits * test: setup testing for U256 * cleanup * feat: add impl U256 max, min, bits, new * test: add new test assertions * style: fmt * test: generate oracle file * Update sway-lib-std/src/u256.sw Co-authored-by: John Adler * fix: remove * import * fix: improve error handling * test: better test coverage * style: fmt * docs: add test comments * test: add more test cases for to_u64() * fix: remove #r prefix from storage lib * test: remove redundant test * refactor: rename to_u64 to as_u64 * Revert "fix: remove #r prefix from storage lib" This reverts commit 8dd0738de0fef716193b6effee9b9956822157a7. Co-authored-by: John Adler * sway-fmt-v2 formatting should use tokens directly from sway-parse (#2097) * Move monomorphization conceptually inside of the type engine (#2093) * Do not rely on TypeMapping when type checking declarations. * Prevent leaking types in impls. * Prevent unconstrained type parameters. * WIP * clippy * WIP * Use TypeId in TypeMapping and in TraitMap. * Add semantic type constraints. * Update test case. * fix * Use TypeId inside of resolve_type_with_self and resolve_type_without_self. * clippy * X * Remove self_type from monomorphization. * Add conceptual distinction between replacing TypeInfo::Self and monomorphization. * Bug is fixed. * Add forc.lock. * update * Move test to inside of the SDK. * Fix test cases. * Add lock files. * Fix test. * Move the stuff. * Move monomorphization conceptually inside of the type engine. * Remove commented out test. * `forc-pkg` - Don't add transitive deps (besides `core`) to a package's initial namespace (#2136) `forc-pkg` - Don't add transitive deps (besides `core`) to namespace Currently `forc-pkg` adds all transitive dependencies to a package's initial namespace prior to its compilation. This had the benefit of implicitly including `core`, but with the downside of implicitly including every other transitive dependency package, even if not a direct depednency (not what we want). This PR changes the behaviour to only include direct dependencies and `core` within a package's initial namespace. Addresses 1, 2 of #2125. * Demonstrate that `T` for `Vec` can now be inferred by arguments (#2132) The bug is fixed. * Remove unnecessary "core" str check in `Span::join` (#2156) * Update the book to explicitly mention that `impl` functions can't call each other yet. (#2160) * Remove duplicate CI checks that already have dedicated jobs (#2161) I noticed a bunch of our CI jobs were were duplicating existing checks. In particular, there was a lot of copy-paste steps of installing forc and the forc-fmt plugin, even when unused in the following checks. This doesn't improve the real bottleneck (our stdlib test job), but it's a start. * Speedup `find_dead_code` pass in control flow analysis (#2159) Fix slow `find_dead_code` pass in control flow analysis While waiting for the tests to pass on a PR I thought I'd have a quick look to see if I could find any quick wins for dead code analysis #1952. I noticed that that we're using `has_path_connecting` for every combination of node and entry point. This means we were re-checking the same nodes many, many times, searching from scratch each time and not re-using any of the knowledge of already visited nodes in each consecutive traversal. This commit refactors the approach to first collect all known live nodes into a set by traversing from the entry points. We re-use the same `Dfs` when searching from each entry in order to re-use its inner set of visited nodes and avoid re-searching sections of the graph that we've already visited. The dead nodes are those not contained in the live set after traversal. This reduces the time taken within the `find_dead_code` call when building the `std` library in debug from ~7.9 seconds down to ~3.3 milliseconds. 1000x+ speedup in DCA :) Hopefully this speeds up our CI a bit! Closes #1952. * const initialization: a few fixes (#2158) * const initialization: a few fixes * cargo fmt * Address review comments * Add IR test Co-authored-by: Mohammad Fawaz * Update broken link for contributing to Sway in README.md (#2172) Closes https://github.com/FuelLabs/sway/issues/2171 * Backport improvements to `U128` type. (#2169) * feat: improve U128 type errors & rename to_u264 * test: add tests for renamed as_u64 * Introduce `__eq` intrinsic (#2100) * Introduce `__eq` intrinsic * Lower to `Instruction::Cmp` instead of to assembly in IRGen * Refactor intrinsics to all have arg and type arg vectors * Improvements around `forc plugins` command (#1969) Use the full path of the plugin when parsing it for a description. This avoids the following panic caused by trying to exec an executable in a sub-folder with a partial path: ``` ~/dev/sway/target/debug$ forc plugins Installed Plugins: thread 'main' panicked at 'Could not get plugin description.: Os { code: 2, kind: NotFound, message: "No such file or directory" }', forc/src/cli/commands/plugins.rs:43:10 stack backtrace: 0: rust_begin_unwind at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/panicking.rs:584:5 1: core::panicking::panic_fmt at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/panicking.rs:143:14 2: core::result::unwrap_failed at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/result.rs:1785:5 3: core::result::Result::expect at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/result.rs:1035:23 4: forc::cli::commands::plugins::parse_description_for_plugin at /home/joao/dev/sway/forc/src/cli/commands/plugins.rs:40:16 5: forc::cli::commands::plugins::format_print_description at /home/joao/dev/sway/forc/src/cli/commands/plugins.rs:81:23 6: forc::cli::commands::plugins::print_plugin at /home/joao/dev/sway/forc/src/cli/commands/plugins.rs:97:5 7: forc::cli::commands::plugins::exec at /home/joao/dev/sway/forc/src/cli/commands/plugins.rs:28:21 ``` * Updates `user_def` with `FieldAlignment` & fix corresponding use cases (#2153) * update user_def with AlignFields & fix corresponding use cases * rmv unused consts * update doc comments in ItemEnum * Add `lex_commented` and `CommentedTokenStream` to `sway_parse` (#2123) * Add `CommentedTokenStream` to `sway_parse` This doesn't yet collect any comments, but adds the necessary structure and attempts to preserve the original API and behaviour where possible. Collecting of comments to be added in a follow-up commit. * Collect multi-line comments in CommentedTokenStream * Collect single-line comments in CommentedTokenStream * Add token_trees and spanned impls for CommentedTokenStream * Add Spanned impl for CommentedTokenTree. Add comment lexing test. * Expose `lex_commented` function from root * Add CommentedTree and CommentedGroup aliases * Move CommentedTokenTree impl to better location * Clean up by using CommentedTree type alias where applicable Co-authored-by: Alex Hansen Co-authored-by: Chris O'Brien <57543709+eureka-cpu@users.noreply.github.com> * Remove unused field `const_decl_origin` from `TypedVariableDeclaration` (#2181) Remove unused const_decl_origin from TypedVariableDeclaration After #2158, constant declartaions use TypedConstantDeclaration AST node, and hence this field is now useless. It must have been removed in #2158 itself, but I missed doing that. Co-authored-by: John Adler Co-authored-by: Kaya Gökalp Co-authored-by: Vaivaswatha N Co-authored-by: Toby Hutton Co-authored-by: Mohammad Fawaz Co-authored-by: Cameron Carstens <54727135+bitzoic@users.noreply.github.com> Co-authored-by: João Matos Co-authored-by: Emily Herbert <17410721+emilyaherbert@users.noreply.github.com> Co-authored-by: rakita Co-authored-by: Chris O'Brien <57543709+eureka-cpu@users.noreply.github.com> Co-authored-by: mitchmindtree Co-authored-by: Joshua Batty Co-authored-by: bing Co-authored-by: seem-less Co-authored-by: Waseem G Co-authored-by: mitchmindtree Co-authored-by: zhou fan <1247714429@qq.com> Co-authored-by: Hlib Kanunnikov Co-authored-by: Emir Co-authored-by: r-sitko <19492095+r-sitko@users.noreply.github.com> Co-authored-by: Nick Furfaro Co-authored-by: Alex Hansen From 3ad6fca0de7a7926d9dfbc8619ecfc814f44bd0f Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 30 Jun 2022 18:48:41 +0530 Subject: [PATCH 25/59] removed unncessary use --- test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs index fadcccc0b1d..c2324f308cf 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs @@ -1,6 +1,4 @@ use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - // Load abi from json abigen!(MyContract, "test_artifacts/storage_vec/svec_u8/out/debug/svec_u8-abi.json"); From 859b0f6534a5e0c70eb185b5a7d77b24e5fe7019 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 30 Jun 2022 19:25:47 +0530 Subject: [PATCH 26/59] added one test --- .../sdk-harness/test_projects/storage_vec/mod.rs | 14 +++++++++++--- .../test_projects/storage_vec/utils/mod.rs | 8 ++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index fa4b0b96c52..9c289c8a605 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -1,12 +1,20 @@ mod utils; -use fuels::{prelude::*, tx::ContractId}; - -use utils::get_contract_instance; +use utils::*; #[tokio::test] async fn can_get_contract_id() { let (_instance, _id) = get_contract_instance().await; // Now you have an instance of your contract you can use to test each function +} + +#[tokio::test] +async fn can_push() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + let item = get(&instance, 0).await; + + assert_eq!(item, 50); } \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs index c2324f308cf..57851d9813d 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs @@ -13,4 +13,12 @@ pub async fn get_contract_instance() -> (MyContract, ContractId) { let instance = MyContract::new(id.to_string(), wallet); (instance, id) +} + +pub async fn push(instance: &MyContract, value: u8) { + instance.vec_u8_push(value).call().await.unwrap(); +} + +pub async fn get(instance: &MyContract, index: u64) -> u8 { + instance.vec_u8_get(index).call().await.unwrap().value } \ No newline at end of file From 7092230826549ca4ad252de1c9493aa0fdd54d53 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 30 Jun 2022 19:37:09 +0530 Subject: [PATCH 27/59] deleted all contracts except u8s --- .../storage_vec/svec_array/.gitignore | 2 - .../storage_vec/svec_array/Cargo.toml | 16 ---- .../storage_vec/svec_array/Forc.lock | 14 ---- .../storage_vec/svec_array/Forc.toml | 8 -- .../storage_vec/svec_array/src/main.sw | 70 ----------------- .../storage_vec/svec_array/tests/harness.rs | 25 ------- .../storage_vec/svec_b256/.gitignore | 2 - .../storage_vec/svec_b256/Cargo.toml | 16 ---- .../storage_vec/svec_b256/Forc.lock | 14 ---- .../storage_vec/svec_b256/Forc.toml | 8 -- .../storage_vec/svec_b256/src/main.sw | 70 ----------------- .../storage_vec/svec_b256/tests/harness.rs | 25 ------- .../storage_vec/svec_bool/.gitignore | 2 - .../storage_vec/svec_bool/Cargo.toml | 16 ---- .../storage_vec/svec_bool/Forc.lock | 14 ---- .../storage_vec/svec_bool/Forc.toml | 8 -- .../storage_vec/svec_bool/src/main.sw | 69 ----------------- .../storage_vec/svec_bool/tests/harness.rs | 25 ------- .../storage_vec/svec_enum/.gitignore | 2 - .../storage_vec/svec_enum/Cargo.toml | 16 ---- .../storage_vec/svec_enum/Forc.lock | 14 ---- .../storage_vec/svec_enum/Forc.toml | 8 -- .../storage_vec/svec_enum/src/main.sw | 75 ------------------- .../storage_vec/svec_enum/tests/harness.rs | 25 ------- .../storage_vec/svec_str/.gitignore | 2 - .../storage_vec/svec_str/Cargo.toml | 16 ---- .../storage_vec/svec_str/Forc.lock | 14 ---- .../storage_vec/svec_str/Forc.toml | 8 -- .../storage_vec/svec_str/src/main.sw | 70 ----------------- .../storage_vec/svec_str/tests/harness.rs | 25 ------- .../storage_vec/svec_struct/.gitignore | 2 - .../storage_vec/svec_struct/Cargo.toml | 16 ---- .../storage_vec/svec_struct/Forc.lock | 14 ---- .../storage_vec/svec_struct/Forc.toml | 8 -- .../storage_vec/svec_struct/src/main.sw | 75 ------------------- .../storage_vec/svec_struct/tests/harness.rs | 25 ------- .../storage_vec/svec_tuple/.gitignore | 2 - .../storage_vec/svec_tuple/Cargo.toml | 16 ---- .../storage_vec/svec_tuple/Forc.lock | 14 ---- .../storage_vec/svec_tuple/Forc.toml | 8 -- .../storage_vec/svec_tuple/src/main.sw | 69 ----------------- .../storage_vec/svec_tuple/tests/harness.rs | 25 ------- .../storage_vec/svec_u16/.gitignore | 2 - .../storage_vec/svec_u16/Cargo.toml | 16 ---- .../storage_vec/svec_u16/Forc.lock | 14 ---- .../storage_vec/svec_u16/Forc.toml | 8 -- .../storage_vec/svec_u16/src/main.sw | 70 ----------------- .../storage_vec/svec_u16/tests/harness.rs | 25 ------- .../storage_vec/svec_u32/.gitignore | 2 - .../storage_vec/svec_u32/Cargo.toml | 16 ---- .../storage_vec/svec_u32/Forc.toml | 8 -- .../storage_vec/svec_u32/src/main.sw | 70 ----------------- .../storage_vec/svec_u32/tests/harness.rs | 25 ------- .../storage_vec/svec_u64/.gitignore | 2 - .../storage_vec/svec_u64/Cargo.toml | 16 ---- .../storage_vec/svec_u64/Forc.toml | 8 -- .../storage_vec/svec_u64/src/main.sw | 70 ----------------- .../storage_vec/svec_u64/tests/harness.rs | 25 ------- 58 files changed, 1330 deletions(-) delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_array/.gitignore delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Cargo.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.lock delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_array/src/main.sw delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_array/tests/harness.rs delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/.gitignore delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Cargo.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.lock delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/src/main.sw delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/tests/harness.rs delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/.gitignore delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Cargo.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.lock delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/src/main.sw delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/tests/harness.rs delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/.gitignore delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Cargo.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.lock delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/src/main.sw delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/tests/harness.rs delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/.gitignore delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Cargo.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.lock delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/src/main.sw delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/tests/harness.rs delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/.gitignore delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Cargo.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.lock delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/src/main.sw delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/tests/harness.rs delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/.gitignore delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Cargo.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.lock delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/src/main.sw delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/tests/harness.rs delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/.gitignore delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Cargo.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.lock delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/src/main.sw delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/tests/harness.rs delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/.gitignore delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Cargo.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/src/main.sw delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/tests/harness.rs delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/.gitignore delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Cargo.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/src/main.sw delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/tests/harness.rs diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/.gitignore deleted file mode 100644 index 77d3844f58c..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -out -target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Cargo.toml deleted file mode 100644 index a471f7fab0f..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "svec_array" -version = "0.1.0" -authors = ["Swaystar"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.lock deleted file mode 100644 index baa6e736c98..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.lock +++ /dev/null @@ -1,14 +0,0 @@ -[[package]] -name = 'core' -source = 'path+from-root-F1A9B05C249770CB' -dependencies = [] - -[[package]] -name = 'std' -source = 'path+from-root-F1A9B05C249770CB' -dependencies = ['core'] - -[[package]] -name = 'svec_array' -source = 'root' -dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.toml deleted file mode 100644 index a5e3bc65639..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/Forc.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -authors = ["Fuel Labs "] -entry = "main.sw" -license = "Apache-2.0" -name = "svec_array" - -[dependencies] -std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/src/main.sw deleted file mode 100644 index 2039fac25c5..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/src/main.sw +++ /dev/null @@ -1,70 +0,0 @@ -contract; - -use std::option::*; -use std::result::*; -use std::storage::{StorageVec, StorageVecError}; - -abi MyContract { - #[storage(read, write)] - fn vec_array_push(value: [u64; 2]); - #[storage(read)] - fn vec_array_get(index: u64) -> Option<[u64; 2]>; - #[storage(read, write)] - fn vec_array_pop() -> Option<[u64; 2]>; - #[storage(read, write)] - fn vec_array_remove(index: u64) -> Result<[u64; 2], StorageVecError>; - #[storage(read, write)] - fn vec_array_swap_remove(index: u64) -> Result<[u64; 2], StorageVecError>; - #[storage(read, write)] - fn vec_array_insert(index: u64, value: [u64; 2]) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_array_len() -> u64; - #[storage(read)] - fn vec_array_is_empty() -> bool; - #[storage(write)] - fn vec_array_clear(); -} - -storage { - vec_array: StorageVec<[u64; 2]>, -} - -impl MyContract for Contract { - #[storage(read, write)] - fn vec_array_push(value: [u64; 2]) { - storage.vec_array.push(value); - } - #[storage(read)] - fn vec_array_get(index: u64) -> Option<[u64; 2]> { - storage.vec_array.get(index) - } - #[storage(read, write)] - fn vec_array_pop() -> Option<[u64; 2]> { - storage.vec_array.pop() - } - #[storage(read, write)] - fn vec_array_remove(index: u64) -> Result<[u64; 2], StorageVecError> { - let res: Result<[u64; 2], StorageVecError> = storage.vec_array.remove(index); - res - } - #[storage(read, write)] - fn vec_array_swap_remove(index: u64) -> Result<[u64; 2], StorageVecError> { - storage.vec_array.swap_remove(index) - } - #[storage(read, write)] - fn vec_array_insert(index: u64, value: [u64; 2]) -> Result<(), StorageVecError> { - storage.vec_array.insert(index, value) - } - #[storage(read)] - fn vec_array_len() -> u64 { - storage.vec_array.len() - } - #[storage(read)] - fn vec_array_is_empty() -> bool { - storage.vec_array.is_empty() - } - #[storage(write)] - fn vec_array_clear() { - storage.vec_array.clear(); - } -} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/tests/harness.rs deleted file mode 100644 index 513330cadaa..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_array/tests/harness.rs +++ /dev/null @@ -1,25 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -// Load abi from json -abigen!(MyContract, "out/debug/svec_array-abi.json"); - -async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; - - let id = Contract::deploy("./out/debug/svec_array.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/.gitignore deleted file mode 100644 index 77d3844f58c..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -out -target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Cargo.toml deleted file mode 100644 index ce674a3ee50..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "svec_b256" -version = "0.1.0" -authors = ["Swaystar"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.lock deleted file mode 100644 index 37516c69109..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.lock +++ /dev/null @@ -1,14 +0,0 @@ -[[package]] -name = 'core' -source = 'path+from-root-BAD4826C86E6CE3D' -dependencies = [] - -[[package]] -name = 'std' -source = 'path+from-root-BAD4826C86E6CE3D' -dependencies = ['core'] - -[[package]] -name = 'svec_b256' -source = 'root' -dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.toml deleted file mode 100644 index 862b2b60675..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -authors = ["Fuel Labs "] -entry = "main.sw" -license = "Apache-2.0" -name = "svec_b256" - -[dependencies] -std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/src/main.sw deleted file mode 100644 index 116d705687b..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/src/main.sw +++ /dev/null @@ -1,70 +0,0 @@ -contract; - -use std::option::*; -use std::result::*; -use std::storage::{StorageVec, StorageVecError}; - -abi MyContract { - #[storage(read, write)] - fn vec_b256_push(value: b256); - #[storage(read)] - fn vec_b256_get(index: u64) -> Option; - #[storage(read, write)] - fn vec_b256_pop() -> Option; - #[storage(read, write)] - fn vec_b256_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_b256_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_b256_insert(index: u64, value: b256) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_b256_len() -> u64; - #[storage(read)] - fn vec_b256_is_empty() -> bool; - #[storage(write)] - fn vec_b256_clear(); -} - -storage { - vec_b256: StorageVec, -} - -impl MyContract for Contract { - #[storage(read, write)] - fn vec_b256_push(value: b256) { - storage.vec_b256.push(value); - } - #[storage(read)] - fn vec_b256_get(index: u64) -> Option { - storage.vec_b256.get(index) - } - #[storage(read, write)] - fn vec_b256_pop() -> Option { - storage.vec_b256.pop() - } - #[storage(read, write)] - fn vec_b256_remove(index: u64) -> Result { - let res: Result = storage.vec_b256.remove(index); - res - } - #[storage(read, write)] - fn vec_b256_swap_remove(index: u64) -> Result { - storage.vec_b256.swap_remove(index) - } - #[storage(read, write)] - fn vec_b256_insert(index: u64, value: b256) -> Result<(), StorageVecError> { - storage.vec_b256.insert(index, value) - } - #[storage(read)] - fn vec_b256_len() -> u64 { - storage.vec_b256.len() - } - #[storage(read)] - fn vec_b256_is_empty() -> bool { - storage.vec_b256.is_empty() - } - #[storage(write)] - fn vec_b256_clear() { - storage.vec_b256.clear(); - } -} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/tests/harness.rs deleted file mode 100644 index 457930b90c4..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/tests/harness.rs +++ /dev/null @@ -1,25 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -// Load abi from json -abigen!(MyContract, "out/debug/svec_b256-abi.json"); - -async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; - - let id = Contract::deploy("./out/debug/svec_b256.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/.gitignore deleted file mode 100644 index 77d3844f58c..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -out -target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Cargo.toml deleted file mode 100644 index 6a391e26136..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "svec_bool" -version = "0.1.0" -authors = ["Swaystar"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.lock deleted file mode 100644 index d16c4ca4065..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.lock +++ /dev/null @@ -1,14 +0,0 @@ -[[package]] -name = 'core' -source = 'path+from-root-112F6FFCFCECE066' -dependencies = [] - -[[package]] -name = 'std' -source = 'path+from-root-112F6FFCFCECE066' -dependencies = ['core'] - -[[package]] -name = 'svec_bool' -source = 'root' -dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.toml deleted file mode 100644 index 0e8331413af..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -authors = ["Fuel Labs "] -entry = "main.sw" -license = "Apache-2.0" -name = "svec_bool" - -[dependencies] -std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/src/main.sw deleted file mode 100644 index ff16641c130..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/src/main.sw +++ /dev/null @@ -1,69 +0,0 @@ -contract; - -use std::option::*; -use std::result::*;use std::storage::{StorageVec, StorageVecError}; - -abi MyContract { - #[storage(read, write)] - fn vec_bool_push(value: bool); - #[storage(read)] - fn vec_bool_get(index: u64) -> Option; - #[storage(read, write)] - fn vec_bool_pop() -> Option; - #[storage(read, write)] - fn vec_bool_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_bool_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_bool_insert(index: u64, value: bool) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_bool_len() -> u64; - #[storage(read)] - fn vec_bool_is_empty() -> bool; - #[storage(write)] - fn vec_bool_clear(); -} - -storage { - vec_bool: StorageVec, -} - -impl MyContract for Contract { - #[storage(read, write)] - fn vec_bool_push(value: bool) { - storage.vec_bool.push(value); - } - #[storage(read)] - fn vec_bool_get(index: u64) -> Option { - storage.vec_bool.get(index) - } - #[storage(read, write)] - fn vec_bool_pop() -> Option { - storage.vec_bool.pop() - } - #[storage(read, write)] - fn vec_bool_remove(index: u64) -> Result { - let res: Result = storage.vec_bool.remove(index); - res - } - #[storage(read, write)] - fn vec_bool_swap_remove(index: u64) -> Result { - storage.vec_bool.swap_remove(index) - } - #[storage(read, write)] - fn vec_bool_insert(index: u64, value: bool) -> Result<(), StorageVecError> { - storage.vec_bool.insert(index, value) - } - #[storage(read)] - fn vec_bool_len() -> u64 { - storage.vec_bool.len() - } - #[storage(read)] - fn vec_bool_is_empty() -> bool { - storage.vec_bool.is_empty() - } - #[storage(write)] - fn vec_bool_clear() { - storage.vec_bool.clear(); - } -} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/tests/harness.rs deleted file mode 100644 index 18a887b6f06..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/tests/harness.rs +++ /dev/null @@ -1,25 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -// Load abi from json -abigen!(MyContract, "out/debug/svec_bool-abi.json"); - -async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; - - let id = Contract::deploy("./out/debug/svec_bool.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/.gitignore deleted file mode 100644 index 77d3844f58c..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -out -target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Cargo.toml deleted file mode 100644 index 0f00934c353..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "svec_enum" -version = "0.1.0" -authors = ["Swaystar"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.lock deleted file mode 100644 index 06f1f17cd10..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.lock +++ /dev/null @@ -1,14 +0,0 @@ -[[package]] -name = 'core' -source = 'path+from-root-BA7DA646BFFC59D3' -dependencies = [] - -[[package]] -name = 'std' -source = 'path+from-root-BA7DA646BFFC59D3' -dependencies = ['core'] - -[[package]] -name = 'svec_enum' -source = 'root' -dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.toml deleted file mode 100644 index 1c7b7856cc7..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -authors = ["Fuel Labs "] -entry = "main.sw" -license = "Apache-2.0" -name = "svec_enum" - -[dependencies] -std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/src/main.sw deleted file mode 100644 index d096f322b0e..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/src/main.sw +++ /dev/null @@ -1,75 +0,0 @@ -contract; - -use std::option::*; -use std::result::*; -use std::storage::{StorageVec, StorageVecError}; - -enum TestEnum { - A: (), - B: (), -} - -abi MyContract { - #[storage(read, write)] - fn vec_enum_push(value: TestEnum); - #[storage(read)] - fn vec_enum_get(index: u64) -> Option; - #[storage(read, write)] - fn vec_enum_pop() -> Option; - #[storage(read, write)] - fn vec_enum_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_enum_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_enum_insert(index: u64, value: TestEnum) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_enum_len() -> u64; - #[storage(read)] - fn vec_enum_is_empty() -> bool; - #[storage(write)] - fn vec_enum_clear(); -} - -storage { - vec_enum: StorageVec, -} - -impl MyContract for Contract { - #[storage(read, write)] - fn vec_enum_push(value: TestEnum) { - storage.vec_enum.push(value); - } - #[storage(read)] - fn vec_enum_get(index: u64) -> Option { - storage.vec_enum.get(index) - } - #[storage(read, write)] - fn vec_enum_pop() -> Option { - storage.vec_enum.pop() - } - #[storage(read, write)] - fn vec_enum_remove(index: u64) -> Result { - let res: Result = storage.vec_enum.remove(index); - res - } - #[storage(read, write)] - fn vec_enum_swap_remove(index: u64) -> Result { - storage.vec_enum.swap_remove(index) - } - #[storage(read, write)] - fn vec_enum_insert(index: u64, value: TestEnum) -> Result<(), StorageVecError> { - storage.vec_enum.insert(index, value) - } - #[storage(read)] - fn vec_enum_len() -> u64 { - storage.vec_enum.len() - } - #[storage(read)] - fn vec_enum_is_empty() -> bool { - storage.vec_enum.is_empty() - } - #[storage(write)] - fn vec_enum_clear() { - storage.vec_enum.clear(); - } -} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/tests/harness.rs deleted file mode 100644 index 2512f82c41c..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/tests/harness.rs +++ /dev/null @@ -1,25 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -// Load abi from json -abigen!(MyContract, "out/debug/svec_enum-abi.json"); - -async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; - - let id = Contract::deploy("./out/debug/svec_enum.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/.gitignore deleted file mode 100644 index 77d3844f58c..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -out -target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Cargo.toml deleted file mode 100644 index 973a1eddcbd..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "svec_str" -version = "0.1.0" -authors = ["Swaystar"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.lock deleted file mode 100644 index 117a72a36a9..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.lock +++ /dev/null @@ -1,14 +0,0 @@ -[[package]] -name = 'core' -source = 'path+from-root-5A8E0F2C8C65E65F' -dependencies = [] - -[[package]] -name = 'std' -source = 'path+from-root-5A8E0F2C8C65E65F' -dependencies = ['core'] - -[[package]] -name = 'svec_str' -source = 'root' -dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.toml deleted file mode 100644 index 7ed62be1140..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -authors = ["Fuel Labs "] -entry = "main.sw" -license = "Apache-2.0" -name = "svec_str" - -[dependencies] -std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/src/main.sw deleted file mode 100644 index e6a59d88e0c..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/src/main.sw +++ /dev/null @@ -1,70 +0,0 @@ -contract; - -use std::option::*; -use std::result::*; -use std::storage::{StorageVec, StorageVecError}; - -abi MyContract { - #[storage(read, write)] - fn vec_str_push(value: str[4]); - #[storage(read)] - fn vec_str_get(index: u64) -> Option; - #[storage(read, write)] - fn vec_str_pop() -> Option; - #[storage(read, write)] - fn vec_str_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_str_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_str_insert(index: u64, value: str[4]) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_str_len() -> u64; - #[storage(read)] - fn vec_str_is_empty() -> bool; - #[storage(write)] - fn vec_str_clear(); -} - -storage { - vec_str: StorageVec, -} - -impl MyContract for Contract { - #[storage(read, write)] - fn vec_str_push(value: str[4]) { - storage.vec_str.push(value); - } - #[storage(read)] - fn vec_str_get(index: u64) -> Option { - storage.vec_str.get(index) - } - #[storage(read, write)] - fn vec_str_pop() -> Option { - storage.vec_str.pop() - } - #[storage(read, write)] - fn vec_str_remove(index: u64) -> Result { - let res: Result = storage.vec_str.remove(index); - res - } - #[storage(read, write)] - fn vec_str_swap_remove(index: u64) -> Result { - storage.vec_str.swap_remove(index) - } - #[storage(read, write)] - fn vec_str_insert(index: u64, value: str[4]) -> Result<(), StorageVecError> { - storage.vec_str.insert(index, value) - } - #[storage(read)] - fn vec_str_len() -> u64 { - storage.vec_str.len() - } - #[storage(read)] - fn vec_str_is_empty() -> bool { - storage.vec_str.is_empty() - } - #[storage(write)] - fn vec_str_clear() { - storage.vec_str.clear(); - } -} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/tests/harness.rs deleted file mode 100644 index a0d48c38411..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/tests/harness.rs +++ /dev/null @@ -1,25 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -// Load abi from json -abigen!(MyContract, "out/debug/svec_str-abi.json"); - -async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; - - let id = Contract::deploy("./out/debug/svec_str.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/.gitignore deleted file mode 100644 index 77d3844f58c..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -out -target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Cargo.toml deleted file mode 100644 index cf1fb8175d3..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "svec_struct" -version = "0.1.0" -authors = ["Swaystar"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.lock deleted file mode 100644 index e185915ccb2..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.lock +++ /dev/null @@ -1,14 +0,0 @@ -[[package]] -name = 'core' -source = 'path+from-root-5D548BD88B479EAC' -dependencies = [] - -[[package]] -name = 'std' -source = 'path+from-root-5D548BD88B479EAC' -dependencies = ['core'] - -[[package]] -name = 'svec_struct' -source = 'root' -dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.toml deleted file mode 100644 index aff4003212f..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -authors = ["Fuel Labs "] -entry = "main.sw" -license = "Apache-2.0" -name = "svec_struct" - -[dependencies] -std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/src/main.sw deleted file mode 100644 index 7e1a8acf2ff..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/src/main.sw +++ /dev/null @@ -1,75 +0,0 @@ -contract; - -use std::option::*; -use std::result::*; -use std::storage::{StorageVec, StorageVecError}; - -struct TestStruct { - A: bool, - B: u64, -} - -abi MyContract { - #[storage(read, write)] - fn vec_struct_push(value: TestStruct); - #[storage(read)] - fn vec_struct_get(index: u64) -> Option; - #[storage(read, write)] - fn vec_struct_pop() -> Option; - #[storage(read, write)] - fn vec_struct_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_struct_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_struct_insert(index: u64, value: TestStruct) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_struct_len() -> u64; - #[storage(read)] - fn vec_struct_is_empty() -> bool; - #[storage(write)] - fn vec_struct_clear(); -} - -storage { - vec_struct: StorageVec, -} - -impl MyContract for Contract { - #[storage(read, write)] - fn vec_struct_push(value: TestStruct) { - storage.vec_struct.push(value); - } - #[storage(read)] - fn vec_struct_get(index: u64) -> Option { - storage.vec_struct.get(index) - } - #[storage(read, write)] - fn vec_struct_pop() -> Option { - storage.vec_struct.pop() - } - #[storage(read, write)] - fn vec_struct_remove(index: u64) -> Result { - let res: Result = storage.vec_struct.remove(index); - res - } - #[storage(read, write)] - fn vec_struct_swap_remove(index: u64) -> Result { - storage.vec_struct.swap_remove(index) - } - #[storage(read, write)] - fn vec_struct_insert(index: u64, value: TestStruct) -> Result<(), StorageVecError> { - storage.vec_struct.insert(index, value) - } - #[storage(read)] - fn vec_struct_len() -> u64 { - storage.vec_struct.len() - } - #[storage(read)] - fn vec_struct_is_empty() -> bool { - storage.vec_struct.is_empty() - } - #[storage(write)] - fn vec_struct_clear() { - storage.vec_struct.clear(); - } -} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/tests/harness.rs deleted file mode 100644 index 21459b9d887..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/tests/harness.rs +++ /dev/null @@ -1,25 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -// Load abi from json -abigen!(MyContract, "out/debug/svec_struct-abi.json"); - -async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; - - let id = Contract::deploy("./out/debug/svec_struct.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/.gitignore deleted file mode 100644 index 77d3844f58c..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -out -target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Cargo.toml deleted file mode 100644 index 7131428751b..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "svec_tuple" -version = "0.1.0" -authors = ["Swaystar"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.lock deleted file mode 100644 index 2f5681f767a..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.lock +++ /dev/null @@ -1,14 +0,0 @@ -[[package]] -name = 'core' -source = 'path+from-root-ADD23FE8604712AD' -dependencies = [] - -[[package]] -name = 'std' -source = 'path+from-root-ADD23FE8604712AD' -dependencies = ['core'] - -[[package]] -name = 'svec_tuple' -source = 'root' -dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.toml deleted file mode 100644 index 6423633708f..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/Forc.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -authors = ["Fuel Labs "] -entry = "main.sw" -license = "Apache-2.0" -name = "svec_tuple" - -[dependencies] -std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/src/main.sw deleted file mode 100644 index 526678e2fa9..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/src/main.sw +++ /dev/null @@ -1,69 +0,0 @@ -contract; - -use std::option::*; -use std::result::*; -use std::storage::{StorageVec, StorageVecError}; - -abi MyContract { - #[storage(read, write)] - fn vec_tuple_push(value: (u64, u64)); - #[storage(read)] - fn vec_tuple_get(index: u64) -> Option<(u64, u64)>; - #[storage(read, write)] - fn vec_tuple_pop() -> Option<(u64, u64)>; - #[storage(read, write)] - fn vec_tuple_remove(index: u64) -> Result<(u64, u64), StorageVecError>; - #[storage(read, write)] - fn vec_tuple_swap_remove(index: u64) -> Result<(u64, u64), StorageVecError>; - #[storage(read, write)] - fn vec_tuple_insert(index: u64, value: (u64, u64)) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_tuple_len() -> u64; - #[storage(read)] - fn vec_tuple_is_empty() -> bool; - #[storage(write)] - fn vec_tuple_clear(); -} - -storage { - vec_tuple: StorageVec<(u64, u64)>, -} - -impl MyContract for Contract { - #[storage(read, write)] - fn vec_tuple_push(value: (u64, u64)) { - storage.vec_tuple.push(value); - } - #[storage(read)] - fn vec_tuple_get(index: u64) -> Option<(u64, u64)> { - storage.vec_tuple.get(index) - } - #[storage(read, write)] - fn vec_tuple_pop() -> Option<(u64, u64)> { - storage.vec_tuple.pop() - } - #[storage(read, write)] - fn vec_tuple_remove(index: u64) -> Result<(u64, u64), StorageVecError> { - let res: Result<(u64, u64), StorageVecError> = storage.vec_tuple.remove(index); - res - } - #[storage(read, write)] - fn vec_tuple_swap_remove(index: u64) -> Result<(u64, u64), StorageVecError> { - storage.vec_tuple.swap_remove(index) - } - #[storage(read, write)] - fn vec_tuple_insert(index: u64, value: (u64, u64)) -> Result<(), StorageVecError> { - storage.vec_tuple.insert(index, value) - } - #[storage(read)] - fn vec_tuple_len() -> u64 { - storage.vec_tuple.len() - } - #[storage(read)] - fn vec_tuple_is_empty() -> bool { - storage.vec_tuple.is_empty() - } - #[storage(write)]fn vec_tuple_clear() { - storage.vec_tuple.clear(); - } -} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/tests/harness.rs deleted file mode 100644 index 5bd9c5c2b59..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_tuple/tests/harness.rs +++ /dev/null @@ -1,25 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -// Load abi from json -abigen!(MyContract, "out/debug/svec_tuple-abi.json"); - -async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; - - let id = Contract::deploy("./out/debug/svec_tuple.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/.gitignore deleted file mode 100644 index 77d3844f58c..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -out -target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Cargo.toml deleted file mode 100644 index f6f386eb174..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "svec_u16" -version = "0.1.0" -authors = ["Swaystar"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.lock deleted file mode 100644 index 3b133df026f..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.lock +++ /dev/null @@ -1,14 +0,0 @@ -[[package]] -name = 'core' -source = 'path+from-root-D2C27CF3A144E426' -dependencies = [] - -[[package]] -name = 'std' -source = 'path+from-root-D2C27CF3A144E426' -dependencies = ['core'] - -[[package]] -name = 'svec_u16' -source = 'root' -dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.toml deleted file mode 100644 index e8bdd27b98f..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -authors = ["Fuel Labs "] -entry = "main.sw" -license = "Apache-2.0" -name = "svec_u16" - -[dependencies] -std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/src/main.sw deleted file mode 100644 index 4887b8d8074..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/src/main.sw +++ /dev/null @@ -1,70 +0,0 @@ -contract; - -use std::option::*; -use std::result::*; -use std::storage::{StorageVec, StorageVecError}; - -abi MyContract { - #[storage(read, write)] - fn vec_u16_push(value: u16); - #[storage(read)] - fn vec_u16_get(index: u64) -> Option; - #[storage(read, write)] - fn vec_u16_pop() -> Option; - #[storage(read, write)] - fn vec_u16_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u16_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u16_insert(index: u64, value: u16) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_u16_len() -> u64; - #[storage(read)] - fn vec_u16_is_empty() -> bool; - #[storage(write)] - fn vec_u16_clear(); -} - -storage { - vec_u16: StorageVec, -} - -impl MyContract for Contract { - #[storage(read, write)] - fn vec_u16_push(value: u16) { - storage.vec_u16.push(value); - } - #[storage(read)] - fn vec_u16_get(index: u64) -> Option { - storage.vec_u16.get(index) - } - #[storage(read, write)] - fn vec_u16_pop() -> Option { - storage.vec_u16.pop() - } - #[storage(read, write)] - fn vec_u16_remove(index: u64) -> Result { - let res: Result = storage.vec_u16.remove(index); - res - } - #[storage(read, write)] - fn vec_u16_swap_remove(index: u64) -> Result { - storage.vec_u16.swap_remove(index) - } - #[storage(read, write)] - fn vec_u16_insert(index: u64, value: u16) -> Result<(), StorageVecError> { - storage.vec_u16.insert(index, value) - } - #[storage(read)] - fn vec_u16_len() -> u64 { - storage.vec_u16.len() - } - #[storage(read)] - fn vec_u16_is_empty() -> bool { - storage.vec_u16.is_empty() - } - #[storage(write)] - fn vec_u16_clear() { - storage.vec_u16.clear(); - } -} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/tests/harness.rs deleted file mode 100644 index bfbe5744601..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/tests/harness.rs +++ /dev/null @@ -1,25 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -// Load abi from json -abigen!(MyContract, "out/debug/svec_u16-abi.json"); - -async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; - - let id = Contract::deploy("./out/debug/svec_u16.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/.gitignore deleted file mode 100644 index 77d3844f58c..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -out -target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Cargo.toml deleted file mode 100644 index b6455a6222b..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "svec_u32" -version = "0.1.0" -authors = ["Swaystar"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.toml deleted file mode 100644 index aab0b8e8a71..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -authors = ["Fuel Labs "] -entry = "main.sw" -license = "Apache-2.0" -name = "svec_u32" - -[dependencies] -std = { path = "../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/src/main.sw deleted file mode 100644 index b0286090309..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/src/main.sw +++ /dev/null @@ -1,70 +0,0 @@ -contract; - -use std::option::*; -use std::result::*; -use std::storage::{StorageVec, StorageVecError}; - -abi MyContract { - #[storage(read, write)] - fn vec_u32_push(value: u32); - #[storage(read)] - fn vec_u32_get(index: u64) -> Option; - #[storage(read, write)] - fn vec_u32_pop() -> Option; - #[storage(read, write)] - fn vec_u32_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u32_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u32_insert(index: u64, value: u32) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_u32_len() -> u64; - #[storage(read)] - fn vec_u32_is_empty() -> bool; - #[storage(write)] - fn vec_u32_clear(); -} - -storage { - vec_u32: StorageVec, -} - -impl MyContract for Contract { - #[storage(read, write)] - fn vec_u32_push(value: u32) { - storage.vec_u32.push(value); - } - #[storage(read)] - fn vec_u32_get(index: u64) -> Option { - storage.vec_u32.get(index) - } - #[storage(read, write)] - fn vec_u32_pop() -> Option { - storage.vec_u32.pop() - } - #[storage(read, write)] - fn vec_u32_remove(index: u64) -> Result { - let res: Result = storage.vec_u32.remove(index); - res - } - #[storage(read, write)] - fn vec_u32_swap_remove(index: u64) -> Result { - storage.vec_u32.swap_remove(index) - } - #[storage(read, write)] - fn vec_u32_insert(index: u64, value: u32) -> Result<(), StorageVecError> { - storage.vec_u32.insert(index, value) - } - #[storage(read)] - fn vec_u32_len() -> u64 { - storage.vec_u32.len() - } - #[storage(read)] - fn vec_u32_is_empty() -> bool { - storage.vec_u32.is_empty() - } - #[storage(write)] - fn vec_u32_clear() { - storage.vec_u32.clear(); - } -} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/tests/harness.rs deleted file mode 100644 index dfd8f65b436..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/tests/harness.rs +++ /dev/null @@ -1,25 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -// Load abi from json -abigen!(MyContract, "out/debug/svec_u32-abi.json"); - -async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; - - let id = Contract::deploy("./out/debug/svec_u32.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/.gitignore deleted file mode 100644 index 77d3844f58c..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -out -target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Cargo.toml deleted file mode 100644 index 5a766397604..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "svec_u64" -version = "0.1.0" -authors = ["Swaystar"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.toml deleted file mode 100644 index 98f0a7acdec..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -authors = ["Fuel Labs "] -entry = "main.sw" -license = "Apache-2.0" -name = "svec_u64" - -[dependencies] -std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/src/main.sw deleted file mode 100644 index f8599d19ab3..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/src/main.sw +++ /dev/null @@ -1,70 +0,0 @@ -contract; - -use std::option::*; -use std::result::*; -use std::storage::{StorageVec, StorageVecError}; - -abi MyContract { - #[storage(read, write)] - fn vec_u64_push(value: u64); - #[storage(read)] - fn vec_u64_get(index: u64) -> Option; - #[storage(read, write)] - fn vec_u64_pop() -> Option; - #[storage(read, write)] - fn vec_u64_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u64_swap_remove(index: u64) -> Result; - #[storage(read, write)] - fn vec_u64_insert(index: u64, value: u64) -> Result<(), StorageVecError>; - #[storage(read)] - fn vec_u64_len() -> u64; - #[storage(read)] - fn vec_u64_is_empty() -> bool; - #[storage(write)] - fn vec_u64_clear(); -} - -storage { - vec_u64: StorageVec, -} - -impl MyContract for Contract { - #[storage(read, write)] - fn vec_u64_push(value: u64) { - storage.vec_u64.push(value); - } - #[storage(read)] - fn vec_u64_get(index: u64) -> Option { - storage.vec_u64.get(index) - } - #[storage(read, write)] - fn vec_u64_pop() -> Option { - storage.vec_u64.pop() - } - #[storage(read, write)] - fn vec_u64_remove(index: u64) -> Result { - let res: Result = storage.vec_u64.remove(index); - res - } - #[storage(read, write)] - fn vec_u64_swap_remove(index: u64) -> Result { - storage.vec_u64.swap_remove(index) - } - #[storage(read, write)] - fn vec_u64_insert(index: u64, value: u64) -> Result<(), StorageVecError> { - storage.vec_u64.insert(index, value) - } - #[storage(read)] - fn vec_u64_len() -> u64 { - storage.vec_u64.len() - } - #[storage(read)] - fn vec_u64_is_empty() -> bool { - storage.vec_u64.is_empty() - } - #[storage(write)] - fn vec_u64_clear() { - storage.vec_u64.clear(); - } -} \ No newline at end of file diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/tests/harness.rs deleted file mode 100644 index a7ca02b48f0..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/tests/harness.rs +++ /dev/null @@ -1,25 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -// Load abi from json -abigen!(MyContract, "out/debug/svec_u64-abi.json"); - -async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; - - let id = Contract::deploy("./out/debug/svec_u64.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} From ed766267de71f01363b29dbeea3e9ba4a9406200 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 30 Jun 2022 21:29:44 +0530 Subject: [PATCH 28/59] fixed bug in pop --- sway-lib-std/src/storage.sw | 6 +-- .../test_projects/storage_vec/mod.rs | 42 +++++++++++----- .../test_projects/storage_vec/utils/mod.rs | 48 +++++++++++++------ 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index ccea723db73..302f4ce6511 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -145,7 +145,7 @@ impl StorageVec { // reduces len by 1, effectively removing the last item in the vec store(__get_storage_key(), len - 1); - let key = sha256((len, __get_storage_key())); + let key = sha256((len - 1, __get_storage_key())); Option::Some::(get::(key)) } @@ -192,7 +192,7 @@ impl StorageVec { store(__get_storage_key(), len - 1); // returns the removed element - Result::Ok(removed_element) + Result::Ok::(removed_element) } /// Removes the element at the specified index and fills it with the last element @@ -219,7 +219,7 @@ impl StorageVec { // decrements len by 1 store(__get_storage_key(), len - 1); - Result::Ok(element_to_be_removed) + Result::Ok::(element_to_be_removed) } /// Inserts the value at the given index, moving the current index's value aswell as the following's diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index 9c289c8a605..d7b801bd4d8 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -1,20 +1,36 @@ mod utils; -use utils::*; +use utils::{ + setup::get_contract_instance, + wrappers::*, +}; -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - // Now you have an instance of your contract you can use to test each function -} +mod success { + use super::*; -#[tokio::test] -async fn can_push() { - let (instance, _id) = get_contract_instance().await; + #[tokio::test] + async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + } - push(&instance, 50).await; - let item = get(&instance, 0).await; - - assert_eq!(item, 50); + #[tokio::test] + async fn can_push() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + let item = get(&instance, 0).await; + + assert_eq!(item, 50); + } + + #[tokio::test] + async fn can_pop() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + let item = pop(&instance).await; + + assert_eq!(item, 50); + } } \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs index 57851d9813d..9737394a543 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs @@ -2,23 +2,41 @@ use fuels::{prelude::*, tx::ContractId}; // Load abi from json abigen!(MyContract, "test_artifacts/storage_vec/svec_u8/out/debug/svec_u8-abi.json"); -pub async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; - let id = Contract::deploy("test_artifacts/storage_vec/svec_u8/out/debug/svec_u8.bin", &wallet, TxParameters::default()) - .await - .unwrap(); +pub mod setup { + use super::*; - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) + pub async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("test_artifacts/storage_vec/svec_u8/out/debug/svec_u8.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) + } + } -pub async fn push(instance: &MyContract, value: u8) { - instance.vec_u8_push(value).call().await.unwrap(); -} +pub mod wrappers { + use super::*; + + pub async fn push(instance: &MyContract, value: u8) { + instance.vec_u8_push(value).call().await.unwrap(); + } + + pub async fn get(instance: &MyContract, index: u64) -> u8 { + instance.vec_u8_get(index).call().await.unwrap().value + } -pub async fn get(instance: &MyContract, index: u64) -> u8 { - instance.vec_u8_get(index).call().await.unwrap().value -} \ No newline at end of file + pub async fn pop(instance: &MyContract) -> u8 { + instance.vec_u8_pop().call().await.unwrap().value + } + + pub async fn remove(instance: &MyContract, index: u64) -> u8 { + instance.vec_u8_remove(index).call().await.unwrap().value + } +} From f90d3042ecfde6acf3fecb57b35762bb0a64c78d Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 30 Jun 2022 22:38:35 +0530 Subject: [PATCH 29/59] failing test for some reason --- .../test_projects/storage_vec/mod.rs | 28 +++++++++++++++++++ .../test_projects/storage_vec/utils/mod.rs | 4 +++ 2 files changed, 32 insertions(+) diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index d7b801bd4d8..13f7b613513 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -33,4 +33,32 @@ mod success { assert_eq!(item, 50); } + + #[tokio::test] + async fn can_remove() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + let item = remove(&instance, 2).await; + + assert_eq!(item, 150); + } + + #[tokio::test] + async fn can_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + let item = swap_remove(&instance, 1).await; + let new_item_at_index = get(&instance, 1).await; + + // assert_eq!(item, 100); + assert_eq!(new_item_at_index, 200); + } } \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs index 9737394a543..9d805c6e747 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs @@ -39,4 +39,8 @@ pub mod wrappers { pub async fn remove(instance: &MyContract, index: u64) -> u8 { instance.vec_u8_remove(index).call().await.unwrap().value } + + pub async fn swap_remove(instance: &MyContract, index: u64) -> u8 { + instance.vec_u8_swap_remove(index).call().await.unwrap().value + } } From b192910804a6bfd1122e90e6b2bef2a10599b5d5 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 30 Jun 2022 22:39:05 +0530 Subject: [PATCH 30/59] . --- test/src/sdk-harness/test_projects/storage_vec/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index 13f7b613513..bab781d510b 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -58,7 +58,7 @@ mod success { let item = swap_remove(&instance, 1).await; let new_item_at_index = get(&instance, 1).await; - // assert_eq!(item, 100); + assert_eq!(item, 100); assert_eq!(new_item_at_index, 200); } } \ No newline at end of file From 3293293d6d94844bb4ae05303b4228396f28c82a Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 30 Jun 2022 22:59:55 +0530 Subject: [PATCH 31/59] fixed some brackets --- sway-lib-std/src/storage.sw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index 302f4ce6511..c8c5c4ed98c 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -213,8 +213,8 @@ impl StorageVec { // gets the element before removing it, so it can be returned let element_to_be_removed = get::(sha256((index, __get_storage_key()))); - let last_element = get::(sha256(len - 1, __get_storage_key())); - store::(sha256(index, __get_storage_key()), last_element); + let last_element = get::(sha256((len - 1, __get_storage_key()))); + store::(sha256((index, __get_storage_key())), last_element); // decrements len by 1 store(__get_storage_key(), len - 1); From 7f233199b4fb5042863702e41b7348884d8bf472 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sat, 2 Jul 2022 14:15:43 +0530 Subject: [PATCH 32/59] fixed a mistake of > where it should be >= --- sway-lib-std/src/storage.sw | 4 ++-- .../test_projects/storage_vec/mod.rs | 19 +++++++++++++++++++ .../test_projects/storage_vec/utils/mod.rs | 4 ++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index c8c5c4ed98c..506a107b2f6 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -236,8 +236,8 @@ impl StorageVec { // for every element in the vec with an index larger than the input index, // move the element up one index. // performed in reverse to prevent data overwriting - let mut count = len; - while count > index { + let mut count = len-1; + while count >= index { let key = sha256((count + 1, __get_storage_key())); // shifts all the values up one index store::(key, get::(sha256((count, __get_storage_key())))); diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index bab781d510b..115bd3ba6c9 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -61,4 +61,23 @@ mod success { assert_eq!(item, 100); assert_eq!(new_item_at_index, 200); } + + #[tokio::test] + async fn can_insert() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + insert(&instance, 1, 250).await; + + let new_item_at_index = get(&instance, 1).await; + + assert_eq!(new_item_at_index, 250); + assert_eq!(100, get(&instance, 2).await); + assert_eq!(150, get(&instance, 3).await); + assert_eq!(200, get(&instance, 4).await); + } } \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs index 9d805c6e747..2400473f1e7 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs @@ -43,4 +43,8 @@ pub mod wrappers { pub async fn swap_remove(instance: &MyContract, index: u64) -> u8 { instance.vec_u8_swap_remove(index).call().await.unwrap().value } + + pub async fn insert(instance: &MyContract, index: u64, value: u8) { + instance.vec_u8_insert(index, value).call().await.unwrap(); + } } From 0ad4143eb07a26cd3e4f9ef6cf9993c231435d01 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sat, 2 Jul 2022 14:27:41 +0530 Subject: [PATCH 33/59] added 2 remaining tests --- .../test_projects/storage_vec/mod.rs | 39 +++++++++++++++++++ .../test_projects/storage_vec/utils/mod.rs | 12 ++++++ 2 files changed, 51 insertions(+) diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index 115bd3ba6c9..7913af3a849 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -80,4 +80,43 @@ mod success { assert_eq!(150, get(&instance, 3).await); assert_eq!(200, get(&instance, 4).await); } + + #[tokio::test] + async fn can_get_len() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 4); + + push(&instance, 200).await; + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_confirm_emptiness() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let isempty = is_empty(&instance).await; + + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + + assert_eq!(isempty, true); + } } \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs index 2400473f1e7..a76ae1c22c4 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs @@ -47,4 +47,16 @@ pub mod wrappers { pub async fn insert(instance: &MyContract, index: u64, value: u8) { instance.vec_u8_insert(index, value).call().await.unwrap(); } + + pub async fn len(instance: &MyContract) -> u64 { + instance.vec_u8_len().call().await.unwrap().value + } + + pub async fn is_empty(instance: &MyContract) -> bool { + instance.vec_u8_is_empty().call().await.unwrap().value + } + + pub async fn clear(instance: &MyContract) { + instance.vec_u8_clear().call().await.unwrap(); + } } From 1c3248985508c01f3f458a93b437d4dead271e20 Mon Sep 17 00:00:00 2001 From: SwayStar123 <46050679+SwayStar123@users.noreply.github.com> Date: Mon, 4 Jul 2022 20:25:32 +0530 Subject: [PATCH 34/59] Update test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml Co-authored-by: Braqzen <103777923+Braqzen@users.noreply.github.com> --- .../sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml index ca4036b0d86..0e7e712aa61 100644 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml @@ -1,7 +1,7 @@ [project] name = "svec_u8" version = "0.1.0" -authors = ["Swaystar"] +authors = ["Fuel Labs "] edition = "2021" license = "Apache-2.0" From 9dc6a5ca052e35408aa784fbd45d1f6f5fbd357c Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Mon, 4 Jul 2022 20:39:56 +0530 Subject: [PATCH 35/59] removed storagevecerrors --- sway-lib-std/src/storage.sw | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index 506a107b2f6..c17569143bf 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -1,5 +1,6 @@ library r#storage; +use ::assert::assert; use ::hash::sha256; use ::option::Option; use ::result::Result; @@ -109,12 +110,6 @@ impl StorageMap { } } - -pub enum StorageVecError { - IndexOutOfBounds: (), - CannotSwapAndRemoveTheSameElement: (), -} - /// A persistant vector struct pub struct StorageVec {} @@ -166,12 +161,10 @@ impl StorageVec { /// Down one index /// WARNING: Expensive for larger vecs #[storage(read, write)] - pub fn remove(self, index: u64) -> Result { + pub fn remove(self, index: u64) -> V { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no item to remove - if len <= index { - return Result::Err(StorageVecError::IndexOutOfBounds); - } + assert(len <= index); // gets the element before removing it, so it can be returned let removed_element = get::(sha256((index, __get_storage_key()))); @@ -191,24 +184,16 @@ impl StorageVec { // decrements len by 1 store(__get_storage_key(), len - 1); - // returns the removed element - Result::Ok::(removed_element) + removed_element } /// Removes the element at the specified index and fills it with the last element /// Does not preserve ordering #[storage(read, write)] - pub fn swap_remove(self, index: u64) -> Result { + pub fn swap_remove(self, index: u64) -> V { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no item to remove - if len <= index { - return Result::Err(StorageVecError::IndexOutOfBounds); - } - - // if the index is the last one, the function should not try to remove and then swap the same element - if index == len - 1 { - return Result::Err(StorageVecError::CannotSwapAndRemoveTheSameElement); - } + assert(len <= index); // gets the element before removing it, so it can be returned let element_to_be_removed = get::(sha256((index, __get_storage_key()))); @@ -219,19 +204,17 @@ impl StorageVec { // decrements len by 1 store(__get_storage_key(), len - 1); - Result::Ok::(element_to_be_removed) + element_to_be_removed } /// Inserts the value at the given index, moving the current index's value aswell as the following's /// Up one index /// WARNING: Expensive for larger vecs #[storage(read, write)] - pub fn insert(self, index: u64, value: V) -> Result<(), StorageVecError> { + pub fn insert(self, index: u64, value: V) { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no space to insert - if index >= len { - return Result::Err(StorageVecError::IndexOutOfBounds); - } + assert(index >= len); // for every element in the vec with an index larger than the input index, // move the element up one index. @@ -251,7 +234,6 @@ impl StorageVec { // increments len by 1 store(__get_storage_key(), len + 1); - Result::Ok(()) } /// Returns the length of the vector From a106f1c67a0d50e1e0b815c56c8901d7c0ca296c Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Mon, 4 Jul 2022 21:14:44 +0530 Subject: [PATCH 36/59] assert was the other way round --- sway-lib-std/src/storage.sw | 6 ++--- sway-lib-std/src/vec.sw | 2 -- .../storage_vec/svec_u8/Cargo.toml | 16 ------------ .../storage_vec/svec_u8/Forc.toml | 2 +- .../storage_vec/svec_u8/src/main.sw | 13 ++++------ .../storage_vec/svec_u8/tests/harness.rs | 25 ------------------- 6 files changed, 9 insertions(+), 55 deletions(-) delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml delete mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/tests/harness.rs diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index c17569143bf..418c1d3d32e 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -164,7 +164,7 @@ impl StorageVec { pub fn remove(self, index: u64) -> V { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no item to remove - assert(len <= index); + assert(index <= len); // gets the element before removing it, so it can be returned let removed_element = get::(sha256((index, __get_storage_key()))); @@ -193,7 +193,7 @@ impl StorageVec { pub fn swap_remove(self, index: u64) -> V { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no item to remove - assert(len <= index); + assert(index <= len); // gets the element before removing it, so it can be returned let element_to_be_removed = get::(sha256((index, __get_storage_key()))); @@ -214,7 +214,7 @@ impl StorageVec { pub fn insert(self, index: u64, value: V) { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no space to insert - assert(index >= len); + assert(index <= len); // for every element in the vec with an index larger than the input index, // move the element up one index. diff --git a/sway-lib-std/src/vec.sw b/sway-lib-std/src/vec.sw index dbb4105dccf..1655e4b4cc9 100644 --- a/sway-lib-std/src/vec.sw +++ b/sway-lib-std/src/vec.sw @@ -2,11 +2,9 @@ library vec; use ::alloc::{alloc, realloc}; use ::intrinsics::size_of; -use ::hash::sha256; use ::mem::{read, write}; use ::option::Option; - struct RawVec { ptr: u64, cap: u64, diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml deleted file mode 100644 index 0e7e712aa61..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "svec_u8" -version = "0.1.0" -authors = ["Fuel Labs "] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Forc.toml index 8d753bb89ef..66a399e3211 100644 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Forc.toml +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/Forc.toml @@ -5,4 +5,4 @@ license = "Apache-2.0" name = "svec_u8" [dependencies] -std = { path = "../../../../../../sway-lib-std" } \ No newline at end of file +std = { path = "../../../../../../sway-lib-std" } diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw index abc964e7d93..5eb5a970aa6 100644 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw @@ -2,7 +2,7 @@ contract; use std::option::*; use std::result::*; -use std::storage::{StorageVec, StorageVecError}; +use std::storage::StorageVec; abi MyContract { #[storage(read, write)] @@ -36,8 +36,7 @@ impl MyContract for Contract { } #[storage(read)] fn vec_u8_get(index: u64) -> u8 { - let item: Option = storage.vec_u8.get(index); - item.unwrap() + storage.vec_u8.get(index).unwrap() } #[storage(read, write)] fn vec_u8_pop() -> u8 { @@ -46,17 +45,15 @@ impl MyContract for Contract { } #[storage(read, write)] fn vec_u8_remove(index: u64) -> u8 { - let res: Result = storage.vec_u8.remove(index); - res.unwrap() + storage.vec_u8.remove(index) } #[storage(read, write)] fn vec_u8_swap_remove(index: u64) -> u8 { - let res: Result = storage.vec_u8.swap_remove(index); - res.unwrap() + storage.vec_u8.swap_remove(index) } #[storage(read, write)] fn vec_u8_insert(index: u64, value: u8) { - let _ = storage.vec_u8.insert(index, value); + storage.vec_u8.insert(index, value); } #[storage(read)] fn vec_u8_len() -> u64 { diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/tests/harness.rs b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/tests/harness.rs deleted file mode 100644 index 46a7bfc613b..00000000000 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/tests/harness.rs +++ /dev/null @@ -1,25 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -// Load abi from json -abigen!(MyContract, "out/debug/svec_u8-abi.json"); - -async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; - - let id = Contract::deploy("./out/debug/svec_u8.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} From f5b78c8352d9f48e19990edac0f798331962364b Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Mon, 4 Jul 2022 21:22:30 +0530 Subject: [PATCH 37/59] added a variable for repeated code --- sway-lib-std/src/storage.sw | 5 +++-- test/src/sdk-harness/test_projects/storage_vec/mod.rs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index 418c1d3d32e..90518941226 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -195,11 +195,12 @@ impl StorageVec { // if the index is larger or equal to len, there is no item to remove assert(index <= len); + let hash_of_to_be_removed = sha256((index, __get_storage_key())); // gets the element before removing it, so it can be returned - let element_to_be_removed = get::(sha256((index, __get_storage_key()))); + let element_to_be_removed = get::(hash_of_to_be_removed); let last_element = get::(sha256((len - 1, __get_storage_key()))); - store::(sha256((index, __get_storage_key())), last_element); + store::(hash_of_to_be_removed, last_element); // decrements len by 1 store(__get_storage_key(), len - 1); diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index 7913af3a849..866c4b874aa 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -119,4 +119,4 @@ mod success { assert_eq!(isempty, true); } -} \ No newline at end of file +} From d242c9c8c6331941a5a481db5a2a15ff225845c5 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Mon, 4 Jul 2022 21:22:51 +0530 Subject: [PATCH 38/59] merged use --- .../test_artifacts/storage_vec/svec_u8/src/main.sw | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw index 5eb5a970aa6..270f28ca8bd 100644 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw @@ -1,8 +1,6 @@ contract; -use std::option::*; -use std::result::*; -use std::storage::StorageVec; +use std::{option::Option, result::Result, storage::StorageVec}; abi MyContract { #[storage(read, write)] From c9ce95fcc778009b614d3cf6f87ac78fbbaa2285 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Mon, 4 Jul 2022 21:34:06 +0530 Subject: [PATCH 39/59] formatting --- .../storage_vec/svec_u8/src/main.sw | 56 +++++++++---------- .../test_projects/storage_vec/mod.rs | 45 ++++++++------- .../test_projects/storage_vec/utils/mod.rs | 48 +++++++++------- 3 files changed, 79 insertions(+), 70 deletions(-) diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw index 270f28ca8bd..ba83c4369b4 100644 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw @@ -4,65 +4,65 @@ use std::{option::Option, result::Result, storage::StorageVec}; abi MyContract { #[storage(read, write)] - fn vec_u8_push(value: u8); + fn u8_push(value: u8); #[storage(read)] - fn vec_u8_get(index: u64) -> u8; + fn u8_get(index: u64) -> u8; #[storage(read, write)] - fn vec_u8_pop() -> u8; + fn u8_pop() -> u8; #[storage(read, write)] - fn vec_u8_remove(index: u64) -> u8; + fn u8_remove(index: u64) -> u8; #[storage(read, write)] - fn vec_u8_swap_remove(index: u64) -> u8; + fn u8_swap_remove(index: u64) -> u8; #[storage(read, write)] - fn vec_u8_insert(index: u64, value: u8); + fn u8_insert(index: u64, value: u8); #[storage(read)] - fn vec_u8_len() -> u64; + fn u8_len() -> u64; #[storage(read)] - fn vec_u8_is_empty() -> bool; + fn u8_is_empty() -> bool; #[storage(write)] - fn vec_u8_clear(); + fn u8_clear(); } storage { - vec_u8: StorageVec, + my_vec: StorageVec, } impl MyContract for Contract { #[storage(read, write)] - fn vec_u8_push(value: u8) { - storage.vec_u8.push(value); + fn u8_push(value: u8) { + storage.my_vec.push(value); } #[storage(read)] - fn vec_u8_get(index: u64) -> u8 { - storage.vec_u8.get(index).unwrap() + fn u8_get(index: u64) -> u8 { + storage.my_vec.get(index).unwrap() } #[storage(read, write)] - fn vec_u8_pop() -> u8 { - let res: Option = storage.vec_u8.pop(); + fn u8_pop() -> u8 { + let res: Option = storage.my_vec.pop(); res.unwrap() } #[storage(read, write)] - fn vec_u8_remove(index: u64) -> u8 { - storage.vec_u8.remove(index) + fn u8_remove(index: u64) -> u8 { + storage.my_vec.remove(index) } #[storage(read, write)] - fn vec_u8_swap_remove(index: u64) -> u8 { - storage.vec_u8.swap_remove(index) + fn u8_swap_remove(index: u64) -> u8 { + storage.my_vec.swap_remove(index) } #[storage(read, write)] - fn vec_u8_insert(index: u64, value: u8) { - storage.vec_u8.insert(index, value); + fn u8_insert(index: u64, value: u8) { + storage.my_vec.insert(index, value); } #[storage(read)] - fn vec_u8_len() -> u64 { - storage.vec_u8.len() + fn u8_len() -> u64 { + storage.my_vec.len() } #[storage(read)] - fn vec_u8_is_empty() -> bool { - storage.vec_u8.is_empty() + fn u8_is_empty() -> bool { + storage.my_vec.is_empty() } #[storage(write)] - fn vec_u8_clear() { - storage.vec_u8.clear(); + fn u8_clear() { + storage.my_vec.clear(); } } diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index 866c4b874aa..cd1507d8894 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -2,70 +2,69 @@ mod utils; use utils::{ setup::get_contract_instance, - wrappers::*, + wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, }; - mod success { use super::*; #[tokio::test] - async fn can_get_contract_id() { + async fn can_get_contract_id() { let (_instance, _id) = get_contract_instance().await; } #[tokio::test] - async fn can_push() { + async fn can_push() { let (instance, _id) = get_contract_instance().await; - + push(&instance, 50).await; let item = get(&instance, 0).await; - + assert_eq!(item, 50); } - + #[tokio::test] - async fn can_pop() { + async fn can_pop() { let (instance, _id) = get_contract_instance().await; - + push(&instance, 50).await; let item = pop(&instance).await; - + assert_eq!(item, 50); } #[tokio::test] - async fn can_remove() { + async fn can_remove() { let (instance, _id) = get_contract_instance().await; - + push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; push(&instance, 200).await; let item = remove(&instance, 2).await; - + assert_eq!(item, 150); } #[tokio::test] - async fn can_swap_remove() { + async fn can_swap_remove() { let (instance, _id) = get_contract_instance().await; - + push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; push(&instance, 200).await; let item = swap_remove(&instance, 1).await; let new_item_at_index = get(&instance, 1).await; - + assert_eq!(item, 100); assert_eq!(new_item_at_index, 200); } #[tokio::test] - async fn can_insert() { + async fn can_insert() { let (instance, _id) = get_contract_instance().await; - + push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; @@ -74,7 +73,7 @@ mod success { insert(&instance, 1, 250).await; let new_item_at_index = get(&instance, 1).await; - + assert_eq!(new_item_at_index, 250); assert_eq!(100, get(&instance, 2).await); assert_eq!(150, get(&instance, 3).await); @@ -82,9 +81,9 @@ mod success { } #[tokio::test] - async fn can_get_len() { + async fn can_get_len() { let (instance, _id) = get_contract_instance().await; - + push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; @@ -101,9 +100,9 @@ mod success { } #[tokio::test] - async fn can_confirm_emptiness() { + async fn can_confirm_emptiness() { let (instance, _id) = get_contract_instance().await; - + push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; diff --git a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs index a76ae1c22c4..db1a0582513 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs @@ -1,7 +1,9 @@ use fuels::{prelude::*, tx::ContractId}; // Load abi from json -abigen!(MyContract, "test_artifacts/storage_vec/svec_u8/out/debug/svec_u8-abi.json"); - +abigen!( + MyContract, + "test_artifacts/storage_vec/svec_u8/out/debug/svec_u8-abi.json" +); pub mod setup { use super::*; @@ -9,54 +11,62 @@ pub mod setup { pub async fn get_contract_instance() -> (MyContract, ContractId) { // Launch a local network and deploy the contract let wallet = launch_provider_and_get_single_wallet().await; - - let id = Contract::deploy("test_artifacts/storage_vec/svec_u8/out/debug/svec_u8.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - + + let id = Contract::deploy( + "test_artifacts/storage_vec/svec_u8/out/debug/svec_u8.bin", + &wallet, + TxParameters::default(), + ) + .await + .unwrap(); + let instance = MyContract::new(id.to_string(), wallet); - + (instance, id) } - } pub mod wrappers { use super::*; pub async fn push(instance: &MyContract, value: u8) { - instance.vec_u8_push(value).call().await.unwrap(); + instance.u8_push(value).call().await.unwrap(); } - + pub async fn get(instance: &MyContract, index: u64) -> u8 { - instance.vec_u8_get(index).call().await.unwrap().value + instance.u8_get(index).call().await.unwrap().value } pub async fn pop(instance: &MyContract) -> u8 { - instance.vec_u8_pop().call().await.unwrap().value + instance.u8_pop().call().await.unwrap().value } pub async fn remove(instance: &MyContract, index: u64) -> u8 { - instance.vec_u8_remove(index).call().await.unwrap().value + instance.u8_remove(index).call().await.unwrap().value } pub async fn swap_remove(instance: &MyContract, index: u64) -> u8 { - instance.vec_u8_swap_remove(index).call().await.unwrap().value + instance + .u8_swap_remove(index) + .call() + .await + .unwrap() + .value } pub async fn insert(instance: &MyContract, index: u64, value: u8) { - instance.vec_u8_insert(index, value).call().await.unwrap(); + instance.u8_insert(index, value).call().await.unwrap(); } pub async fn len(instance: &MyContract) -> u64 { - instance.vec_u8_len().call().await.unwrap().value + instance.u8_len().call().await.unwrap().value } pub async fn is_empty(instance: &MyContract) -> bool { - instance.vec_u8_is_empty().call().await.unwrap().value + instance.u8_is_empty().call().await.unwrap().value } pub async fn clear(instance: &MyContract) { - instance.vec_u8_clear().call().await.unwrap(); + instance.u8_clear().call().await.unwrap(); } } From 578d9e36b49cb52a6d291ae41b142a18d50ce0f3 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 6 Jul 2022 19:17:11 +0530 Subject: [PATCH 40/59] expanded the testing --- .../test_projects/storage_vec/mod.rs | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index cd1507d8894..c352884bc90 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -84,6 +84,10 @@ mod success { async fn can_get_len() { let (instance, _id) = get_contract_instance().await; + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 0); + push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; @@ -99,23 +103,61 @@ mod success { assert_eq!(len_vec, 5); } + // Doubles as a test for is_empty #[tokio::test] async fn can_confirm_emptiness() { let (instance, _id) = get_contract_instance().await; + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; push(&instance, 200).await; let isempty = is_empty(&instance).await; - assert_eq!(isempty, false); clear(&instance).await; let isempty = is_empty(&instance).await; - assert_eq!(isempty, true); } } + +mod failure { + use super::*; + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_pop() { + let (instance, _id) = get_contract_instance().await; + + pop(&instance).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = remove(&instance, 2).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = swap_remove(&instance, 2).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_insert() { + let (instance, _id) = get_contract_instance().await; + + insert(&instance, 1, 250).await; + } +} \ No newline at end of file From 27979d89a924e4a0251112c33fa3031ef3e748c1 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 6 Jul 2022 19:34:05 +0530 Subject: [PATCH 41/59] rearranged file structure --- .../test_projects/storage_vec/mod.rs | 164 +----------------- .../test_projects/storage_vec/u8/mod.rs | 163 +++++++++++++++++ .../storage_vec/{utils/mod.rs => u8/utils.rs} | 0 3 files changed, 164 insertions(+), 163 deletions(-) create mode 100644 test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs rename test/src/sdk-harness/test_projects/storage_vec/{utils/mod.rs => u8/utils.rs} (100%) diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index c352884bc90..03f3caae2d8 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -1,163 +1 @@ -mod utils; - -use utils::{ - setup::get_contract_instance, - wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, -}; - -mod success { - use super::*; - - #[tokio::test] - async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - } - - #[tokio::test] - async fn can_push() { - let (instance, _id) = get_contract_instance().await; - - push(&instance, 50).await; - let item = get(&instance, 0).await; - - assert_eq!(item, 50); - } - - #[tokio::test] - async fn can_pop() { - let (instance, _id) = get_contract_instance().await; - - push(&instance, 50).await; - let item = pop(&instance).await; - - assert_eq!(item, 50); - } - - #[tokio::test] - async fn can_remove() { - let (instance, _id) = get_contract_instance().await; - - push(&instance, 50).await; - push(&instance, 100).await; - push(&instance, 150).await; - push(&instance, 200).await; - let item = remove(&instance, 2).await; - - assert_eq!(item, 150); - } - - #[tokio::test] - async fn can_swap_remove() { - let (instance, _id) = get_contract_instance().await; - - push(&instance, 50).await; - push(&instance, 100).await; - push(&instance, 150).await; - push(&instance, 200).await; - let item = swap_remove(&instance, 1).await; - let new_item_at_index = get(&instance, 1).await; - - assert_eq!(item, 100); - assert_eq!(new_item_at_index, 200); - } - - #[tokio::test] - async fn can_insert() { - let (instance, _id) = get_contract_instance().await; - - push(&instance, 50).await; - push(&instance, 100).await; - push(&instance, 150).await; - push(&instance, 200).await; - - insert(&instance, 1, 250).await; - - let new_item_at_index = get(&instance, 1).await; - - assert_eq!(new_item_at_index, 250); - assert_eq!(100, get(&instance, 2).await); - assert_eq!(150, get(&instance, 3).await); - assert_eq!(200, get(&instance, 4).await); - } - - #[tokio::test] - async fn can_get_len() { - let (instance, _id) = get_contract_instance().await; - - let len_vec = len(&instance).await; - - assert_eq!(len_vec, 0); - - push(&instance, 50).await; - push(&instance, 100).await; - push(&instance, 150).await; - push(&instance, 200).await; - - let len_vec = len(&instance).await; - - assert_eq!(len_vec, 4); - - push(&instance, 200).await; - let len_vec = len(&instance).await; - - assert_eq!(len_vec, 5); - } - - // Doubles as a test for is_empty - #[tokio::test] - async fn can_confirm_emptiness() { - let (instance, _id) = get_contract_instance().await; - - let isempty = is_empty(&instance).await; - assert_eq!(isempty, true); - - push(&instance, 50).await; - push(&instance, 100).await; - push(&instance, 150).await; - push(&instance, 200).await; - - let isempty = is_empty(&instance).await; - assert_eq!(isempty, false); - - clear(&instance).await; - - let isempty = is_empty(&instance).await; - assert_eq!(isempty, true); - } -} - -mod failure { - use super::*; - - #[tokio::test] - #[should_panic(expected = "Revert(0)")] - async fn cant_pop() { - let (instance, _id) = get_contract_instance().await; - - pop(&instance).await; - } - - #[tokio::test] - #[should_panic(expected = "Revert(0)")] - async fn cant_remove() { - let (instance, _id) = get_contract_instance().await; - - let _ = remove(&instance, 2).await; - } - - #[tokio::test] - #[should_panic(expected = "Revert(0)")] - async fn cant_swap_remove() { - let (instance, _id) = get_contract_instance().await; - - let _ = swap_remove(&instance, 2).await; - } - - #[tokio::test] - #[should_panic(expected = "Revert(0)")] - async fn cant_insert() { - let (instance, _id) = get_contract_instance().await; - - insert(&instance, 1, 250).await; - } -} \ No newline at end of file +mod u8; \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs new file mode 100644 index 00000000000..c352884bc90 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs @@ -0,0 +1,163 @@ +mod utils; + +use utils::{ + setup::get_contract_instance, + wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, +}; + +mod success { + use super::*; + + #[tokio::test] + async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + } + + #[tokio::test] + async fn can_push() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + let item = get(&instance, 0).await; + + assert_eq!(item, 50); + } + + #[tokio::test] + async fn can_pop() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + let item = pop(&instance).await; + + assert_eq!(item, 50); + } + + #[tokio::test] + async fn can_remove() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + let item = remove(&instance, 2).await; + + assert_eq!(item, 150); + } + + #[tokio::test] + async fn can_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + let item = swap_remove(&instance, 1).await; + let new_item_at_index = get(&instance, 1).await; + + assert_eq!(item, 100); + assert_eq!(new_item_at_index, 200); + } + + #[tokio::test] + async fn can_insert() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + insert(&instance, 1, 250).await; + + let new_item_at_index = get(&instance, 1).await; + + assert_eq!(new_item_at_index, 250); + assert_eq!(100, get(&instance, 2).await); + assert_eq!(150, get(&instance, 3).await); + assert_eq!(200, get(&instance, 4).await); + } + + #[tokio::test] + async fn can_get_len() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 4); + + push(&instance, 200).await; + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 5); + } + + // Doubles as a test for is_empty + #[tokio::test] + async fn can_confirm_emptiness() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } +} + +mod failure { + use super::*; + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_pop() { + let (instance, _id) = get_contract_instance().await; + + pop(&instance).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = remove(&instance, 2).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = swap_remove(&instance, 2).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_insert() { + let (instance, _id) = get_contract_instance().await; + + insert(&instance, 1, 250).await; + } +} \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs similarity index 100% rename from test/src/sdk-harness/test_projects/storage_vec/utils/mod.rs rename to test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs From d9f17e3ba071d3394b101bdeac92aab55f7cf743 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 6 Jul 2022 19:35:54 +0530 Subject: [PATCH 42/59] cargo fmt --- test/src/sdk-harness/test_projects/storage_vec/mod.rs | 2 +- test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs | 2 +- test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs | 7 +------ 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index 03f3caae2d8..b0bbf99eb32 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -1 +1 @@ -mod u8; \ No newline at end of file +mod u8; diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs index c352884bc90..685625f84ae 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs @@ -160,4 +160,4 @@ mod failure { insert(&instance, 1, 250).await; } -} \ No newline at end of file +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs index db1a0582513..4011b03a5a6 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs @@ -46,12 +46,7 @@ pub mod wrappers { } pub async fn swap_remove(instance: &MyContract, index: u64) -> u8 { - instance - .u8_swap_remove(index) - .call() - .await - .unwrap() - .value + instance.u8_swap_remove(index).call().await.unwrap().value } pub async fn insert(instance: &MyContract, index: u64, value: u8) { From f51da9fc8dd406646516bcbc1e5e5d7aca116e54 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 7 Jul 2022 21:03:56 +0530 Subject: [PATCH 43/59] adjusted assert for removes --- sway-lib-std/src/storage.sw | 6 +++--- test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index 90518941226..75fb901c46d 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -164,7 +164,7 @@ impl StorageVec { pub fn remove(self, index: u64) -> V { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no item to remove - assert(index <= len); + assert(index < len); // gets the element before removing it, so it can be returned let removed_element = get::(sha256((index, __get_storage_key()))); @@ -193,7 +193,7 @@ impl StorageVec { pub fn swap_remove(self, index: u64) -> V { let len = get::(__get_storage_key()); // if the index is larger or equal to len, there is no item to remove - assert(index <= len); + assert(index < len); let hash_of_to_be_removed = sha256((index, __get_storage_key())); // gets the element before removing it, so it can be returned @@ -214,7 +214,7 @@ impl StorageVec { #[storage(read, write)] pub fn insert(self, index: u64, value: V) { let len = get::(__get_storage_key()); - // if the index is larger or equal to len, there is no space to insert + // if the index is larger than len, there is no space to insert assert(index <= len); // for every element in the vec with an index larger than the input index, diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs index 685625f84ae..e0faac46a69 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs @@ -142,7 +142,7 @@ mod failure { async fn cant_remove() { let (instance, _id) = get_contract_instance().await; - let _ = remove(&instance, 2).await; + let _ = remove(&instance, 0).await; } #[tokio::test] @@ -150,7 +150,7 @@ mod failure { async fn cant_swap_remove() { let (instance, _id) = get_contract_instance().await; - let _ = swap_remove(&instance, 2).await; + let _ = swap_remove(&instance, 0).await; } #[tokio::test] From 57e4aef3b8f9c6b632a17377ab3cf4d069c2fe73 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 7 Jul 2022 21:06:31 +0530 Subject: [PATCH 44/59] removed non test and shortened the contract code --- .../test_artifacts/storage_vec/svec_u8/src/main.sw | 3 +-- test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs | 5 ----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw index ba83c4369b4..cd375ca1012 100644 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw @@ -38,8 +38,7 @@ impl MyContract for Contract { } #[storage(read, write)] fn u8_pop() -> u8 { - let res: Option = storage.my_vec.pop(); - res.unwrap() + storage.my_vec.pop().unwrap() } #[storage(read, write)] fn u8_remove(index: u64) -> u8 { diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs index e0faac46a69..cee5baf0385 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs @@ -8,11 +8,6 @@ use utils::{ mod success { use super::*; - #[tokio::test] - async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - } - #[tokio::test] async fn can_push() { let (instance, _id) = get_contract_instance().await; From 6e65c3971d14536189e26cbbe5f5be3cae2133fc Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 7 Jul 2022 21:09:35 +0530 Subject: [PATCH 45/59] added cant_get test --- .../sdk-harness/test_projects/storage_vec/u8/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs index cee5baf0385..c1808dc7571 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs @@ -121,9 +121,19 @@ mod success { } } +// Some of these are meant to be tests for None returns but since the SDK doesnt support options; +// the options are being unwrapped in the contract and tested as reverts instead mod failure { use super::*; + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_get() { + let (instance, _id) = get_contract_instance().await; + + get(&instance, 0).await; + } + #[tokio::test] #[should_panic(expected = "Revert(0)")] async fn cant_pop() { From 5796f402fee055dab99d29a3419af6b3e5f451dd Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Thu, 7 Jul 2022 21:18:28 +0530 Subject: [PATCH 46/59] added a todo --- test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs index c1808dc7571..32886b7c3bb 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs @@ -5,6 +5,9 @@ use utils::{ wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, }; +// TODO: Many of these tests have no preconditional assertions because options are not supported +// by the SDK + mod success { use super::*; @@ -98,7 +101,6 @@ mod success { assert_eq!(len_vec, 5); } - // Doubles as a test for is_empty #[tokio::test] async fn can_confirm_emptiness() { let (instance, _id) = get_contract_instance().await; From bcae640c97e16004e279e2908ec4dd6f9329c9e1 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sat, 9 Jul 2022 20:04:12 +0530 Subject: [PATCH 47/59] Improved documentation --- sway-lib-std/src/storage.sw | 53 ++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index 75fb901c46d..c1b0037e1ba 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -115,6 +115,10 @@ pub struct StorageVec {} impl StorageVec { /// Appends the value to the end of the vector + /// + /// # Arguments + /// + /// * `value` - The item being added to the end of the vector #[storage(read, write)] pub fn push(self, value: V) { // The length of the vec is stored in the __get_storage_key() slot @@ -128,7 +132,7 @@ impl StorageVec { store(__get_storage_key(), len + 1); } - /// Removes the last element of the vector + /// Removes the last element of the vector and returns it, None if empty #[storage(read, write)] pub fn pop(self) -> Option { let len = get::(__get_storage_key()); @@ -144,7 +148,11 @@ impl StorageVec { Option::Some::(get::(key)) } - /// Gets the value in the given index + /// Gets the value in the given index, None if index is out of bounds + /// + /// # Arguments + /// + /// * `index` - The index of the vec to retrieve the item from #[storage(read)] pub fn get(self, index: u64) -> Option { let len = get::(__get_storage_key()); @@ -157,9 +165,20 @@ impl StorageVec { Option::Some::(get::(key)) } - /// Removes the value in the given index and moves all the values in the following indexes - /// Down one index - /// WARNING: Expensive for larger vecs + /// Removes the element in the given index and moves all the element in the following indexes + /// Down one index. Also returns the element + /// + /// # WARNING + /// + /// Expensive for larger vecs + /// + /// # Arguments + /// + /// * `index` - The index of the vec to remove the item from + /// + /// # Reverts + /// + /// Reverts if index is larger or equal to length of the vec #[storage(read, write)] pub fn remove(self, index: u64) -> V { let len = get::(__get_storage_key()); @@ -188,7 +207,15 @@ impl StorageVec { } /// Removes the element at the specified index and fills it with the last element - /// Does not preserve ordering + /// Does not preserve ordering. Also returns the element + /// + /// # Arguments + /// + /// * `index` - The index of the vec to remove the item from + /// + /// # Reverts + /// + /// Reverts if index is larger or equal to length of the vec #[storage(read, write)] pub fn swap_remove(self, index: u64) -> V { let len = get::(__get_storage_key()); @@ -210,7 +237,19 @@ impl StorageVec { /// Inserts the value at the given index, moving the current index's value aswell as the following's /// Up one index - /// WARNING: Expensive for larger vecs + /// + /// # WARNING + /// + /// Expensive for larger vecs + /// + /// # Arguments + /// + /// * `index` - The index of the vec to insert the item into + /// * `value` - The value to insert into the vec + /// + /// # Reverts + /// + /// Reverts if index is larger than length of the vec #[storage(read, write)] pub fn insert(self, index: u64, value: V) { let len = get::(__get_storage_key()); From a6b6ab863dcae549f257f4ff2de80fa38a962e84 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sat, 9 Jul 2022 20:17:08 +0530 Subject: [PATCH 48/59] updated tests with preconditional tests --- .../test_projects/storage_vec/u8/mod.rs | 64 +++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs index 32886b7c3bb..f15726d54a8 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs @@ -5,20 +5,36 @@ use utils::{ wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, }; -// TODO: Many of these tests have no preconditional assertions because options are not supported -// by the SDK +// TODO: Replace many of the get calls with direct storage values +// once the SDK supports that mod success { use super::*; + #[tokio::test] + async fn can_get() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + let item = get(&instance, 0).await; + + assert_eq!(item, 50); + } + #[tokio::test] async fn can_push() { let (instance, _id) = get_contract_instance().await; + let len_before_push = len(&instance).await; + assert_eq!(len_before_push, 0); + push(&instance, 50).await; let item = get(&instance, 0).await; assert_eq!(item, 50); + + let len_after_push = len(&instance).await; + assert_eq!(len_after_push, 1); } #[tokio::test] @@ -26,9 +42,14 @@ mod success { let (instance, _id) = get_contract_instance().await; push(&instance, 50).await; - let item = pop(&instance).await; + let len_before_pop = len(&instance).await; + assert_eq!(len_before_pop, 1); + let item = pop(&instance).await; assert_eq!(item, 50); + + let len_after_pop = len(&instance).await; + assert_eq!(len_after_pop, 0); } #[tokio::test] @@ -39,9 +60,16 @@ mod success { push(&instance, 100).await; push(&instance, 150).await; push(&instance, 200).await; + + let old_item_at_index = get(&instance, 2).await; + assert_eq!(150, old_item_at_index); + let item = remove(&instance, 2).await; assert_eq!(item, 150); + + let new_item_at_index = get(&instance, 2).await; + assert_eq!(new_item_at_index, 200); } #[tokio::test] @@ -52,6 +80,10 @@ mod success { push(&instance, 100).await; push(&instance, 150).await; push(&instance, 200).await; + + let old_item_at_index = get(&instance, 1).await; + assert_eq!(old_item_at_index, 100); + let item = swap_remove(&instance, 1).await; let new_item_at_index = get(&instance, 1).await; @@ -68,11 +100,14 @@ mod success { push(&instance, 150).await; push(&instance, 200).await; + let old_item_at_index = get(&instance, 1).await; + assert_eq!(100, old_item_at_index); + insert(&instance, 1, 250).await; let new_item_at_index = get(&instance, 1).await; - assert_eq!(new_item_at_index, 250); + assert_eq!(100, get(&instance, 2).await); assert_eq!(150, get(&instance, 3).await); assert_eq!(200, get(&instance, 4).await); @@ -121,6 +156,27 @@ mod success { let isempty = is_empty(&instance).await; assert_eq!(isempty, true); } + + #[tokio::test] + async fn can_clear() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } } // Some of these are meant to be tests for None returns but since the SDK doesnt support options; From bfae2792c1a3fe19b31a2430829b634da42ca21b Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sat, 9 Jul 2022 20:24:01 +0530 Subject: [PATCH 49/59] added initializer --- .../sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw index cd375ca1012..27534066c37 100644 --- a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u8/src/main.sw @@ -24,7 +24,7 @@ abi MyContract { } storage { - my_vec: StorageVec, + my_vec: StorageVec = StorageVec {}, } impl MyContract for Contract { From 06805d882d7c6dc760fc86f9c5181839822c6a11 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sat, 9 Jul 2022 21:03:15 +0530 Subject: [PATCH 50/59] updated functions with sdk release --- test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs index 4011b03a5a6..41f4bcc1a06 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs @@ -10,12 +10,15 @@ pub mod setup { pub async fn get_contract_instance() -> (MyContract, ContractId) { // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; + let wallet = launch_provider_and_get_wallet().await; let id = Contract::deploy( "test_artifacts/storage_vec/svec_u8/out/debug/svec_u8.bin", &wallet, TxParameters::default(), + StorageConfiguration::with_storage_path(Some( + "test_artifacts/storage_vec/svec_u8/out/debug/svec_u8-storage_slots.json".to_string(), + )), ) .await .unwrap(); From 5adddc56856a6a46bb54fdf845bf1ef2c906585a Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sat, 9 Jul 2022 21:15:19 +0530 Subject: [PATCH 51/59] mdae build.sh more generic --- test/src/sdk-harness/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/sdk-harness/build.sh b/test/src/sdk-harness/build.sh index e9c7bb40de8..3c0e56365f6 100755 --- a/test/src/sdk-harness/build.sh +++ b/test/src/sdk-harness/build.sh @@ -27,7 +27,7 @@ while true; do fi done -test_dirs="${base_dir}/test_artifacts/* ${base_dir}/test_projects/* ${base_dir}/test_artifacts/storage_vec/*" +test_dirs="${base_dir}/test_artifacts/* ${base_dir}/test_projects/* ${base_dir}/test_artifacts/**" for test_dir in $test_dirs; do if [[ -f "${test_dir}/Forc.toml" ]]; then From a1b38432c0fae09b385b817cb3ea127622a135f4 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sat, 9 Jul 2022 21:47:32 +0530 Subject: [PATCH 52/59] fixed build script --- test/src/sdk-harness/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/sdk-harness/build.sh b/test/src/sdk-harness/build.sh index 3c0e56365f6..5b6acaecb1b 100755 --- a/test/src/sdk-harness/build.sh +++ b/test/src/sdk-harness/build.sh @@ -27,7 +27,7 @@ while true; do fi done -test_dirs="${base_dir}/test_artifacts/* ${base_dir}/test_projects/* ${base_dir}/test_artifacts/**" +test_dirs="${base_dir}/test_artifacts/*/* ${base_dir}/test_projects/*" for test_dir in $test_dirs; do if [[ -f "${test_dir}/Forc.toml" ]]; then From 4b527501f29ba5fa1c30d0a1f1e57f90ac116b3e Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Sat, 9 Jul 2022 21:56:22 +0530 Subject: [PATCH 53/59] fix 2 electric boogaloo --- test/src/sdk-harness/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/sdk-harness/build.sh b/test/src/sdk-harness/build.sh index 5b6acaecb1b..638675782bc 100755 --- a/test/src/sdk-harness/build.sh +++ b/test/src/sdk-harness/build.sh @@ -27,7 +27,7 @@ while true; do fi done -test_dirs="${base_dir}/test_artifacts/*/* ${base_dir}/test_projects/*" +test_dirs="${base_dir}/test_artifacts/* ${base_dir}/test_projects/* ${base_dir}/test_artifacts/*/*" for test_dir in $test_dirs; do if [[ -f "${test_dir}/Forc.toml" ]]; then From 3d62d03353bf61a0fbd97453fb323a0e4a36728a Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Mon, 11 Jul 2022 21:07:10 +0530 Subject: [PATCH 54/59] updated remove and insert tests --- .../test_projects/storage_vec/u8/mod.rs | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs index f15726d54a8..8f452e2b0b7 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs @@ -61,15 +61,17 @@ mod success { push(&instance, 150).await; push(&instance, 200).await; - let old_item_at_index = get(&instance, 2).await; - assert_eq!(150, old_item_at_index); + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + assert_eq!(200, get(&instance, 3).await); let item = remove(&instance, 2).await; - assert_eq!(item, 150); - let new_item_at_index = get(&instance, 2).await; - assert_eq!(new_item_at_index, 200); + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(200, get(&instance, 2).await); } #[tokio::test] @@ -81,14 +83,17 @@ mod success { push(&instance, 150).await; push(&instance, 200).await; - let old_item_at_index = get(&instance, 1).await; - assert_eq!(old_item_at_index, 100); + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + assert_eq!(200, get(&instance, 3).await); let item = swap_remove(&instance, 1).await; - let new_item_at_index = get(&instance, 1).await; - assert_eq!(item, 100); - assert_eq!(new_item_at_index, 200); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(200, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); } #[tokio::test] @@ -100,14 +105,15 @@ mod success { push(&instance, 150).await; push(&instance, 200).await; - let old_item_at_index = get(&instance, 1).await; - assert_eq!(100, old_item_at_index); + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + assert_eq!(200, get(&instance, 3).await); insert(&instance, 1, 250).await; - let new_item_at_index = get(&instance, 1).await; - assert_eq!(new_item_at_index, 250); - + assert_eq!(50, get(&instance, 0).await); + assert_eq!(250, get(&instance, 1).await); assert_eq!(100, get(&instance, 2).await); assert_eq!(150, get(&instance, 3).await); assert_eq!(200, get(&instance, 4).await); From ab325397655a90c7b299f47420a36ea1b87350a1 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Mon, 11 Jul 2022 21:18:30 +0530 Subject: [PATCH 55/59] added len checks --- .../test_projects/storage_vec/u8/mod.rs | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs index 8f452e2b0b7..c92b3485bf2 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs @@ -56,11 +56,17 @@ mod success { async fn can_remove() { let (instance, _id) = get_contract_instance().await; + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; push(&instance, 200).await; + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + assert_eq!(50, get(&instance, 0).await); assert_eq!(100, get(&instance, 1).await); assert_eq!(150, get(&instance, 2).await); @@ -72,17 +78,26 @@ mod success { assert_eq!(50, get(&instance, 0).await); assert_eq!(100, get(&instance, 1).await); assert_eq!(200, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); } #[tokio::test] async fn can_swap_remove() { let (instance, _id) = get_contract_instance().await; + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; push(&instance, 200).await; + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + assert_eq!(50, get(&instance, 0).await); assert_eq!(100, get(&instance, 1).await); assert_eq!(150, get(&instance, 2).await); @@ -94,17 +109,26 @@ mod success { assert_eq!(50, get(&instance, 0).await); assert_eq!(200, get(&instance, 1).await); assert_eq!(150, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); } #[tokio::test] async fn can_insert() { let (instance, _id) = get_contract_instance().await; + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; push(&instance, 200).await; + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + assert_eq!(50, get(&instance, 0).await); assert_eq!(100, get(&instance, 1).await); assert_eq!(150, get(&instance, 2).await); @@ -117,6 +141,9 @@ mod success { assert_eq!(100, get(&instance, 2).await); assert_eq!(150, get(&instance, 3).await); assert_eq!(200, get(&instance, 4).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 5); } #[tokio::test] @@ -124,7 +151,6 @@ mod success { let (instance, _id) = get_contract_instance().await; let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); push(&instance, 50).await; @@ -133,7 +159,6 @@ mod success { push(&instance, 200).await; let len_vec = len(&instance).await; - assert_eq!(len_vec, 4); push(&instance, 200).await; From b13a0a3df0ba06758655f14b069ffb1f312602c6 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Tue, 12 Jul 2022 00:08:33 +0530 Subject: [PATCH 56/59] FINALLY ADDED TESTS FOR ALL TYPES OMG --- .../storage_vec/svec_b256/.gitignore | 2 + .../storage_vec/svec_b256/Forc.lock | 14 + .../storage_vec/svec_b256/Forc.toml | 8 + .../storage_vec/svec_b256/src/main.sw | 67 +++++ .../storage_vec/svec_bool/.gitignore | 2 + .../storage_vec/svec_bool/Forc.lock | 14 + .../storage_vec/svec_bool/Forc.toml | 8 + .../storage_vec/svec_bool/src/main.sw | 67 +++++ .../storage_vec/svec_enum/.gitignore | 2 + .../storage_vec/svec_enum/Forc.lock | 14 + .../storage_vec/svec_enum/Forc.toml | 8 + .../storage_vec/svec_enum/src/main.sw | 72 +++++ .../storage_vec/svec_str/.gitignore | 2 + .../storage_vec/svec_str/Forc.lock | 14 + .../storage_vec/svec_str/Forc.toml | 8 + .../storage_vec/svec_str/src/main.sw | 67 +++++ .../storage_vec/svec_struct/.gitignore | 2 + .../storage_vec/svec_struct/Forc.lock | 14 + .../storage_vec/svec_struct/Forc.toml | 8 + .../storage_vec/svec_struct/src/main.sw | 72 +++++ .../storage_vec/svec_u16/.gitignore | 2 + .../storage_vec/svec_u16/Forc.lock | 14 + .../storage_vec/svec_u16/Forc.toml | 8 + .../storage_vec/svec_u16/src/main.sw | 67 +++++ .../storage_vec/svec_u32/.gitignore | 2 + .../storage_vec/svec_u32/Forc.lock | 14 + .../storage_vec/svec_u32/Forc.toml | 8 + .../storage_vec/svec_u32/src/main.sw | 67 +++++ .../storage_vec/svec_u64/.gitignore | 2 + .../storage_vec/svec_u64/Forc.lock | 14 + .../storage_vec/svec_u64/Forc.toml | 8 + .../storage_vec/svec_u64/src/main.sw | 67 +++++ .../test_projects/storage_vec/b256/mod.rs | 263 ++++++++++++++++ .../test_projects/storage_vec/b256/utils.rs | 70 +++++ .../test_projects/storage_vec/bool/mod.rs | 257 ++++++++++++++++ .../test_projects/storage_vec/bool/utils.rs | 70 +++++ .../test_projects/storage_vec/enum/mod.rs | 264 +++++++++++++++++ .../test_projects/storage_vec/enum/utils.rs | 70 +++++ .../test_projects/storage_vec/mod.rs | 8 + .../test_projects/storage_vec/str/mod.rs | 257 ++++++++++++++++ .../test_projects/storage_vec/str/utils.rs | 70 +++++ .../test_projects/storage_vec/struct/mod.rs | 280 ++++++++++++++++++ .../test_projects/storage_vec/struct/utils.rs | 70 +++++ .../test_projects/storage_vec/u16/mod.rs | 257 ++++++++++++++++ .../test_projects/storage_vec/u16/utils.rs | 70 +++++ .../test_projects/storage_vec/u32/mod.rs | 257 ++++++++++++++++ .../test_projects/storage_vec/u32/utils.rs | 70 +++++ .../test_projects/storage_vec/u64/mod.rs | 257 ++++++++++++++++ .../test_projects/storage_vec/u64/utils.rs | 70 +++++ 49 files changed, 3398 insertions(+) create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_str/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/src/main.sw create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/.gitignore create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.lock create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.toml create mode 100644 test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/src/main.sw create mode 100644 test/src/sdk-harness/test_projects/storage_vec/b256/mod.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/b256/utils.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/bool/mod.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/bool/utils.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/enum/mod.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/enum/utils.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/str/mod.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/str/utils.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/struct/mod.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/struct/utils.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/u16/mod.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/u16/utils.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/u32/mod.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/u32/utils.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/u64/mod.rs create mode 100644 test/src/sdk-harness/test_projects/storage_vec/u64/utils.rs diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.lock new file mode 100644 index 00000000000..37516c69109 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-BAD4826C86E6CE3D' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-BAD4826C86E6CE3D' +dependencies = ['core'] + +[[package]] +name = 'svec_b256' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.toml new file mode 100644 index 00000000000..1b1da6edb36 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_b256" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/src/main.sw new file mode 100644 index 00000000000..1d5b6e4e617 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_b256/src/main.sw @@ -0,0 +1,67 @@ +contract; + +use std::{option::Option, result::Result, storage::StorageVec}; + +abi MyContract { + #[storage(read, write)] + fn b256_push(value: b256); + #[storage(read)] + fn b256_get(index: u64) -> b256; + #[storage(read, write)] + fn b256_pop() -> b256; + #[storage(read, write)] + fn b256_remove(index: u64) -> b256; + #[storage(read, write)] + fn b256_swap_remove(index: u64) -> b256; + #[storage(read, write)] + fn b256_insert(index: u64, value: b256); + #[storage(read)] + fn b256_len() -> u64; + #[storage(read)] + fn b256_is_empty() -> bool; + #[storage(write)] + fn b256_clear(); +} + +storage { + my_vec: StorageVec = StorageVec {}, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn b256_push(value: b256) { + storage.my_vec.push(value); + } + #[storage(read)] + fn b256_get(index: u64) -> b256 { + storage.my_vec.get(index).unwrap() + } + #[storage(read, write)] + fn b256_pop() -> b256 { + storage.my_vec.pop().unwrap() + } + #[storage(read, write)] + fn b256_remove(index: u64) -> b256 { + storage.my_vec.remove(index) + } + #[storage(read, write)] + fn b256_swap_remove(index: u64) -> b256 { + storage.my_vec.swap_remove(index) + } + #[storage(read, write)] + fn b256_insert(index: u64, value: b256) { + storage.my_vec.insert(index, value); + } + #[storage(read)] + fn b256_len() -> u64 { + storage.my_vec.len() + } + #[storage(read)] + fn b256_is_empty() -> bool { + storage.my_vec.is_empty() + } + #[storage(write)] + fn b256_clear() { + storage.my_vec.clear(); + } +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.lock new file mode 100644 index 00000000000..d16c4ca4065 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-112F6FFCFCECE066' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-112F6FFCFCECE066' +dependencies = ['core'] + +[[package]] +name = 'svec_bool' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.toml new file mode 100644 index 00000000000..e7681654fa1 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_bool" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/src/main.sw new file mode 100644 index 00000000000..b0f44012eaa --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_bool/src/main.sw @@ -0,0 +1,67 @@ +contract; + +use std::{option::Option, result::Result, storage::StorageVec}; + +abi MyContract { + #[storage(read, write)] + fn bool_push(value: bool); + #[storage(read)] + fn bool_get(index: u64) -> bool; + #[storage(read, write)] + fn bool_pop() -> bool; + #[storage(read, write)] + fn bool_remove(index: u64) -> bool; + #[storage(read, write)] + fn bool_swap_remove(index: u64) -> bool; + #[storage(read, write)] + fn bool_insert(index: u64, value: bool); + #[storage(read)] + fn bool_len() -> u64; + #[storage(read)] + fn bool_is_empty() -> bool; + #[storage(write)] + fn bool_clear(); +} + +storage { + my_vec: StorageVec = StorageVec {}, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn bool_push(value: bool) { + storage.my_vec.push(value); + } + #[storage(read)] + fn bool_get(index: u64) -> bool { + storage.my_vec.get(index).unwrap() + } + #[storage(read, write)] + fn bool_pop() -> bool { + storage.my_vec.pop().unwrap() + } + #[storage(read, write)] + fn bool_remove(index: u64) -> bool { + storage.my_vec.remove(index) + } + #[storage(read, write)] + fn bool_swap_remove(index: u64) -> bool { + storage.my_vec.swap_remove(index) + } + #[storage(read, write)] + fn bool_insert(index: u64, value: bool) { + storage.my_vec.insert(index, value); + } + #[storage(read)] + fn bool_len() -> u64 { + storage.my_vec.len() + } + #[storage(read)] + fn bool_is_empty() -> bool { + storage.my_vec.is_empty() + } + #[storage(write)] + fn bool_clear() { + storage.my_vec.clear(); + } +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.lock new file mode 100644 index 00000000000..06f1f17cd10 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-BA7DA646BFFC59D3' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-BA7DA646BFFC59D3' +dependencies = ['core'] + +[[package]] +name = 'svec_enum' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.toml new file mode 100644 index 00000000000..6714176a6a2 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_enum" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/src/main.sw new file mode 100644 index 00000000000..94f6c54667d --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_enum/src/main.sw @@ -0,0 +1,72 @@ +contract; + +use std::{option::Option, result::Result, storage::StorageVec}; + +enum TestEnum { + A: bool, + B: u16, +} + +abi MyContract { + #[storage(read, write)] + fn enum_push(value: TestEnum); + #[storage(read)] + fn enum_get(index: u64) -> TestEnum; + #[storage(read, write)] + fn enum_pop() -> TestEnum; + #[storage(read, write)] + fn enum_remove(index: u64) -> TestEnum; + #[storage(read, write)] + fn enum_swap_remove(index: u64) -> TestEnum; + #[storage(read, write)] + fn enum_insert(index: u64, value: TestEnum); + #[storage(read)] + fn enum_len() -> u64; + #[storage(read)] + fn enum_is_empty() -> bool; + #[storage(write)] + fn enum_clear(); +} + +storage { + my_vec: StorageVec = StorageVec {}, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn enum_push(value: TestEnum) { + storage.my_vec.push(value); + } + #[storage(read)] + fn enum_get(index: u64) -> TestEnum { + storage.my_vec.get(index).unwrap() + } + #[storage(read, write)] + fn enum_pop() -> TestEnum { + storage.my_vec.pop().unwrap() + } + #[storage(read, write)] + fn enum_remove(index: u64) -> TestEnum { + storage.my_vec.remove(index) + } + #[storage(read, write)] + fn enum_swap_remove(index: u64) -> TestEnum { + storage.my_vec.swap_remove(index) + } + #[storage(read, write)] + fn enum_insert(index: u64, value: TestEnum) { + storage.my_vec.insert(index, value); + } + #[storage(read)] + fn enum_len() -> u64 { + storage.my_vec.len() + } + #[storage(read)] + fn enum_is_empty() -> bool { + storage.my_vec.is_empty() + } + #[storage(write)] + fn enum_clear() { + storage.my_vec.clear(); + } +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.lock new file mode 100644 index 00000000000..117a72a36a9 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-5A8E0F2C8C65E65F' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-5A8E0F2C8C65E65F' +dependencies = ['core'] + +[[package]] +name = 'svec_str' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.toml new file mode 100644 index 00000000000..d65b979ece3 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_str" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/src/main.sw new file mode 100644 index 00000000000..aba2250e206 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_str/src/main.sw @@ -0,0 +1,67 @@ +contract; + +use std::{option::Option, result::Result, storage::StorageVec}; + +abi MyContract { + #[storage(read, write)] + fn str_push(value: str[4]); + #[storage(read)] + fn str_get(index: u64) -> str[4]; + #[storage(read, write)] + fn str_pop() -> str[4]; + #[storage(read, write)] + fn str_remove(index: u64) -> str[4]; + #[storage(read, write)] + fn str_swap_remove(index: u64) -> str[4]; + #[storage(read, write)] + fn str_insert(index: u64, value: str[4]); + #[storage(read)] + fn str_len() -> u64; + #[storage(read)] + fn str_is_empty() -> bool; + #[storage(write)] + fn str_clear(); +} + +storage { + my_vec: StorageVec = StorageVec {}, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn str_push(value: str[4]) { + storage.my_vec.push(value); + } + #[storage(read)] + fn str_get(index: u64) -> str[4] { + storage.my_vec.get(index).unwrap() + } + #[storage(read, write)] + fn str_pop() -> str[4] { + storage.my_vec.pop().unwrap() + } + #[storage(read, write)] + fn str_remove(index: u64) -> str[4] { + storage.my_vec.remove(index) + } + #[storage(read, write)] + fn str_swap_remove(index: u64) -> str[4] { + storage.my_vec.swap_remove(index) + } + #[storage(read, write)] + fn str_insert(index: u64, value: str[4]) { + storage.my_vec.insert(index, value); + } + #[storage(read)] + fn str_len() -> u64 { + storage.my_vec.len() + } + #[storage(read)] + fn str_is_empty() -> bool { + storage.my_vec.is_empty() + } + #[storage(write)] + fn str_clear() { + storage.my_vec.clear(); + } +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.lock new file mode 100644 index 00000000000..e185915ccb2 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-5D548BD88B479EAC' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-5D548BD88B479EAC' +dependencies = ['core'] + +[[package]] +name = 'svec_struct' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.toml new file mode 100644 index 00000000000..8ad370c395f --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_struct" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/src/main.sw new file mode 100644 index 00000000000..f9fe22c983e --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_struct/src/main.sw @@ -0,0 +1,72 @@ +contract; + +use std::{option::Option, result::Result, storage::StorageVec}; + +struct TestStruct { + A: bool, + B: u16, +} + +abi MyContract { + #[storage(read, write)] + fn struct_push(value: TestStruct); + #[storage(read)] + fn struct_get(index: u64) -> TestStruct; + #[storage(read, write)] + fn struct_pop() -> TestStruct; + #[storage(read, write)] + fn struct_remove(index: u64) -> TestStruct; + #[storage(read, write)] + fn struct_swap_remove(index: u64) -> TestStruct; + #[storage(read, write)] + fn struct_insert(index: u64, value: TestStruct); + #[storage(read)] + fn struct_len() -> u64; + #[storage(read)] + fn struct_is_empty() -> bool; + #[storage(write)] + fn struct_clear(); +} + +storage { + my_vec: StorageVec = StorageVec {}, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn struct_push(value: TestStruct) { + storage.my_vec.push(value); + } + #[storage(read)] + fn struct_get(index: u64) -> TestStruct { + storage.my_vec.get(index).unwrap() + } + #[storage(read, write)] + fn struct_pop() -> TestStruct { + storage.my_vec.pop().unwrap() + } + #[storage(read, write)] + fn struct_remove(index: u64) -> TestStruct { + storage.my_vec.remove(index) + } + #[storage(read, write)] + fn struct_swap_remove(index: u64) -> TestStruct { + storage.my_vec.swap_remove(index) + } + #[storage(read, write)] + fn struct_insert(index: u64, value: TestStruct) { + storage.my_vec.insert(index, value); + } + #[storage(read)] + fn struct_len() -> u64 { + storage.my_vec.len() + } + #[storage(read)] + fn struct_is_empty() -> bool { + storage.my_vec.is_empty() + } + #[storage(write)] + fn struct_clear() { + storage.my_vec.clear(); + } +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.lock new file mode 100644 index 00000000000..3b133df026f --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-D2C27CF3A144E426' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-D2C27CF3A144E426' +dependencies = ['core'] + +[[package]] +name = 'svec_u16' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.toml new file mode 100644 index 00000000000..a2f5b819f5b --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_u16" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/src/main.sw new file mode 100644 index 00000000000..db8f8f48ce6 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u16/src/main.sw @@ -0,0 +1,67 @@ +contract; + +use std::{option::Option, result::Result, storage::StorageVec}; + +abi MyContract { + #[storage(read, write)] + fn u16_push(value: u16); + #[storage(read)] + fn u16_get(index: u64) -> u16; + #[storage(read, write)] + fn u16_pop() -> u16; + #[storage(read, write)] + fn u16_remove(index: u64) -> u16; + #[storage(read, write)] + fn u16_swap_remove(index: u64) -> u16; + #[storage(read, write)] + fn u16_insert(index: u64, value: u16); + #[storage(read)] + fn u16_len() -> u64; + #[storage(read)] + fn u16_is_empty() -> bool; + #[storage(write)] + fn u16_clear(); +} + +storage { + my_vec: StorageVec = StorageVec {}, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn u16_push(value: u16) { + storage.my_vec.push(value); + } + #[storage(read)] + fn u16_get(index: u64) -> u16 { + storage.my_vec.get(index).unwrap() + } + #[storage(read, write)] + fn u16_pop() -> u16 { + storage.my_vec.pop().unwrap() + } + #[storage(read, write)] + fn u16_remove(index: u64) -> u16 { + storage.my_vec.remove(index) + } + #[storage(read, write)] + fn u16_swap_remove(index: u64) -> u16 { + storage.my_vec.swap_remove(index) + } + #[storage(read, write)] + fn u16_insert(index: u64, value: u16) { + storage.my_vec.insert(index, value); + } + #[storage(read)] + fn u16_len() -> u64 { + storage.my_vec.len() + } + #[storage(read)] + fn u16_is_empty() -> bool { + storage.my_vec.is_empty() + } + #[storage(write)] + fn u16_clear() { + storage.my_vec.clear(); + } +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.lock new file mode 100644 index 00000000000..233fdbca046 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-273E1774DB1237EA' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-273E1774DB1237EA' +dependencies = ['core'] + +[[package]] +name = 'svec_u32' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.toml new file mode 100644 index 00000000000..8356145b78d --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_u32" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/src/main.sw new file mode 100644 index 00000000000..1b01726def1 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u32/src/main.sw @@ -0,0 +1,67 @@ +contract; + +use std::{option::Option, result::Result, storage::StorageVec}; + +abi MyContract { + #[storage(read, write)] + fn u32_push(value: u32); + #[storage(read)] + fn u32_get(index: u64) -> u32; + #[storage(read, write)] + fn u32_pop() -> u32; + #[storage(read, write)] + fn u32_remove(index: u64) -> u32; + #[storage(read, write)] + fn u32_swap_remove(index: u64) -> u32; + #[storage(read, write)] + fn u32_insert(index: u64, value: u32); + #[storage(read)] + fn u32_len() -> u64; + #[storage(read)] + fn u32_is_empty() -> bool; + #[storage(write)] + fn u32_clear(); +} + +storage { + my_vec: StorageVec = StorageVec {}, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn u32_push(value: u32) { + storage.my_vec.push(value); + } + #[storage(read)] + fn u32_get(index: u64) -> u32 { + storage.my_vec.get(index).unwrap() + } + #[storage(read, write)] + fn u32_pop() -> u32 { + storage.my_vec.pop().unwrap() + } + #[storage(read, write)] + fn u32_remove(index: u64) -> u32 { + storage.my_vec.remove(index) + } + #[storage(read, write)] + fn u32_swap_remove(index: u64) -> u32 { + storage.my_vec.swap_remove(index) + } + #[storage(read, write)] + fn u32_insert(index: u64, value: u32) { + storage.my_vec.insert(index, value); + } + #[storage(read)] + fn u32_len() -> u64 { + storage.my_vec.len() + } + #[storage(read)] + fn u32_is_empty() -> bool { + storage.my_vec.is_empty() + } + #[storage(write)] + fn u32_clear() { + storage.my_vec.clear(); + } +} diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/.gitignore b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/.gitignore new file mode 100644 index 00000000000..77d3844f58c --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.lock b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.lock new file mode 100644 index 00000000000..e7ac2c09eda --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.lock @@ -0,0 +1,14 @@ +[[package]] +name = 'core' +source = 'path+from-root-1BF264D58B073501' +dependencies = [] + +[[package]] +name = 'std' +source = 'path+from-root-1BF264D58B073501' +dependencies = ['core'] + +[[package]] +name = 'svec_u64' +source = 'root' +dependencies = ['std'] diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.toml b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.toml new file mode 100644 index 00000000000..beb8efb4f34 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "svec_u64" + +[dependencies] +std = { path = "../../../../../../sway-lib-std" } diff --git a/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/src/main.sw b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/src/main.sw new file mode 100644 index 00000000000..a3251772846 --- /dev/null +++ b/test/src/sdk-harness/test_artifacts/storage_vec/svec_u64/src/main.sw @@ -0,0 +1,67 @@ +contract; + +use std::{option::Option, result::Result, storage::StorageVec}; + +abi MyContract { + #[storage(read, write)] + fn u64_push(value: u64); + #[storage(read)] + fn u64_get(index: u64) -> u64; + #[storage(read, write)] + fn u64_pop() -> u64; + #[storage(read, write)] + fn u64_remove(index: u64) -> u64; + #[storage(read, write)] + fn u64_swap_remove(index: u64) -> u64; + #[storage(read, write)] + fn u64_insert(index: u64, value: u64); + #[storage(read)] + fn u64_len() -> u64; + #[storage(read)] + fn u64_is_empty() -> bool; + #[storage(write)] + fn u64_clear(); +} + +storage { + my_vec: StorageVec = StorageVec {}, +} + +impl MyContract for Contract { + #[storage(read, write)] + fn u64_push(value: u64) { + storage.my_vec.push(value); + } + #[storage(read)] + fn u64_get(index: u64) -> u64 { + storage.my_vec.get(index).unwrap() + } + #[storage(read, write)] + fn u64_pop() -> u64 { + storage.my_vec.pop().unwrap() + } + #[storage(read, write)] + fn u64_remove(index: u64) -> u64 { + storage.my_vec.remove(index) + } + #[storage(read, write)] + fn u64_swap_remove(index: u64) -> u64 { + storage.my_vec.swap_remove(index) + } + #[storage(read, write)] + fn u64_insert(index: u64, value: u64) { + storage.my_vec.insert(index, value); + } + #[storage(read)] + fn u64_len() -> u64 { + storage.my_vec.len() + } + #[storage(read)] + fn u64_is_empty() -> bool { + storage.my_vec.is_empty() + } + #[storage(write)] + fn u64_clear() { + storage.my_vec.clear(); + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/b256/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/b256/mod.rs new file mode 100644 index 00000000000..fe0639e9751 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/b256/mod.rs @@ -0,0 +1,263 @@ +mod utils; + +use utils::{ + setup::get_contract_instance, + wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, +}; + +// TODO: Replace many of the get calls with direct storage values +// once the SDK supports that + +const BYTES1: [u8; 32] = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]; +const BYTES2: [u8; 32] = [32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63]; +const BYTES3: [u8; 32] = [64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95]; +const BYTES4: [u8; 32] = [96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127]; +const BYTES5: [u8; 32] = [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159]; + +mod success { + use super::*; + + #[tokio::test] + async fn can_get() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, BYTES1).await; + let item = get(&instance, 0).await; + + assert_eq!(item, BYTES1); + } + + #[tokio::test] + async fn can_push() { + let (instance, _id) = get_contract_instance().await; + + let len_before_push = len(&instance).await; + assert_eq!(len_before_push, 0); + + push(&instance, BYTES1).await; + let item = get(&instance, 0).await; + + assert_eq!(item, BYTES1); + + let len_after_push = len(&instance).await; + assert_eq!(len_after_push, 1); + } + + #[tokio::test] + async fn can_pop() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, BYTES1).await; + let len_before_pop = len(&instance).await; + assert_eq!(len_before_pop, 1); + + let item = pop(&instance).await; + assert_eq!(item, BYTES1); + + let len_after_pop = len(&instance).await; + assert_eq!(len_after_pop, 0); + } + + #[tokio::test] + async fn can_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, BYTES1).await; + push(&instance, BYTES2).await; + push(&instance, BYTES3).await; + push(&instance, BYTES4).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(BYTES1, get(&instance, 0).await); + assert_eq!(BYTES2, get(&instance, 1).await); + assert_eq!(BYTES3, get(&instance, 2).await); + assert_eq!(BYTES4, get(&instance, 3).await); + + let item = remove(&instance, 2).await; + assert_eq!(item, BYTES3); + + assert_eq!(BYTES1, get(&instance, 0).await); + assert_eq!(BYTES2, get(&instance, 1).await); + assert_eq!(BYTES4, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, BYTES1).await; + push(&instance, BYTES2).await; + push(&instance, BYTES3).await; + push(&instance, BYTES4).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(BYTES1, get(&instance, 0).await); + assert_eq!(BYTES2, get(&instance, 1).await); + assert_eq!(BYTES3, get(&instance, 2).await); + assert_eq!(BYTES4, get(&instance, 3).await); + + let item = swap_remove(&instance, 1).await; + assert_eq!(item, BYTES2); + + assert_eq!(BYTES1, get(&instance, 0).await); + assert_eq!(BYTES4, get(&instance, 1).await); + assert_eq!(BYTES3, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_insert() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, BYTES1).await; + push(&instance, BYTES2).await; + push(&instance, BYTES3).await; + push(&instance, BYTES4).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(BYTES1, get(&instance, 0).await); + assert_eq!(BYTES2, get(&instance, 1).await); + assert_eq!(BYTES3, get(&instance, 2).await); + assert_eq!(BYTES4, get(&instance, 3).await); + + insert(&instance, 1, BYTES5).await; + + assert_eq!(BYTES1, get(&instance, 0).await); + assert_eq!(BYTES5, get(&instance, 1).await); + assert_eq!(BYTES2, get(&instance, 2).await); + assert_eq!(BYTES3, get(&instance, 3).await); + assert_eq!(BYTES4, get(&instance, 4).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_get_len() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, BYTES1).await; + push(&instance, BYTES2).await; + push(&instance, BYTES3).await; + push(&instance, BYTES4).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + push(&instance, BYTES5).await; + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_confirm_emptiness() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, BYTES1).await; + push(&instance, BYTES2).await; + push(&instance, BYTES3).await; + push(&instance, BYTES4).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } + + #[tokio::test] + async fn can_clear() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, BYTES1).await; + push(&instance, BYTES2).await; + push(&instance, BYTES3).await; + push(&instance, BYTES4).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } +} + +// Some of these are meant to be tests for None returns but since the SDK doesnt support options; +// the options are being unwrapped in the contract and tested as reverts instead +mod failure { + use super::*; + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_get() { + let (instance, _id) = get_contract_instance().await; + + get(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_pop() { + let (instance, _id) = get_contract_instance().await; + + pop(&instance).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = swap_remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_insert() { + let (instance, _id) = get_contract_instance().await; + + insert(&instance, 1, BYTES5).await; + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/b256/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/b256/utils.rs new file mode 100644 index 00000000000..854aaae235a --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/b256/utils.rs @@ -0,0 +1,70 @@ +use fuels::{prelude::*, tx::ContractId}; +// Load abi from json +abigen!( + MyContract, + "test_artifacts/storage_vec/svec_b256/out/debug/svec_b256-abi.json" +); + +pub mod setup { + use super::*; + + pub async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "test_artifacts/storage_vec/svec_b256/out/debug/svec_b256.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(Some( + "test_artifacts/storage_vec/svec_b256/out/debug/svec_b256-storage_slots.json".to_string(), + )), + ) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) + } +} + +pub mod wrappers { + use super::*; + + pub async fn push(instance: &MyContract, value: [u8; 32]) { + instance.b256_push(value).call().await.unwrap(); + } + + pub async fn get(instance: &MyContract, index: u64) -> [u8; 32] { + instance.b256_get(index).call().await.unwrap().value + } + + pub async fn pop(instance: &MyContract) -> [u8; 32] { + instance.b256_pop().call().await.unwrap().value + } + + pub async fn remove(instance: &MyContract, index: u64) -> [u8; 32] { + instance.b256_remove(index).call().await.unwrap().value + } + + pub async fn swap_remove(instance: &MyContract, index: u64) -> [u8; 32] { + instance.b256_swap_remove(index).call().await.unwrap().value + } + + pub async fn insert(instance: &MyContract, index: u64, value: [u8; 32]) { + instance.b256_insert(index, value).call().await.unwrap(); + } + + pub async fn len(instance: &MyContract) -> u64 { + instance.b256_len().call().await.unwrap().value + } + + pub async fn is_empty(instance: &MyContract) -> bool { + instance.b256_is_empty().call().await.unwrap().value + } + + pub async fn clear(instance: &MyContract) { + instance.b256_clear().call().await.unwrap(); + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/bool/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/bool/mod.rs new file mode 100644 index 00000000000..8bab7368f29 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/bool/mod.rs @@ -0,0 +1,257 @@ +mod utils; + +use utils::{ + setup::get_contract_instance, + wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, +}; + +// TODO: Replace many of the get calls with direct storage values +// once the SDK supports that + +mod success { + use super::*; + + #[tokio::test] + async fn can_get() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, true).await; + let item = get(&instance, 0).await; + + assert_eq!(item, true); + } + + #[tokio::test] + async fn can_push() { + let (instance, _id) = get_contract_instance().await; + + let len_before_push = len(&instance).await; + assert_eq!(len_before_push, 0); + + push(&instance, true).await; + let item = get(&instance, 0).await; + + assert_eq!(item, true); + + let len_after_push = len(&instance).await; + assert_eq!(len_after_push, 1); + } + + #[tokio::test] + async fn can_pop() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, true).await; + let len_before_pop = len(&instance).await; + assert_eq!(len_before_pop, 1); + + let item = pop(&instance).await; + assert_eq!(item, true); + + let len_after_pop = len(&instance).await; + assert_eq!(len_after_pop, 0); + } + + #[tokio::test] + async fn can_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, true).await; + push(&instance, false).await; + push(&instance, true).await; + push(&instance, false).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(true, get(&instance, 0).await); + assert_eq!(false, get(&instance, 1).await); + assert_eq!(true, get(&instance, 2).await); + assert_eq!(false, get(&instance, 3).await); + + let item = remove(&instance, 2).await; + assert_eq!(item, true); + + assert_eq!(true, get(&instance, 0).await); + assert_eq!(false, get(&instance, 1).await); + assert_eq!(false, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, true).await; + push(&instance, false).await; + push(&instance, true).await; + push(&instance, false).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(true, get(&instance, 0).await); + assert_eq!(false, get(&instance, 1).await); + assert_eq!(true, get(&instance, 2).await); + assert_eq!(false, get(&instance, 3).await); + + let item = swap_remove(&instance, 1).await; + assert_eq!(item, false); + + assert_eq!(true, get(&instance, 0).await); + assert_eq!(false, get(&instance, 1).await); + assert_eq!(true, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_insert() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, true).await; + push(&instance, false).await; + push(&instance, true).await; + push(&instance, false).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(true, get(&instance, 0).await); + assert_eq!(false, get(&instance, 1).await); + assert_eq!(true, get(&instance, 2).await); + assert_eq!(false, get(&instance, 3).await); + + insert(&instance, 1, true).await; + + assert_eq!(true, get(&instance, 0).await); + assert_eq!(true, get(&instance, 1).await); + assert_eq!(false, get(&instance, 2).await); + assert_eq!(true, get(&instance, 3).await); + assert_eq!(false, get(&instance, 4).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_get_len() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, true).await; + push(&instance, false).await; + push(&instance, true).await; + push(&instance, false).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + push(&instance, false).await; + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_confirm_emptiness() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, true).await; + push(&instance, false).await; + push(&instance, true).await; + push(&instance, false).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } + + #[tokio::test] + async fn can_clear() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, true).await; + push(&instance, false).await; + push(&instance, true).await; + push(&instance, false).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } +} + +// Some of these are meant to be tests for None returns but since the SDK doesnt support options; +// the options are being unwrapped in the contract and tested as reverts instead +mod failure { + use super::*; + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_get() { + let (instance, _id) = get_contract_instance().await; + + get(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_pop() { + let (instance, _id) = get_contract_instance().await; + + pop(&instance).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = swap_remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_insert() { + let (instance, _id) = get_contract_instance().await; + + insert(&instance, 1, true).await; + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/bool/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/bool/utils.rs new file mode 100644 index 00000000000..1138b71d581 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/bool/utils.rs @@ -0,0 +1,70 @@ +use fuels::{prelude::*, tx::ContractId}; +// Load abi from json +abigen!( + MyContract, + "test_artifacts/storage_vec/svec_bool/out/debug/svec_bool-abi.json" +); + +pub mod setup { + use super::*; + + pub async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "test_artifacts/storage_vec/svec_bool/out/debug/svec_bool.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(Some( + "test_artifacts/storage_vec/svec_bool/out/debug/svec_bool-storage_slots.json".to_string(), + )), + ) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) + } +} + +pub mod wrappers { + use super::*; + + pub async fn push(instance: &MyContract, value: bool) { + instance.bool_push(value).call().await.unwrap(); + } + + pub async fn get(instance: &MyContract, index: u64) -> bool { + instance.bool_get(index).call().await.unwrap().value + } + + pub async fn pop(instance: &MyContract) -> bool { + instance.bool_pop().call().await.unwrap().value + } + + pub async fn remove(instance: &MyContract, index: u64) -> bool { + instance.bool_remove(index).call().await.unwrap().value + } + + pub async fn swap_remove(instance: &MyContract, index: u64) -> bool { + instance.bool_swap_remove(index).call().await.unwrap().value + } + + pub async fn insert(instance: &MyContract, index: u64, value: bool) { + instance.bool_insert(index, value).call().await.unwrap(); + } + + pub async fn len(instance: &MyContract) -> u64 { + instance.bool_len().call().await.unwrap().value + } + + pub async fn is_empty(instance: &MyContract) -> bool { + instance.bool_is_empty().call().await.unwrap().value + } + + pub async fn clear(instance: &MyContract) { + instance.bool_clear().call().await.unwrap(); + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/enum/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/enum/mod.rs new file mode 100644 index 00000000000..f1fa8505d92 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/enum/mod.rs @@ -0,0 +1,264 @@ +mod utils; + +use utils::{ + setup::get_contract_instance, + wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, + TestEnum, +}; + +// TODO: Replace many of the get calls with direct storage values +// once the SDK supports that + +const ENUM1: TestEnum = TestEnum::A(true); +const ENUM2: TestEnum = TestEnum::A(false); +const ENUM3: TestEnum = TestEnum::B(1); +const ENUM4: TestEnum = TestEnum::B(2); +const ENUM5: TestEnum = TestEnum::B(3); + +mod success { + use super::*; + + #[tokio::test] + async fn can_get() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, ENUM1).await; + let item = get(&instance, 0).await; + + assert_eq!(item, ENUM1); + } + + #[tokio::test] + async fn can_push() { + let (instance, _id) = get_contract_instance().await; + + let len_before_push = len(&instance).await; + assert_eq!(len_before_push, 0); + + push(&instance, ENUM1).await; + let item = get(&instance, 0).await; + + assert_eq!(item, ENUM1); + + let len_after_push = len(&instance).await; + assert_eq!(len_after_push, 1); + } + + #[tokio::test] + async fn can_pop() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, ENUM1).await; + let len_before_pop = len(&instance).await; + assert_eq!(len_before_pop, 1); + + let item = pop(&instance).await; + assert_eq!(item, ENUM1); + + let len_after_pop = len(&instance).await; + assert_eq!(len_after_pop, 0); + } + + #[tokio::test] + async fn can_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, ENUM1).await; + push(&instance, ENUM2).await; + push(&instance, ENUM3).await; + push(&instance, ENUM4).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(ENUM1, get(&instance, 0).await); + assert_eq!(ENUM2, get(&instance, 1).await); + assert_eq!(ENUM3, get(&instance, 2).await); + assert_eq!(ENUM4, get(&instance, 3).await); + + let item = remove(&instance, 2).await; + assert_eq!(item, ENUM3); + + assert_eq!(ENUM1, get(&instance, 0).await); + assert_eq!(ENUM2, get(&instance, 1).await); + assert_eq!(ENUM4, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, ENUM1).await; + push(&instance, ENUM2).await; + push(&instance, ENUM3).await; + push(&instance, ENUM4).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(ENUM1, get(&instance, 0).await); + assert_eq!(ENUM2, get(&instance, 1).await); + assert_eq!(ENUM3, get(&instance, 2).await); + assert_eq!(ENUM4, get(&instance, 3).await); + + let item = swap_remove(&instance, 1).await; + assert_eq!(item, ENUM2); + + assert_eq!(ENUM1, get(&instance, 0).await); + assert_eq!(ENUM4, get(&instance, 1).await); + assert_eq!(ENUM3, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_insert() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, ENUM1).await; + push(&instance, ENUM2).await; + push(&instance, ENUM3).await; + push(&instance, ENUM4).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(ENUM1, get(&instance, 0).await); + assert_eq!(ENUM2, get(&instance, 1).await); + assert_eq!(ENUM3, get(&instance, 2).await); + assert_eq!(ENUM4, get(&instance, 3).await); + + insert(&instance, 1, ENUM5).await; + + assert_eq!(ENUM1, get(&instance, 0).await); + assert_eq!(ENUM5, get(&instance, 1).await); + assert_eq!(ENUM2, get(&instance, 2).await); + assert_eq!(ENUM3, get(&instance, 3).await); + assert_eq!(ENUM4, get(&instance, 4).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_get_len() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, ENUM1).await; + push(&instance, ENUM2).await; + push(&instance, ENUM3).await; + push(&instance, ENUM4).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + push(&instance, ENUM4).await; + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_confirm_emptiness() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, ENUM1).await; + push(&instance, ENUM2).await; + push(&instance, ENUM3).await; + push(&instance, ENUM4).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } + + #[tokio::test] + async fn can_clear() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, ENUM1).await; + push(&instance, ENUM2).await; + push(&instance, ENUM3).await; + push(&instance, ENUM4).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } +} + +// Some of these are meant to be tests for None returns but since the SDK doesnt support options; +// the options are being unwrapped in the contract and tested as reverts instead +mod failure { + use super::*; + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_get() { + let (instance, _id) = get_contract_instance().await; + + get(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_pop() { + let (instance, _id) = get_contract_instance().await; + + pop(&instance).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = swap_remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_insert() { + let (instance, _id) = get_contract_instance().await; + + insert(&instance, 1, ENUM5).await; + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/enum/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/enum/utils.rs new file mode 100644 index 00000000000..54680e1e105 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/enum/utils.rs @@ -0,0 +1,70 @@ +use fuels::{prelude::*, tx::ContractId}; +// Load abi from json +abigen!( + MyContract, + "test_artifacts/storage_vec/svec_enum/out/debug/svec_enum-abi.json" +); + +pub mod setup { + use super::*; + + pub async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "test_artifacts/storage_vec/svec_enum/out/debug/svec_enum.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(Some( + "test_artifacts/storage_vec/svec_enum/out/debug/svec_enum-storage_slots.json".to_string(), + )), + ) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) + } +} + +pub mod wrappers { + use super::*; + + pub async fn push(instance: &MyContract, value: TestEnum) { + instance.enum_push(value).call().await.unwrap(); + } + + pub async fn get(instance: &MyContract, index: u64) -> TestEnum { + instance.enum_get(index).call().await.unwrap().value + } + + pub async fn pop(instance: &MyContract) -> TestEnum { + instance.enum_pop().call().await.unwrap().value + } + + pub async fn remove(instance: &MyContract, index: u64) -> TestEnum { + instance.enum_remove(index).call().await.unwrap().value + } + + pub async fn swap_remove(instance: &MyContract, index: u64) -> TestEnum { + instance.enum_swap_remove(index).call().await.unwrap().value + } + + pub async fn insert(instance: &MyContract, index: u64, value: TestEnum) { + instance.enum_insert(index, value).call().await.unwrap(); + } + + pub async fn len(instance: &MyContract) -> u64 { + instance.enum_len().call().await.unwrap().value + } + + pub async fn is_empty(instance: &MyContract) -> bool { + instance.enum_is_empty().call().await.unwrap().value + } + + pub async fn clear(instance: &MyContract) { + instance.enum_clear().call().await.unwrap(); + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index b0bbf99eb32..2cd48fbce3e 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -1 +1,9 @@ mod u8; +mod u16; +mod u32; +mod u64; +mod b256; +mod bool; +mod str; +mod r#struct; +mod r#enum; \ No newline at end of file diff --git a/test/src/sdk-harness/test_projects/storage_vec/str/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/str/mod.rs new file mode 100644 index 00000000000..2f4b398fb27 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/str/mod.rs @@ -0,0 +1,257 @@ +mod utils; + +use utils::{ + setup::get_contract_instance, + wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, +}; + +// TODO: Replace many of the get calls with direct storage values +// once the SDK supports that + +mod success { + use super::*; + + #[tokio::test] + async fn can_get() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, String::from("0050")).await; + let item = get(&instance, 0).await; + + assert_eq!(item, String::from("0050")); + } + + #[tokio::test] + async fn can_push() { + let (instance, _id) = get_contract_instance().await; + + let len_before_push = len(&instance).await; + assert_eq!(len_before_push, 0); + + push(&instance, String::from("0050")).await; + let item = get(&instance, 0).await; + + assert_eq!(item, String::from("0050")); + + let len_after_push = len(&instance).await; + assert_eq!(len_after_push, 1); + } + + #[tokio::test] + async fn can_pop() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, String::from("0050")).await; + let len_before_pop = len(&instance).await; + assert_eq!(len_before_pop, 1); + + let item = pop(&instance).await; + assert_eq!(item, String::from("0050")); + + let len_after_pop = len(&instance).await; + assert_eq!(len_after_pop, 0); + } + + #[tokio::test] + async fn can_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, String::from("0050")).await; + push(&instance, String::from("0100")).await; + push(&instance, String::from("0150")).await; + push(&instance, String::from("0200")).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(String::from("0050"), get(&instance, 0).await); + assert_eq!(String::from("0100"), get(&instance, 1).await); + assert_eq!(String::from("0150"), get(&instance, 2).await); + assert_eq!(String::from("0200"), get(&instance, 3).await); + + let item = remove(&instance, 2).await; + assert_eq!(item, String::from("0150")); + + assert_eq!(String::from("0050"), get(&instance, 0).await); + assert_eq!(String::from("0100"), get(&instance, 1).await); + assert_eq!(String::from("0200"), get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, String::from("0050")).await; + push(&instance, String::from("0100")).await; + push(&instance, String::from("0150")).await; + push(&instance, String::from("0200")).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(String::from("0050"), get(&instance, 0).await); + assert_eq!(String::from("0100"), get(&instance, 1).await); + assert_eq!(String::from("0150"), get(&instance, 2).await); + assert_eq!(String::from("0200"), get(&instance, 3).await); + + let item = swap_remove(&instance, 1).await; + assert_eq!(item, String::from("0100")); + + assert_eq!(String::from("0050"), get(&instance, 0).await); + assert_eq!(String::from("0200"), get(&instance, 1).await); + assert_eq!(String::from("0150"), get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_insert() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, String::from("0050")).await; + push(&instance, String::from("0100")).await; + push(&instance, String::from("0150")).await; + push(&instance, String::from("0200")).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(String::from("0050"), get(&instance, 0).await); + assert_eq!(String::from("0100"), get(&instance, 1).await); + assert_eq!(String::from("0150"), get(&instance, 2).await); + assert_eq!(String::from("0200"), get(&instance, 3).await); + + insert(&instance, 1, String::from("0250")).await; + + assert_eq!(String::from("0050"), get(&instance, 0).await); + assert_eq!(String::from("0250"), get(&instance, 1).await); + assert_eq!(String::from("0100"), get(&instance, 2).await); + assert_eq!(String::from("0150"), get(&instance, 3).await); + assert_eq!(String::from("0200"), get(&instance, 4).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_get_len() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, String::from("0050")).await; + push(&instance, String::from("0100")).await; + push(&instance, String::from("0150")).await; + push(&instance, String::from("0200")).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + push(&instance, String::from("0200")).await; + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_confirm_emptiness() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, String::from("0050")).await; + push(&instance, String::from("0100")).await; + push(&instance, String::from("0150")).await; + push(&instance, String::from("0200")).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } + + #[tokio::test] + async fn can_clear() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, String::from("0050")).await; + push(&instance, String::from("0100")).await; + push(&instance, String::from("0150")).await; + push(&instance, String::from("0200")).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } +} + +// Some of these are meant to be tests for None returns but since the SDK doesnt support options; +// the options are being unwrapped in the contract and tested as reverts instead +mod failure { + use super::*; + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_get() { + let (instance, _id) = get_contract_instance().await; + + get(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_pop() { + let (instance, _id) = get_contract_instance().await; + + pop(&instance).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = swap_remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_insert() { + let (instance, _id) = get_contract_instance().await; + + insert(&instance, 1, String::from("0250")).await; + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/str/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/str/utils.rs new file mode 100644 index 00000000000..a6aa96e6258 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/str/utils.rs @@ -0,0 +1,70 @@ +use fuels::{prelude::*, tx::ContractId}; +// Load abi from json +abigen!( + MyContract, + "test_artifacts/storage_vec/svec_str/out/debug/svec_str-abi.json" +); + +pub mod setup { + use super::*; + + pub async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "test_artifacts/storage_vec/svec_str/out/debug/svec_str.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(Some( + "test_artifacts/storage_vec/svec_str/out/debug/svec_str-storage_slots.json".to_string(), + )), + ) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) + } +} + +pub mod wrappers { + use super::*; + + pub async fn push(instance: &MyContract, value: String) { + instance.str_push(value).call().await.unwrap(); + } + + pub async fn get(instance: &MyContract, index: u64) -> String { + instance.str_get(index).call().await.unwrap().value + } + + pub async fn pop(instance: &MyContract) -> String { + instance.str_pop().call().await.unwrap().value + } + + pub async fn remove(instance: &MyContract, index: u64) -> String { + instance.str_remove(index).call().await.unwrap().value + } + + pub async fn swap_remove(instance: &MyContract, index: u64) -> String { + instance.str_swap_remove(index).call().await.unwrap().value + } + + pub async fn insert(instance: &MyContract, index: u64, value: String) { + instance.str_insert(index, value).call().await.unwrap(); + } + + pub async fn len(instance: &MyContract) -> u64 { + instance.str_len().call().await.unwrap().value + } + + pub async fn is_empty(instance: &MyContract) -> bool { + instance.str_is_empty().call().await.unwrap().value + } + + pub async fn clear(instance: &MyContract) { + instance.str_clear().call().await.unwrap(); + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/struct/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/struct/mod.rs new file mode 100644 index 00000000000..84ae3fc8b2c --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/struct/mod.rs @@ -0,0 +1,280 @@ +mod utils; + +use utils::{ + setup::get_contract_instance, + wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, + TestStruct, +}; + + +// TODO: Replace many of the get calls with direct storage values +// once the SDK supports that + +const STRUCT1: TestStruct = TestStruct { + a: true, + b: 1, +}; +const STRUCT2: TestStruct = TestStruct { + a: false, + b: 2, +}; +const STRUCT3: TestStruct = TestStruct { + a: true, + b: 3, +}; +const STRUCT4: TestStruct = TestStruct { + a: false, + b: 4, +}; +const STRUCT5: TestStruct = TestStruct { + a: true, + b: 5, +}; + +mod success { + use super::*; + + #[tokio::test] + async fn can_get() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, STRUCT1).await; + let item = get(&instance, 0).await; + + assert_eq!(item, STRUCT1); + } + + #[tokio::test] + async fn can_push() { + let (instance, _id) = get_contract_instance().await; + + let len_before_push = len(&instance).await; + assert_eq!(len_before_push, 0); + + push(&instance, STRUCT1).await; + let item = get(&instance, 0).await; + + assert_eq!(item, STRUCT1); + + let len_after_push = len(&instance).await; + assert_eq!(len_after_push, 1); + } + + #[tokio::test] + async fn can_pop() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, STRUCT1).await; + let len_before_pop = len(&instance).await; + assert_eq!(len_before_pop, 1); + + let item = pop(&instance).await; + assert_eq!(item, STRUCT1); + + let len_after_pop = len(&instance).await; + assert_eq!(len_after_pop, 0); + } + + #[tokio::test] + async fn can_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, STRUCT1).await; + push(&instance, STRUCT2).await; + push(&instance, STRUCT3).await; + push(&instance, STRUCT4).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(STRUCT1, get(&instance, 0).await); + assert_eq!(STRUCT2, get(&instance, 1).await); + assert_eq!(STRUCT3, get(&instance, 2).await); + assert_eq!(STRUCT4, get(&instance, 3).await); + + let item = remove(&instance, 2).await; + assert_eq!(item, STRUCT3); + + assert_eq!(STRUCT1, get(&instance, 0).await); + assert_eq!(STRUCT2, get(&instance, 1).await); + assert_eq!(STRUCT4, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, STRUCT1).await; + push(&instance, STRUCT2).await; + push(&instance, STRUCT3).await; + push(&instance, STRUCT4).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(STRUCT1, get(&instance, 0).await); + assert_eq!(STRUCT2, get(&instance, 1).await); + assert_eq!(STRUCT3, get(&instance, 2).await); + assert_eq!(STRUCT4, get(&instance, 3).await); + + let item = swap_remove(&instance, 1).await; + assert_eq!(item, STRUCT2); + + assert_eq!(STRUCT1, get(&instance, 0).await); + assert_eq!(STRUCT4, get(&instance, 1).await); + assert_eq!(STRUCT3, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_insert() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, STRUCT1).await; + push(&instance, STRUCT2).await; + push(&instance, STRUCT3).await; + push(&instance, STRUCT4).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(STRUCT1, get(&instance, 0).await); + assert_eq!(STRUCT2, get(&instance, 1).await); + assert_eq!(STRUCT3, get(&instance, 2).await); + assert_eq!(STRUCT4, get(&instance, 3).await); + + insert(&instance, 1, STRUCT5).await; + + assert_eq!(STRUCT1, get(&instance, 0).await); + assert_eq!(STRUCT5, get(&instance, 1).await); + assert_eq!(STRUCT2, get(&instance, 2).await); + assert_eq!(STRUCT3, get(&instance, 3).await); + assert_eq!(STRUCT4, get(&instance, 4).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_get_len() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, STRUCT1).await; + push(&instance, STRUCT2).await; + push(&instance, STRUCT3).await; + push(&instance, STRUCT4).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + push(&instance, STRUCT4).await; + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_confirm_emptiness() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, STRUCT1).await; + push(&instance, STRUCT2).await; + push(&instance, STRUCT3).await; + push(&instance, STRUCT4).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } + + #[tokio::test] + async fn can_clear() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, STRUCT1).await; + push(&instance, STRUCT2).await; + push(&instance, STRUCT3).await; + push(&instance, STRUCT4).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } +} + +// Some of these are meant to be tests for None returns but since the SDK doesnt support options; +// the options are being unwrapped in the contract and tested as reverts instead +mod failure { + use super::*; + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_get() { + let (instance, _id) = get_contract_instance().await; + + get(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_pop() { + let (instance, _id) = get_contract_instance().await; + + pop(&instance).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = swap_remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_insert() { + let (instance, _id) = get_contract_instance().await; + + insert(&instance, 1, STRUCT5).await; + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/struct/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/struct/utils.rs new file mode 100644 index 00000000000..3ee2b2a463d --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/struct/utils.rs @@ -0,0 +1,70 @@ +use fuels::{prelude::*, tx::ContractId}; +// Load abi from json +abigen!( + MyContract, + "test_artifacts/storage_vec/svec_struct/out/debug/svec_struct-abi.json" +); + +pub mod setup { + use super::*; + + pub async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "test_artifacts/storage_vec/svec_struct/out/debug/svec_struct.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(Some( + "test_artifacts/storage_vec/svec_struct/out/debug/svec_struct-storage_slots.json".to_string(), + )), + ) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) + } +} + +pub mod wrappers { + use super::*; + + pub async fn push(instance: &MyContract, value: TestStruct) { + instance.struct_push(value).call().await.unwrap(); + } + + pub async fn get(instance: &MyContract, index: u64) -> TestStruct { + instance.struct_get(index).call().await.unwrap().value + } + + pub async fn pop(instance: &MyContract) -> TestStruct { + instance.struct_pop().call().await.unwrap().value + } + + pub async fn remove(instance: &MyContract, index: u64) -> TestStruct { + instance.struct_remove(index).call().await.unwrap().value + } + + pub async fn swap_remove(instance: &MyContract, index: u64) -> TestStruct { + instance.struct_swap_remove(index).call().await.unwrap().value + } + + pub async fn insert(instance: &MyContract, index: u64, value: TestStruct) { + instance.struct_insert(index, value).call().await.unwrap(); + } + + pub async fn len(instance: &MyContract) -> u64 { + instance.struct_len().call().await.unwrap().value + } + + pub async fn is_empty(instance: &MyContract) -> bool { + instance.struct_is_empty().call().await.unwrap().value + } + + pub async fn clear(instance: &MyContract) { + instance.struct_clear().call().await.unwrap(); + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/u16/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u16/mod.rs new file mode 100644 index 00000000000..c92b3485bf2 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/u16/mod.rs @@ -0,0 +1,257 @@ +mod utils; + +use utils::{ + setup::get_contract_instance, + wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, +}; + +// TODO: Replace many of the get calls with direct storage values +// once the SDK supports that + +mod success { + use super::*; + + #[tokio::test] + async fn can_get() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + let item = get(&instance, 0).await; + + assert_eq!(item, 50); + } + + #[tokio::test] + async fn can_push() { + let (instance, _id) = get_contract_instance().await; + + let len_before_push = len(&instance).await; + assert_eq!(len_before_push, 0); + + push(&instance, 50).await; + let item = get(&instance, 0).await; + + assert_eq!(item, 50); + + let len_after_push = len(&instance).await; + assert_eq!(len_after_push, 1); + } + + #[tokio::test] + async fn can_pop() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + let len_before_pop = len(&instance).await; + assert_eq!(len_before_pop, 1); + + let item = pop(&instance).await; + assert_eq!(item, 50); + + let len_after_pop = len(&instance).await; + assert_eq!(len_after_pop, 0); + } + + #[tokio::test] + async fn can_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + assert_eq!(200, get(&instance, 3).await); + + let item = remove(&instance, 2).await; + assert_eq!(item, 150); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(200, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + assert_eq!(200, get(&instance, 3).await); + + let item = swap_remove(&instance, 1).await; + assert_eq!(item, 100); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(200, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_insert() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + assert_eq!(200, get(&instance, 3).await); + + insert(&instance, 1, 250).await; + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(250, get(&instance, 1).await); + assert_eq!(100, get(&instance, 2).await); + assert_eq!(150, get(&instance, 3).await); + assert_eq!(200, get(&instance, 4).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_get_len() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + push(&instance, 200).await; + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_confirm_emptiness() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } + + #[tokio::test] + async fn can_clear() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } +} + +// Some of these are meant to be tests for None returns but since the SDK doesnt support options; +// the options are being unwrapped in the contract and tested as reverts instead +mod failure { + use super::*; + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_get() { + let (instance, _id) = get_contract_instance().await; + + get(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_pop() { + let (instance, _id) = get_contract_instance().await; + + pop(&instance).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = swap_remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_insert() { + let (instance, _id) = get_contract_instance().await; + + insert(&instance, 1, 250).await; + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/u16/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/u16/utils.rs new file mode 100644 index 00000000000..da8723280a1 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/u16/utils.rs @@ -0,0 +1,70 @@ +use fuels::{prelude::*, tx::ContractId}; +// Load abi from json +abigen!( + MyContract, + "test_artifacts/storage_vec/svec_u16/out/debug/svec_u16-abi.json" +); + +pub mod setup { + use super::*; + + pub async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "test_artifacts/storage_vec/svec_u16/out/debug/svec_u16.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(Some( + "test_artifacts/storage_vec/svec_u16/out/debug/svec_u16-storage_slots.json".to_string(), + )), + ) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) + } +} + +pub mod wrappers { + use super::*; + + pub async fn push(instance: &MyContract, value: u16) { + instance.u16_push(value).call().await.unwrap(); + } + + pub async fn get(instance: &MyContract, index: u64) -> u16 { + instance.u16_get(index).call().await.unwrap().value + } + + pub async fn pop(instance: &MyContract) -> u16 { + instance.u16_pop().call().await.unwrap().value + } + + pub async fn remove(instance: &MyContract, index: u64) -> u16 { + instance.u16_remove(index).call().await.unwrap().value + } + + pub async fn swap_remove(instance: &MyContract, index: u64) -> u16 { + instance.u16_swap_remove(index).call().await.unwrap().value + } + + pub async fn insert(instance: &MyContract, index: u64, value: u16) { + instance.u16_insert(index, value).call().await.unwrap(); + } + + pub async fn len(instance: &MyContract) -> u64 { + instance.u16_len().call().await.unwrap().value + } + + pub async fn is_empty(instance: &MyContract) -> bool { + instance.u16_is_empty().call().await.unwrap().value + } + + pub async fn clear(instance: &MyContract) { + instance.u16_clear().call().await.unwrap(); + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/u32/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u32/mod.rs new file mode 100644 index 00000000000..c92b3485bf2 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/u32/mod.rs @@ -0,0 +1,257 @@ +mod utils; + +use utils::{ + setup::get_contract_instance, + wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, +}; + +// TODO: Replace many of the get calls with direct storage values +// once the SDK supports that + +mod success { + use super::*; + + #[tokio::test] + async fn can_get() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + let item = get(&instance, 0).await; + + assert_eq!(item, 50); + } + + #[tokio::test] + async fn can_push() { + let (instance, _id) = get_contract_instance().await; + + let len_before_push = len(&instance).await; + assert_eq!(len_before_push, 0); + + push(&instance, 50).await; + let item = get(&instance, 0).await; + + assert_eq!(item, 50); + + let len_after_push = len(&instance).await; + assert_eq!(len_after_push, 1); + } + + #[tokio::test] + async fn can_pop() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + let len_before_pop = len(&instance).await; + assert_eq!(len_before_pop, 1); + + let item = pop(&instance).await; + assert_eq!(item, 50); + + let len_after_pop = len(&instance).await; + assert_eq!(len_after_pop, 0); + } + + #[tokio::test] + async fn can_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + assert_eq!(200, get(&instance, 3).await); + + let item = remove(&instance, 2).await; + assert_eq!(item, 150); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(200, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + assert_eq!(200, get(&instance, 3).await); + + let item = swap_remove(&instance, 1).await; + assert_eq!(item, 100); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(200, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_insert() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + assert_eq!(200, get(&instance, 3).await); + + insert(&instance, 1, 250).await; + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(250, get(&instance, 1).await); + assert_eq!(100, get(&instance, 2).await); + assert_eq!(150, get(&instance, 3).await); + assert_eq!(200, get(&instance, 4).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_get_len() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + push(&instance, 200).await; + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_confirm_emptiness() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } + + #[tokio::test] + async fn can_clear() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } +} + +// Some of these are meant to be tests for None returns but since the SDK doesnt support options; +// the options are being unwrapped in the contract and tested as reverts instead +mod failure { + use super::*; + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_get() { + let (instance, _id) = get_contract_instance().await; + + get(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_pop() { + let (instance, _id) = get_contract_instance().await; + + pop(&instance).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = swap_remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_insert() { + let (instance, _id) = get_contract_instance().await; + + insert(&instance, 1, 250).await; + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/u32/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/u32/utils.rs new file mode 100644 index 00000000000..0a69220e449 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/u32/utils.rs @@ -0,0 +1,70 @@ +use fuels::{prelude::*, tx::ContractId}; +// Load abi from json +abigen!( + MyContract, + "test_artifacts/storage_vec/svec_u32/out/debug/svec_u32-abi.json" +); + +pub mod setup { + use super::*; + + pub async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "test_artifacts/storage_vec/svec_u32/out/debug/svec_u32.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(Some( + "test_artifacts/storage_vec/svec_u32/out/debug/svec_u32-storage_slots.json".to_string(), + )), + ) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) + } +} + +pub mod wrappers { + use super::*; + + pub async fn push(instance: &MyContract, value: u32) { + instance.u32_push(value).call().await.unwrap(); + } + + pub async fn get(instance: &MyContract, index: u64) -> u32 { + instance.u32_get(index).call().await.unwrap().value + } + + pub async fn pop(instance: &MyContract) -> u32 { + instance.u32_pop().call().await.unwrap().value + } + + pub async fn remove(instance: &MyContract, index: u64) -> u32 { + instance.u32_remove(index).call().await.unwrap().value + } + + pub async fn swap_remove(instance: &MyContract, index: u64) -> u32 { + instance.u32_swap_remove(index).call().await.unwrap().value + } + + pub async fn insert(instance: &MyContract, index: u64, value: u32) { + instance.u32_insert(index, value).call().await.unwrap(); + } + + pub async fn len(instance: &MyContract) -> u64 { + instance.u32_len().call().await.unwrap().value + } + + pub async fn is_empty(instance: &MyContract) -> bool { + instance.u32_is_empty().call().await.unwrap().value + } + + pub async fn clear(instance: &MyContract) { + instance.u32_clear().call().await.unwrap(); + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/u64/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u64/mod.rs new file mode 100644 index 00000000000..c92b3485bf2 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/u64/mod.rs @@ -0,0 +1,257 @@ +mod utils; + +use utils::{ + setup::get_contract_instance, + wrappers::{clear, get, insert, is_empty, len, pop, push, remove, swap_remove}, +}; + +// TODO: Replace many of the get calls with direct storage values +// once the SDK supports that + +mod success { + use super::*; + + #[tokio::test] + async fn can_get() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + let item = get(&instance, 0).await; + + assert_eq!(item, 50); + } + + #[tokio::test] + async fn can_push() { + let (instance, _id) = get_contract_instance().await; + + let len_before_push = len(&instance).await; + assert_eq!(len_before_push, 0); + + push(&instance, 50).await; + let item = get(&instance, 0).await; + + assert_eq!(item, 50); + + let len_after_push = len(&instance).await; + assert_eq!(len_after_push, 1); + } + + #[tokio::test] + async fn can_pop() { + let (instance, _id) = get_contract_instance().await; + + push(&instance, 50).await; + let len_before_pop = len(&instance).await; + assert_eq!(len_before_pop, 1); + + let item = pop(&instance).await; + assert_eq!(item, 50); + + let len_after_pop = len(&instance).await; + assert_eq!(len_after_pop, 0); + } + + #[tokio::test] + async fn can_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + assert_eq!(200, get(&instance, 3).await); + + let item = remove(&instance, 2).await; + assert_eq!(item, 150); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(200, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + assert_eq!(200, get(&instance, 3).await); + + let item = swap_remove(&instance, 1).await; + assert_eq!(item, 100); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(200, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 3); + } + + #[tokio::test] + async fn can_insert() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(100, get(&instance, 1).await); + assert_eq!(150, get(&instance, 2).await); + assert_eq!(200, get(&instance, 3).await); + + insert(&instance, 1, 250).await; + + assert_eq!(50, get(&instance, 0).await); + assert_eq!(250, get(&instance, 1).await); + assert_eq!(100, get(&instance, 2).await); + assert_eq!(150, get(&instance, 3).await); + assert_eq!(200, get(&instance, 4).await); + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_get_len() { + let (instance, _id) = get_contract_instance().await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 0); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let len_vec = len(&instance).await; + assert_eq!(len_vec, 4); + + push(&instance, 200).await; + let len_vec = len(&instance).await; + + assert_eq!(len_vec, 5); + } + + #[tokio::test] + async fn can_confirm_emptiness() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } + + #[tokio::test] + async fn can_clear() { + let (instance, _id) = get_contract_instance().await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + + push(&instance, 50).await; + push(&instance, 100).await; + push(&instance, 150).await; + push(&instance, 200).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, false); + + clear(&instance).await; + + let isempty = is_empty(&instance).await; + assert_eq!(isempty, true); + } +} + +// Some of these are meant to be tests for None returns but since the SDK doesnt support options; +// the options are being unwrapped in the contract and tested as reverts instead +mod failure { + use super::*; + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_get() { + let (instance, _id) = get_contract_instance().await; + + get(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_pop() { + let (instance, _id) = get_contract_instance().await; + + pop(&instance).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_swap_remove() { + let (instance, _id) = get_contract_instance().await; + + let _ = swap_remove(&instance, 0).await; + } + + #[tokio::test] + #[should_panic(expected = "Revert(0)")] + async fn cant_insert() { + let (instance, _id) = get_contract_instance().await; + + insert(&instance, 1, 250).await; + } +} diff --git a/test/src/sdk-harness/test_projects/storage_vec/u64/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/u64/utils.rs new file mode 100644 index 00000000000..f76574392a1 --- /dev/null +++ b/test/src/sdk-harness/test_projects/storage_vec/u64/utils.rs @@ -0,0 +1,70 @@ +use fuels::{prelude::*, tx::ContractId}; +// Load abi from json +abigen!( + MyContract, + "test_artifacts/storage_vec/svec_u64/out/debug/svec_u64-abi.json" +); + +pub mod setup { + use super::*; + + pub async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "test_artifacts/storage_vec/svec_u64/out/debug/svec_u64.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(Some( + "test_artifacts/storage_vec/svec_u64/out/debug/svec_u64-storage_slots.json".to_string(), + )), + ) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) + } +} + +pub mod wrappers { + use super::*; + + pub async fn push(instance: &MyContract, value: u64) { + instance.u64_push(value).call().await.unwrap(); + } + + pub async fn get(instance: &MyContract, index: u64) -> u64 { + instance.u64_get(index).call().await.unwrap().value + } + + pub async fn pop(instance: &MyContract) -> u64 { + instance.u64_pop().call().await.unwrap().value + } + + pub async fn remove(instance: &MyContract, index: u64) -> u64 { + instance.u64_remove(index).call().await.unwrap().value + } + + pub async fn swap_remove(instance: &MyContract, index: u64) -> u64 { + instance.u64_swap_remove(index).call().await.unwrap().value + } + + pub async fn insert(instance: &MyContract, index: u64, value: u64) { + instance.u64_insert(index, value).call().await.unwrap(); + } + + pub async fn len(instance: &MyContract) -> u64 { + instance.u64_len().call().await.unwrap().value + } + + pub async fn is_empty(instance: &MyContract) -> bool { + instance.u64_is_empty().call().await.unwrap().value + } + + pub async fn clear(instance: &MyContract) { + instance.u64_clear().call().await.unwrap(); + } +} From e2d1deb28e9bdde1fc578bf2a9e48b5bc0a9268f Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 13 Jul 2022 15:06:58 +0530 Subject: [PATCH 57/59] alphabetical order --- sway-lib-std/src/storage.sw | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index c1b0037e1ba..6bd9e565560 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -1,10 +1,11 @@ library r#storage; use ::assert::assert; +use ::context::registers::stack_ptr; use ::hash::sha256; use ::option::Option; use ::result::Result; -use ::context::registers::stack_ptr; + /// Store a stack variable in storage. #[storage(write)]pub fn store(key: b256, value: T) { From 01eb00a047975b24f7084c87b75853d502da31e8 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 13 Jul 2022 15:10:48 +0530 Subject: [PATCH 58/59] cargo fmt + changed the b256 consts --- .../test_projects/storage_vec/b256/mod.rs | 10 +++---- .../test_projects/storage_vec/b256/utils.rs | 3 ++- .../test_projects/storage_vec/bool/utils.rs | 3 ++- .../test_projects/storage_vec/enum/utils.rs | 3 ++- .../test_projects/storage_vec/mod.rs | 10 +++---- .../test_projects/storage_vec/str/utils.rs | 3 ++- .../test_projects/storage_vec/struct/mod.rs | 26 ++++--------------- .../test_projects/storage_vec/struct/utils.rs | 10 +++++-- .../test_projects/storage_vec/u16/utils.rs | 3 ++- .../test_projects/storage_vec/u32/utils.rs | 3 ++- .../test_projects/storage_vec/u64/utils.rs | 3 ++- .../test_projects/storage_vec/u8/utils.rs | 3 ++- 12 files changed, 39 insertions(+), 41 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/b256/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/b256/mod.rs index fe0639e9751..3ed375bc4e0 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/b256/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/b256/mod.rs @@ -8,11 +8,11 @@ use utils::{ // TODO: Replace many of the get calls with direct storage values // once the SDK supports that -const BYTES1: [u8; 32] = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]; -const BYTES2: [u8; 32] = [32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63]; -const BYTES3: [u8; 32] = [64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95]; -const BYTES4: [u8; 32] = [96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127]; -const BYTES5: [u8; 32] = [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159]; +const BYTES1: [u8; 32] = [1; 32]; +const BYTES2: [u8; 32] = [2; 32]; +const BYTES3: [u8; 32] = [3; 32]; +const BYTES4: [u8; 32] = [4; 32]; +const BYTES5: [u8; 32] = [5; 32]; mod success { use super::*; diff --git a/test/src/sdk-harness/test_projects/storage_vec/b256/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/b256/utils.rs index 854aaae235a..cb825715187 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/b256/utils.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/b256/utils.rs @@ -17,7 +17,8 @@ pub mod setup { &wallet, TxParameters::default(), StorageConfiguration::with_storage_path(Some( - "test_artifacts/storage_vec/svec_b256/out/debug/svec_b256-storage_slots.json".to_string(), + "test_artifacts/storage_vec/svec_b256/out/debug/svec_b256-storage_slots.json" + .to_string(), )), ) .await diff --git a/test/src/sdk-harness/test_projects/storage_vec/bool/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/bool/utils.rs index 1138b71d581..6ce6dbcf1f4 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/bool/utils.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/bool/utils.rs @@ -17,7 +17,8 @@ pub mod setup { &wallet, TxParameters::default(), StorageConfiguration::with_storage_path(Some( - "test_artifacts/storage_vec/svec_bool/out/debug/svec_bool-storage_slots.json".to_string(), + "test_artifacts/storage_vec/svec_bool/out/debug/svec_bool-storage_slots.json" + .to_string(), )), ) .await diff --git a/test/src/sdk-harness/test_projects/storage_vec/enum/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/enum/utils.rs index 54680e1e105..1ff5b442970 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/enum/utils.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/enum/utils.rs @@ -17,7 +17,8 @@ pub mod setup { &wallet, TxParameters::default(), StorageConfiguration::with_storage_path(Some( - "test_artifacts/storage_vec/svec_enum/out/debug/svec_enum-storage_slots.json".to_string(), + "test_artifacts/storage_vec/svec_enum/out/debug/svec_enum-storage_slots.json" + .to_string(), )), ) .await diff --git a/test/src/sdk-harness/test_projects/storage_vec/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/mod.rs index 2cd48fbce3e..5dcb56cf8a3 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/mod.rs @@ -1,9 +1,9 @@ -mod u8; -mod u16; -mod u32; -mod u64; mod b256; mod bool; +mod r#enum; mod str; mod r#struct; -mod r#enum; \ No newline at end of file +mod u16; +mod u32; +mod u64; +mod u8; diff --git a/test/src/sdk-harness/test_projects/storage_vec/str/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/str/utils.rs index a6aa96e6258..11d4f50174a 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/str/utils.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/str/utils.rs @@ -17,7 +17,8 @@ pub mod setup { &wallet, TxParameters::default(), StorageConfiguration::with_storage_path(Some( - "test_artifacts/storage_vec/svec_str/out/debug/svec_str-storage_slots.json".to_string(), + "test_artifacts/storage_vec/svec_str/out/debug/svec_str-storage_slots.json" + .to_string(), )), ) .await diff --git a/test/src/sdk-harness/test_projects/storage_vec/struct/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/struct/mod.rs index 84ae3fc8b2c..dbcef1362a7 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/struct/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/struct/mod.rs @@ -6,30 +6,14 @@ use utils::{ TestStruct, }; - // TODO: Replace many of the get calls with direct storage values // once the SDK supports that -const STRUCT1: TestStruct = TestStruct { - a: true, - b: 1, -}; -const STRUCT2: TestStruct = TestStruct { - a: false, - b: 2, -}; -const STRUCT3: TestStruct = TestStruct { - a: true, - b: 3, -}; -const STRUCT4: TestStruct = TestStruct { - a: false, - b: 4, -}; -const STRUCT5: TestStruct = TestStruct { - a: true, - b: 5, -}; +const STRUCT1: TestStruct = TestStruct { a: true, b: 1 }; +const STRUCT2: TestStruct = TestStruct { a: false, b: 2 }; +const STRUCT3: TestStruct = TestStruct { a: true, b: 3 }; +const STRUCT4: TestStruct = TestStruct { a: false, b: 4 }; +const STRUCT5: TestStruct = TestStruct { a: true, b: 5 }; mod success { use super::*; diff --git a/test/src/sdk-harness/test_projects/storage_vec/struct/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/struct/utils.rs index 3ee2b2a463d..b796c085860 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/struct/utils.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/struct/utils.rs @@ -17,7 +17,8 @@ pub mod setup { &wallet, TxParameters::default(), StorageConfiguration::with_storage_path(Some( - "test_artifacts/storage_vec/svec_struct/out/debug/svec_struct-storage_slots.json".to_string(), + "test_artifacts/storage_vec/svec_struct/out/debug/svec_struct-storage_slots.json" + .to_string(), )), ) .await @@ -49,7 +50,12 @@ pub mod wrappers { } pub async fn swap_remove(instance: &MyContract, index: u64) -> TestStruct { - instance.struct_swap_remove(index).call().await.unwrap().value + instance + .struct_swap_remove(index) + .call() + .await + .unwrap() + .value } pub async fn insert(instance: &MyContract, index: u64, value: TestStruct) { diff --git a/test/src/sdk-harness/test_projects/storage_vec/u16/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/u16/utils.rs index da8723280a1..8b5fb9179e8 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u16/utils.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u16/utils.rs @@ -17,7 +17,8 @@ pub mod setup { &wallet, TxParameters::default(), StorageConfiguration::with_storage_path(Some( - "test_artifacts/storage_vec/svec_u16/out/debug/svec_u16-storage_slots.json".to_string(), + "test_artifacts/storage_vec/svec_u16/out/debug/svec_u16-storage_slots.json" + .to_string(), )), ) .await diff --git a/test/src/sdk-harness/test_projects/storage_vec/u32/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/u32/utils.rs index 0a69220e449..3e762215989 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u32/utils.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u32/utils.rs @@ -17,7 +17,8 @@ pub mod setup { &wallet, TxParameters::default(), StorageConfiguration::with_storage_path(Some( - "test_artifacts/storage_vec/svec_u32/out/debug/svec_u32-storage_slots.json".to_string(), + "test_artifacts/storage_vec/svec_u32/out/debug/svec_u32-storage_slots.json" + .to_string(), )), ) .await diff --git a/test/src/sdk-harness/test_projects/storage_vec/u64/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/u64/utils.rs index f76574392a1..18d3db04eee 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u64/utils.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u64/utils.rs @@ -17,7 +17,8 @@ pub mod setup { &wallet, TxParameters::default(), StorageConfiguration::with_storage_path(Some( - "test_artifacts/storage_vec/svec_u64/out/debug/svec_u64-storage_slots.json".to_string(), + "test_artifacts/storage_vec/svec_u64/out/debug/svec_u64-storage_slots.json" + .to_string(), )), ) .await diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs index 41f4bcc1a06..5ad1a3e74c8 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/utils.rs @@ -17,7 +17,8 @@ pub mod setup { &wallet, TxParameters::default(), StorageConfiguration::with_storage_path(Some( - "test_artifacts/storage_vec/svec_u8/out/debug/svec_u8-storage_slots.json".to_string(), + "test_artifacts/storage_vec/svec_u8/out/debug/svec_u8-storage_slots.json" + .to_string(), )), ) .await From 7468ad60489326e6ecd42ac23263bdb59a72c135 Mon Sep 17 00:00:00 2001 From: SwayStar123 Date: Wed, 13 Jul 2022 15:13:43 +0530 Subject: [PATCH 59/59] removed unncessary len checks --- .../sdk-harness/test_projects/storage_vec/b256/mod.rs | 9 --------- .../sdk-harness/test_projects/storage_vec/bool/mod.rs | 9 --------- .../sdk-harness/test_projects/storage_vec/enum/mod.rs | 9 --------- .../src/sdk-harness/test_projects/storage_vec/str/mod.rs | 9 --------- .../sdk-harness/test_projects/storage_vec/struct/mod.rs | 9 --------- .../src/sdk-harness/test_projects/storage_vec/u16/mod.rs | 9 --------- .../src/sdk-harness/test_projects/storage_vec/u32/mod.rs | 9 --------- .../src/sdk-harness/test_projects/storage_vec/u64/mod.rs | 9 --------- test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs | 9 --------- 9 files changed, 81 deletions(-) diff --git a/test/src/sdk-harness/test_projects/storage_vec/b256/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/b256/mod.rs index 3ed375bc4e0..78a744a3ac8 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/b256/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/b256/mod.rs @@ -62,9 +62,6 @@ mod success { async fn can_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, BYTES1).await; push(&instance, BYTES2).await; push(&instance, BYTES3).await; @@ -93,9 +90,6 @@ mod success { async fn can_swap_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, BYTES1).await; push(&instance, BYTES2).await; push(&instance, BYTES3).await; @@ -124,9 +118,6 @@ mod success { async fn can_insert() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, BYTES1).await; push(&instance, BYTES2).await; push(&instance, BYTES3).await; diff --git a/test/src/sdk-harness/test_projects/storage_vec/bool/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/bool/mod.rs index 8bab7368f29..8ccf82a8e3f 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/bool/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/bool/mod.rs @@ -56,9 +56,6 @@ mod success { async fn can_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, true).await; push(&instance, false).await; push(&instance, true).await; @@ -87,9 +84,6 @@ mod success { async fn can_swap_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, true).await; push(&instance, false).await; push(&instance, true).await; @@ -118,9 +112,6 @@ mod success { async fn can_insert() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, true).await; push(&instance, false).await; push(&instance, true).await; diff --git a/test/src/sdk-harness/test_projects/storage_vec/enum/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/enum/mod.rs index f1fa8505d92..d178e18463c 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/enum/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/enum/mod.rs @@ -63,9 +63,6 @@ mod success { async fn can_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, ENUM1).await; push(&instance, ENUM2).await; push(&instance, ENUM3).await; @@ -94,9 +91,6 @@ mod success { async fn can_swap_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, ENUM1).await; push(&instance, ENUM2).await; push(&instance, ENUM3).await; @@ -125,9 +119,6 @@ mod success { async fn can_insert() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, ENUM1).await; push(&instance, ENUM2).await; push(&instance, ENUM3).await; diff --git a/test/src/sdk-harness/test_projects/storage_vec/str/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/str/mod.rs index 2f4b398fb27..d40df2495c9 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/str/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/str/mod.rs @@ -56,9 +56,6 @@ mod success { async fn can_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, String::from("0050")).await; push(&instance, String::from("0100")).await; push(&instance, String::from("0150")).await; @@ -87,9 +84,6 @@ mod success { async fn can_swap_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, String::from("0050")).await; push(&instance, String::from("0100")).await; push(&instance, String::from("0150")).await; @@ -118,9 +112,6 @@ mod success { async fn can_insert() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, String::from("0050")).await; push(&instance, String::from("0100")).await; push(&instance, String::from("0150")).await; diff --git a/test/src/sdk-harness/test_projects/storage_vec/struct/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/struct/mod.rs index dbcef1362a7..746f49d94b6 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/struct/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/struct/mod.rs @@ -63,9 +63,6 @@ mod success { async fn can_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, STRUCT1).await; push(&instance, STRUCT2).await; push(&instance, STRUCT3).await; @@ -94,9 +91,6 @@ mod success { async fn can_swap_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, STRUCT1).await; push(&instance, STRUCT2).await; push(&instance, STRUCT3).await; @@ -125,9 +119,6 @@ mod success { async fn can_insert() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, STRUCT1).await; push(&instance, STRUCT2).await; push(&instance, STRUCT3).await; diff --git a/test/src/sdk-harness/test_projects/storage_vec/u16/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u16/mod.rs index c92b3485bf2..58b6a9f33d4 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u16/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u16/mod.rs @@ -56,9 +56,6 @@ mod success { async fn can_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; @@ -87,9 +84,6 @@ mod success { async fn can_swap_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; @@ -118,9 +112,6 @@ mod success { async fn can_insert() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; diff --git a/test/src/sdk-harness/test_projects/storage_vec/u32/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u32/mod.rs index c92b3485bf2..58b6a9f33d4 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u32/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u32/mod.rs @@ -56,9 +56,6 @@ mod success { async fn can_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; @@ -87,9 +84,6 @@ mod success { async fn can_swap_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; @@ -118,9 +112,6 @@ mod success { async fn can_insert() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; diff --git a/test/src/sdk-harness/test_projects/storage_vec/u64/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u64/mod.rs index c92b3485bf2..58b6a9f33d4 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u64/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u64/mod.rs @@ -56,9 +56,6 @@ mod success { async fn can_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; @@ -87,9 +84,6 @@ mod success { async fn can_swap_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; @@ -118,9 +112,6 @@ mod success { async fn can_insert() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; diff --git a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs index c92b3485bf2..58b6a9f33d4 100644 --- a/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_vec/u8/mod.rs @@ -56,9 +56,6 @@ mod success { async fn can_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; @@ -87,9 +84,6 @@ mod success { async fn can_swap_remove() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await; @@ -118,9 +112,6 @@ mod success { async fn can_insert() { let (instance, _id) = get_contract_instance().await; - let len_vec = len(&instance).await; - assert_eq!(len_vec, 0); - push(&instance, 50).await; push(&instance, 100).await; push(&instance, 150).await;