From 96e9d968cc1f683370eccdef8f5c9424812f6a02 Mon Sep 17 00:00:00 2001 From: bytedeveloperr Date: Thu, 9 Mar 2023 22:25:35 +0100 Subject: [PATCH 1/3] [move-stdlib] add struct tag module --- language/move-stdlib/docs/overview.md | 1 + language/move-stdlib/docs/struct_tag.md | 196 ++++++++++++++++++ language/move-stdlib/sources/struct_tag.move | 53 +++++ language/move-stdlib/src/natives/mod.rs | 9 + .../move-stdlib/src/natives/struct_tag.rs | 92 ++++++++ .../move-stdlib/tests/struct_tag_tests.move | 154 ++++++++++++++ 6 files changed, 505 insertions(+) create mode 100644 language/move-stdlib/docs/struct_tag.md create mode 100644 language/move-stdlib/sources/struct_tag.move create mode 100644 language/move-stdlib/src/natives/struct_tag.rs create mode 100644 language/move-stdlib/tests/struct_tag_tests.move diff --git a/language/move-stdlib/docs/overview.md b/language/move-stdlib/docs/overview.md index e8aff3f041..72b6def118 100644 --- a/language/move-stdlib/docs/overview.md +++ b/language/move-stdlib/docs/overview.md @@ -21,6 +21,7 @@ This is the root document for the Move stdlib module documentation. The Move std - [`0x1::option`](option.md#0x1_option) - [`0x1::signer`](signer.md#0x1_signer) - [`0x1::string`](string.md#0x1_string) +- [`0x1::struct_tag`](struct_tag.md#0x1_struct_tag) - [`0x1::type_name`](type_name.md#0x1_type_name) - [`0x1::vector`](vector.md#0x1_vector) diff --git a/language/move-stdlib/docs/struct_tag.md b/language/move-stdlib/docs/struct_tag.md new file mode 100644 index 0000000000..fb2712aa6c --- /dev/null +++ b/language/move-stdlib/docs/struct_tag.md @@ -0,0 +1,196 @@ + + + +# Module `0x1::struct_tag` + +Module to decompose a move struct into it's components. + + +- [Struct `StructTag`](#0x1_struct_tag_StructTag) +- [Function `get`](#0x1_struct_tag_get) +- [Function `package_address`](#0x1_struct_tag_package_address) +- [Function `module_name`](#0x1_struct_tag_module_name) +- [Function `struct_name`](#0x1_struct_tag_struct_name) +- [Function `generics`](#0x1_struct_tag_generics) + + +
use 0x1::ascii;
+
+ + + + + +## Struct `StructTag` + + + +
struct StructTag has copy, drop, store
+
+ + + +
+Fields + + +
+
+package_address: address +
+
+ Address of the package that the struct belongs to. + taking 00000000000000000000000000000001::option::Option<u64> for example, + it's package address will be 00000000000000000000000000000001 +
+
+module_name: ascii::String +
+
+ the name of the module where the struct is defined. + using the example struct above the module name should be option +
+
+struct_name: ascii::String +
+
+ the name of the struct itself. + using the example struct above the module name should be Option +
+
+generics: vector<ascii::String> +
+
+ the generics or tyepe params of the struct. + using the example struct above the module name should be vector[u64] +
+
+ + +
+ + + +## Function `get` + +Return the tag of the struct of type T + + +
public fun get<T>(): struct_tag::StructTag
+
+ + + +
+Implementation + + +
public native fun get<T>(): StructTag;
+
+ + + +
+ + + +## Function `package_address` + +Returns the package address of self + + +
public fun package_address(self: struct_tag::StructTag): address
+
+ + + +
+Implementation + + +
public fun package_address(self: StructTag): address {
+    self.package_address
+}
+
+ + + +
+ + + +## Function `module_name` + +Returns the module name of self + + +
public fun module_name(self: struct_tag::StructTag): ascii::String
+
+ + + +
+Implementation + + +
public fun module_name(self: StructTag): String {
+    self.module_name
+}
+
+ + + +
+ + + +## Function `struct_name` + +Returns the struct name of self + + +
public fun struct_name(self: struct_tag::StructTag): ascii::String
+
+ + + +
+Implementation + + +
public fun struct_name(self: StructTag): String {
+    self.struct_name
+}
+
+ + + +
+ + + +## Function `generics` + +Returns the generics of self + + +
public fun generics(self: struct_tag::StructTag): vector<ascii::String>
+
+ + + +
+Implementation + + +
public fun generics(self: StructTag): vector<String> {
+    self.generics
+}
+
+ + + +
+ + +[//]: # ("File containing references which can be used from documentation") diff --git a/language/move-stdlib/sources/struct_tag.move b/language/move-stdlib/sources/struct_tag.move new file mode 100644 index 0000000000..e7b5f81529 --- /dev/null +++ b/language/move-stdlib/sources/struct_tag.move @@ -0,0 +1,53 @@ +/// Module to decompose a move struct into it's components. +module std::struct_tag { + use std::ascii::String; + + struct StructTag has copy, store, drop { + /// Address of the package that the struct belongs to. + /// taking `00000000000000000000000000000001::option::Option` for example, + /// it's package address will be `00000000000000000000000000000001` + package_address: address, + /// the name of the module where the struct is defined. + /// using the example struct above the module name should be `option` + module_name: String, + /// the name of the struct itself. + /// using the example struct above the module name should be `Option` + struct_name: String, + /// the generics or tyepe params of the struct. + /// using the example struct above the module name should be `vector[u64]` + generics: vector + } + + /// Return the tag of the struct of type `T` + public native fun get(): StructTag; + + /// Returns the package address of `self` + public fun package_address(self: StructTag): address { + self.package_address + } + + /// Returns the module name of `self` + public fun module_name(self: StructTag): String { + self.module_name + } + + /// Returns the struct name of `self` + public fun struct_name(self: StructTag): String { + self.struct_name + } + + /// Returns the generics of `self` + public fun generics(self: StructTag): vector { + self.generics + } + + #[test_only] + public fun new_for_testing(package_address: address, module_name: String, struct_name: String, generics: vector): StructTag { + StructTag { + package_address, + module_name, + struct_name, + generics + } + } +} \ No newline at end of file diff --git a/language/move-stdlib/src/natives/mod.rs b/language/move-stdlib/src/natives/mod.rs index fe97636884..910a4b3c9e 100644 --- a/language/move-stdlib/src/natives/mod.rs +++ b/language/move-stdlib/src/natives/mod.rs @@ -8,6 +8,7 @@ pub mod event; pub mod hash; pub mod signer; pub mod string; +pub mod struct_tag; pub mod type_name; #[cfg(feature = "testing")] pub mod unit_test; @@ -26,6 +27,7 @@ pub struct GasParameters { pub string: string::GasParameters, pub type_name: type_name::GasParameters, pub vector: vector::GasParameters, + pub struct_tag: struct_tag::GasParameters, #[cfg(feature = "testing")] pub unit_test: unit_test::GasParameters, @@ -91,6 +93,12 @@ impl GasParameters { destroy_empty: vector::DestroyEmptyGasParameters { base: 0.into() }, swap: vector::SwapGasParameters { base: 0.into() }, }, + struct_tag: struct_tag::GasParameters { + get: struct_tag::GetGasParameters { + base: 0.into(), + per_byte: 0.into(), + }, + }, #[cfg(feature = "testing")] unit_test: unit_test::GasParameters { create_signers_for_testing: unit_test::CreateSignersForTestingGasParameters { @@ -122,6 +130,7 @@ pub fn all_natives( add_natives!("string", string::make_all(gas_params.string)); add_natives!("type_name", type_name::make_all(gas_params.type_name)); add_natives!("vector", vector::make_all(gas_params.vector)); + add_natives!("struct_tag", struct_tag::make_all(gas_params.struct_tag)); #[cfg(feature = "testing")] { add_natives!("unit_test", unit_test::make_all(gas_params.unit_test)); diff --git a/language/move-stdlib/src/natives/struct_tag.rs b/language/move-stdlib/src/natives/struct_tag.rs new file mode 100644 index 0000000000..cf6e9943fa --- /dev/null +++ b/language/move-stdlib/src/natives/struct_tag.rs @@ -0,0 +1,92 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use move_binary_format::errors::PartialVMResult; +use move_core_types::{ + gas_algebra::{InternalGas, InternalGasPerByte, NumBytes}, + language_storage::TypeTag, +}; +use move_vm_runtime::native_functions::{NativeContext, NativeFunction}; +use move_vm_types::{ + loaded_data::runtime_types::Type, + natives::function::NativeResult, + values::{Struct, Value}, +}; + +use smallvec::smallvec; +use std::{collections::VecDeque, sync::Arc}; + +#[derive(Debug, Clone)] +pub struct GetGasParameters { + pub base: InternalGas, + pub per_byte: InternalGasPerByte, +} + +fn native_get( + gas_params: &GetGasParameters, + context: &mut NativeContext, + ty_args: Vec, + arguments: VecDeque, +) -> PartialVMResult { + debug_assert!(ty_args.len() == 1); + debug_assert!(arguments.is_empty()); + + let type_tag = context.type_to_type_tag(&ty_args[0])?; + let type_name = type_tag.to_canonical_string(); + + let mut cost = gas_params.base; + + if let TypeTag::Struct(tag) = type_tag { + let address = Value::address(tag.address); + + // make std::ascii::String for the module name + let module = Value::struct_(Struct::pack(vec![Value::vector_u8( + tag.module.into_bytes(), + )])); + + // make std::ascii::String for the struct name + let name = Value::struct_(Struct::pack(vec![Value::vector_u8(tag.name.into_bytes())])); + + // make a vector of std::ascii::String for the generics + let generics_vec = tag + .type_params + .iter() + .map(|ty| { + Value::struct_(Struct::pack(vec![Value::vector_u8( + ty.to_canonical_string().into_bytes(), + )])) + }) + .collect::>(); + + // convert the generics vector into move supported value. + // using the `vector_for_testing_only` which can break as it's currently the easiest way to do this without altering the existing `Value` struct. + // it should the replaced when the proper API is ready. + let generics = Value::vector_for_testing_only(generics_vec); + + cost += gas_params.per_byte * NumBytes::new(type_name.len() as u64); + + Ok(NativeResult::ok( + cost, + smallvec![Value::struct_(Struct::pack(vec![ + address, module, name, generics + ]))], + )) + } else { + Ok(NativeResult::err(cost, 0)) + } +} + +pub fn make_native_get(gas_params: GetGasParameters) -> NativeFunction { + Arc::new(move |context, ty_args, args| native_get(&gas_params, context, ty_args, args)) +} + +#[derive(Debug, Clone)] +pub struct GasParameters { + pub get: GetGasParameters, +} + +pub fn make_all(gas_params: GasParameters) -> impl Iterator { + let natives = [("get", make_native_get(gas_params.get))]; + + crate::natives::helpers::make_module_natives(natives) +} diff --git a/language/move-stdlib/tests/struct_tag_tests.move b/language/move-stdlib/tests/struct_tag_tests.move new file mode 100644 index 0000000000..077b033c20 --- /dev/null +++ b/language/move-stdlib/tests/struct_tag_tests.move @@ -0,0 +1,154 @@ +#[test_only] +module std::struct_tag_tests { + use std::ascii::{Self, String}; + use std::option::{Option}; + use std::struct_tag; + + struct TestStruct has drop {} + struct TestStructGeneric1 has drop {} + struct TestStructGeneric2 has drop {} + struct TestStructGeneric3 has drop {} + + #[test] + fun test_plain_struct() { + assert!(struct_tag::get() == struct_tag::new_for_testing(@0x1, ascii::string(b"struct_tag_tests"), ascii::string(b"TestStruct"), vector[]), 0); + assert!(struct_tag::get() == struct_tag::new_for_testing(@0x1, ascii::string(b"ascii"), ascii::string(b"String"), vector[]), 0); + } + + #[test] + fun test_generic_struct() { + // testing withbasic single generic + let new_test_struct_1 = struct_tag::new_for_testing( + @0x1, + ascii::string(b"struct_tag_tests"), + ascii::string(b"TestStructGeneric1"), + vector[ascii::string(b"00000000000000000000000000000001::ascii::String")] + ); + + // testing with two generics + let new_test_struct_2_a = struct_tag::new_for_testing( + @0x1, + ascii::string(b"struct_tag_tests"), + ascii::string(b"TestStructGeneric2"), + vector[ + ascii::string(b"00000000000000000000000000000001::ascii::String"), + ascii::string(b"address") + ] + ); + + // testing with two generics with nested generic + let new_test_struct_2_b = struct_tag::new_for_testing( + @0x1, + ascii::string(b"struct_tag_tests"), + ascii::string(b"TestStructGeneric2"), + vector[ + ascii::string(b"00000000000000000000000000000001::ascii::String"), + ascii::string(b"00000000000000000000000000000001::option::Option") + ] + ); + + // testing with multiple(two or more) generics with nested generic + let new_test_struct_3_a = struct_tag::new_for_testing( + @0x1, + ascii::string(b"struct_tag_tests"), + ascii::string(b"TestStructGeneric3"), + vector[ + ascii::string(b"00000000000000000000000000000001::ascii::String"), + ascii::string(b"address"), + ascii::string(b"00000000000000000000000000000001::option::Option") + ] + ); + + // testing with multiple generics with nested two or more generics + let new_test_struct_3_b = struct_tag::new_for_testing( + @0x1, + ascii::string(b"struct_tag_tests"), + ascii::string(b"TestStructGeneric3"), + vector[ + ascii::string(b"00000000000000000000000000000001::ascii::String"), + ascii::string(b"address"), + ascii::string(b"00000000000000000000000000000001::struct_tag_tests::TestStructGeneric2<00000000000000000000000000000001::ascii::String,00000000000000000000000000000001::option::Option>") + ] + ); + + assert!(struct_tag::get>() == new_test_struct_1, 0); + assert!(struct_tag::get>() == new_test_struct_2_a, 0); + assert!(struct_tag::get>>() == new_test_struct_2_b, 0); + assert!(struct_tag::get>>() == new_test_struct_3_a, 0); + assert!(struct_tag::get>>>() == new_test_struct_3_b, 0); + } + + #[test] + #[expected_failure(abort_code = 0, location = std::struct_tag_tests)] + fun test_invalid_properties_failure() { + // supplying invalid address + let new_test_struct_1_a = struct_tag::new_for_testing( + @0x2, + ascii::string(b"struct_tag_tests"), + ascii::string(b"TestStructGeneric1"), + vector[ascii::string(b"00000000000000000000000000000001::ascii::String")] + ); + + // supplying invalid module name + let new_test_struct_1_b = struct_tag::new_for_testing( + @0x1, + ascii::string(b"fake_module_name"), + ascii::string(b"TestStructGeneric1"), + vector[ascii::string(b"00000000000000000000000000000001::ascii::String")] + ); + + // supplying invalid struct name + let new_test_struct_1_c = struct_tag::new_for_testing( + @0x1, + ascii::string(b"struct_tag_tests"), + ascii::string(b"TestStructGeneric"), + vector[ascii::string(b"00000000000000000000000000000001::ascii::String")] + ); + + // supplying invalid generic + let new_test_struct_1_d = struct_tag::new_for_testing( + @0x1, + ascii::string(b"fake_module_name"), + ascii::string(b"TestStructGeneric1"), + vector[ascii::string(b"00000000000000000000000000000001::string::String")] + ); + + // supplying incorrectly positioned generics + let new_test_struct_3_a = struct_tag::new_for_testing( + @0x1, + ascii::string(b"struct_tag_tests"), + ascii::string(b"TestStructGeneric3"), + vector[ + ascii::string(b"address"), + ascii::string(b"00000000000000000000000000000001::option::Option"), + ascii::string(b"00000000000000000000000000000001::ascii::String"), + ] + ); + + // supplying incomplete generics + let new_test_struct_3_b = struct_tag::new_for_testing( + @0x1, + ascii::string(b"struct_tag_tests"), + ascii::string(b"TestStructGeneric3"), + vector[ + ascii::string(b"00000000000000000000000000000001::ascii::String"), + ascii::string(b"00000000000000000000000000000001::struct_tag_tests::TestStructGeneric2<00000000000000000000000000000001::ascii::String,00000000000000000000000000000001::option::Option>") + ] + ); + + assert!(struct_tag::get>() == new_test_struct_1_a, 0); + assert!(struct_tag::get>() == new_test_struct_1_b, 0); + assert!(struct_tag::get>() == new_test_struct_1_c, 0); + assert!(struct_tag::get>() == new_test_struct_1_d, 0); + assert!(struct_tag::get>>() == new_test_struct_3_a, 0); + assert!(struct_tag::get>>>() == new_test_struct_3_b, 0); + } + + #[test] + #[expected_failure(abort_code = 0, location = std::struct_tag)] + fun test_invalid_struct_type_failure() { + // supplying type that is not a struct + struct_tag::get(); + struct_tag::get
(); + } +} From 0de2b30b598de83debac403a79fa66497b875cbc Mon Sep 17 00:00:00 2001 From: bytedeveloperr Date: Fri, 10 Mar 2023 08:35:09 +0100 Subject: [PATCH 2/3] [move-stdlib] add `module_authority` and `into` --- language/move-stdlib/sources/struct_tag.move | 48 ++++++++++--------- .../move-stdlib/tests/struct_tag_tests.move | 17 +++++++ 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/language/move-stdlib/sources/struct_tag.move b/language/move-stdlib/sources/struct_tag.move index e7b5f81529..557368b3c9 100644 --- a/language/move-stdlib/sources/struct_tag.move +++ b/language/move-stdlib/sources/struct_tag.move @@ -1,12 +1,12 @@ /// Module to decompose a move struct into it's components. module std::struct_tag { - use std::ascii::String; + use std::ascii::{Self, String}; struct StructTag has copy, store, drop { - /// Address of the package that the struct belongs to. + /// Address of the entity that the struct belongs to. /// taking `00000000000000000000000000000001::option::Option` for example, - /// it's package address will be `00000000000000000000000000000001` - package_address: address, + /// the address will be `00000000000000000000000000000001` + address_: address, /// the name of the module where the struct is defined. /// using the example struct above the module name should be `option` module_name: String, @@ -14,37 +14,39 @@ module std::struct_tag { /// using the example struct above the module name should be `Option` struct_name: String, /// the generics or tyepe params of the struct. - /// using the example struct above the module name should be `vector[u64]` + /// using the example struct above the module name should be `vector["u64"]` generics: vector } - /// Return the tag of the struct of type `T` + /// Returns the tag of the struct of type `T` public native fun get(): StructTag; - /// Returns the package address of `self` - public fun package_address(self: StructTag): address { - self.package_address + // Converts `self` into a tuple of it's inner values + public fun into(self: &StructTag): (address, String, String, vector) { + (self.address_, self.module_name, self.struct_name, self.generics) } - /// Returns the module name of `self` - public fun module_name(self: StructTag): String { - self.module_name - } - - /// Returns the struct name of `self` - public fun struct_name(self: StructTag): String { - self.struct_name - } + /// Returns the module authority for the struct of type `T` + public fun module_authority(): StructTag { + let StructTag { + address_, + module_name, + struct_name: _, + generics: _ + } = get(); - /// Returns the generics of `self` - public fun generics(self: StructTag): vector { - self.generics + StructTag { + address_, + module_name, + struct_name: ascii::string(b"Witness"), + generics: vector[] + } } #[test_only] - public fun new_for_testing(package_address: address, module_name: String, struct_name: String, generics: vector): StructTag { + public fun new_for_testing(address_: address, module_name: String, struct_name: String, generics: vector): StructTag { StructTag { - package_address, + address_, module_name, struct_name, generics diff --git a/language/move-stdlib/tests/struct_tag_tests.move b/language/move-stdlib/tests/struct_tag_tests.move index 077b033c20..39773545b4 100644 --- a/language/move-stdlib/tests/struct_tag_tests.move +++ b/language/move-stdlib/tests/struct_tag_tests.move @@ -9,6 +9,8 @@ module std::struct_tag_tests { struct TestStructGeneric2 has drop {} struct TestStructGeneric3 has drop {} + struct Witness has drop {} + #[test] fun test_plain_struct() { assert!(struct_tag::get() == struct_tag::new_for_testing(@0x1, ascii::string(b"struct_tag_tests"), ascii::string(b"TestStruct"), vector[]), 0); @@ -78,6 +80,21 @@ module std::struct_tag_tests { assert!(struct_tag::get>>>() == new_test_struct_3_b, 0); } + #[test] + fun test_module_authority() { + assert!(struct_tag::module_authority() == struct_tag::get(), 0); + assert!(struct_tag::module_authority>>() == struct_tag::get(), 0); + assert!(struct_tag::module_authority>>>() == struct_tag::get(), 0); + } + + #[test] + #[expected_failure(abort_code = 0, location = std::struct_tag_tests)] + fun test_module_authority_failure() { + assert!(struct_tag::module_authority() == struct_tag::get(), 0); + assert!(struct_tag::module_authority>() == struct_tag::get(), 0); + assert!(struct_tag::module_authority>>() == struct_tag::get(), 0); + } + #[test] #[expected_failure(abort_code = 0, location = std::struct_tag_tests)] fun test_invalid_properties_failure() { From 444c95ad1dfcc1140c4db6f87ea4a70b968e6a9b Mon Sep 17 00:00:00 2001 From: bytedeveloperr Date: Fri, 10 Mar 2023 08:45:28 +0100 Subject: [PATCH 3/3] [move-stdlib] lint and build docs --- language/move-stdlib/docs/struct_tag.md | 101 ++++++------------ language/move-stdlib/sources/struct_tag.move | 16 +-- .../move-stdlib/tests/struct_tag_tests.move | 48 ++++----- 3 files changed, 62 insertions(+), 103 deletions(-) diff --git a/language/move-stdlib/docs/struct_tag.md b/language/move-stdlib/docs/struct_tag.md index fb2712aa6c..abd9bc9dd8 100644 --- a/language/move-stdlib/docs/struct_tag.md +++ b/language/move-stdlib/docs/struct_tag.md @@ -8,10 +8,8 @@ Module to decompose a move struct into it's components. - [Struct `StructTag`](#0x1_struct_tag_StructTag) - [Function `get`](#0x1_struct_tag_get) -- [Function `package_address`](#0x1_struct_tag_package_address) -- [Function `module_name`](#0x1_struct_tag_module_name) -- [Function `struct_name`](#0x1_struct_tag_struct_name) -- [Function `generics`](#0x1_struct_tag_generics) +- [Function `into`](#0x1_struct_tag_into) +- [Function `module_authority`](#0x1_struct_tag_module_authority)
use 0x1::ascii;
@@ -36,12 +34,12 @@ Module to decompose a move struct into it's components.
 
 
-package_address: address +address_: address
- Address of the package that the struct belongs to. + Address of the entity that the struct belongs to. taking 00000000000000000000000000000001::option::Option<u64> for example, - it's package address will be 00000000000000000000000000000001 + the address will be 00000000000000000000000000000001
module_name: ascii::String @@ -62,7 +60,7 @@ Module to decompose a move struct into it's components.
the generics or tyepe params of the struct. - using the example struct above the module name should be vector[u64] + using the example struct above the module name should be vector["u64"]
@@ -73,7 +71,7 @@ Module to decompose a move struct into it's components. ## Function `get` -Return the tag of the struct of type T +Returns the tag of the struct of type T
public fun get<T>(): struct_tag::StructTag
@@ -92,14 +90,13 @@ Return the tag of the struct of type T
 
 
 
-
+
 
-## Function `package_address`
+## Function `into`
 
-Returns the package address of self
 
 
-
public fun package_address(self: struct_tag::StructTag): address
+
public fun into(self: &struct_tag::StructTag): (address, ascii::String, ascii::String, vector<ascii::String>)
 
@@ -108,8 +105,8 @@ Returns the package address of self Implementation -
public fun package_address(self: StructTag): address {
-    self.package_address
+
public fun into(self: &StructTag): (address, String, String, vector<String>) {
+    (self.address_, self.module_name, self.struct_name, self.generics)
 }
 
@@ -117,14 +114,14 @@ Returns the package address of self - + -## Function `module_name` +## Function `module_authority` -Returns the module name of self +Returns the module authority for the struct of type T -
public fun module_name(self: struct_tag::StructTag): ascii::String
+
public fun module_authority<T>(): struct_tag::StructTag
 
@@ -133,58 +130,20 @@ Returns the module name of self Implementation -
public fun module_name(self: StructTag): String {
-    self.module_name
-}
-
- - - - - - - -## Function `struct_name` - -Returns the struct name of self - - -
public fun struct_name(self: struct_tag::StructTag): ascii::String
-
- - - -
-Implementation - - -
public fun struct_name(self: StructTag): String {
-    self.struct_name
-}
-
- - - -
- - - -## Function `generics` - -Returns the generics of self - - -
public fun generics(self: struct_tag::StructTag): vector<ascii::String>
-
- - - -
-Implementation - - -
public fun generics(self: StructTag): vector<String> {
-    self.generics
+
public fun module_authority<T>(): StructTag {
+    let StructTag {
+        address_,
+        module_name,
+        struct_name: _,
+        generics: _
+    } = get<T>();
+
+    StructTag {
+        address_,
+        module_name,
+        struct_name: ascii::string(b"Witness"),
+        generics: vector[]
+    }
 }
 
diff --git a/language/move-stdlib/sources/struct_tag.move b/language/move-stdlib/sources/struct_tag.move index 557368b3c9..9d659b232d 100644 --- a/language/move-stdlib/sources/struct_tag.move +++ b/language/move-stdlib/sources/struct_tag.move @@ -4,10 +4,10 @@ module std::struct_tag { struct StructTag has copy, store, drop { /// Address of the entity that the struct belongs to. - /// taking `00000000000000000000000000000001::option::Option` for example, + /// taking `00000000000000000000000000000001::option::Option` for example, /// the address will be `00000000000000000000000000000001` address_: address, - /// the name of the module where the struct is defined. + /// the name of the module where the struct is defined. /// using the example struct above the module name should be `option` module_name: String, /// the name of the struct itself. @@ -28,11 +28,11 @@ module std::struct_tag { /// Returns the module authority for the struct of type `T` public fun module_authority(): StructTag { - let StructTag { - address_, - module_name, - struct_name: _, - generics: _ + let StructTag { + address_, + module_name, + struct_name: _, + generics: _ } = get(); StructTag { @@ -52,4 +52,4 @@ module std::struct_tag { generics } } -} \ No newline at end of file +} diff --git a/language/move-stdlib/tests/struct_tag_tests.move b/language/move-stdlib/tests/struct_tag_tests.move index 39773545b4..abf05ff4c1 100644 --- a/language/move-stdlib/tests/struct_tag_tests.move +++ b/language/move-stdlib/tests/struct_tag_tests.move @@ -12,7 +12,7 @@ module std::struct_tag_tests { struct Witness has drop {} #[test] - fun test_plain_struct() { + fun test_plain_struct() { assert!(struct_tag::get() == struct_tag::new_for_testing(@0x1, ascii::string(b"struct_tag_tests"), ascii::string(b"TestStruct"), vector[]), 0); assert!(struct_tag::get() == struct_tag::new_for_testing(@0x1, ascii::string(b"ascii"), ascii::string(b"String"), vector[]), 0); } @@ -21,16 +21,16 @@ module std::struct_tag_tests { fun test_generic_struct() { // testing withbasic single generic let new_test_struct_1 = struct_tag::new_for_testing( - @0x1, - ascii::string(b"struct_tag_tests"), + @0x1, + ascii::string(b"struct_tag_tests"), ascii::string(b"TestStructGeneric1"), vector[ascii::string(b"00000000000000000000000000000001::ascii::String")] ); // testing with two generics let new_test_struct_2_a = struct_tag::new_for_testing( - @0x1, - ascii::string(b"struct_tag_tests"), + @0x1, + ascii::string(b"struct_tag_tests"), ascii::string(b"TestStructGeneric2"), vector[ ascii::string(b"00000000000000000000000000000001::ascii::String"), @@ -40,8 +40,8 @@ module std::struct_tag_tests { // testing with two generics with nested generic let new_test_struct_2_b = struct_tag::new_for_testing( - @0x1, - ascii::string(b"struct_tag_tests"), + @0x1, + ascii::string(b"struct_tag_tests"), ascii::string(b"TestStructGeneric2"), vector[ ascii::string(b"00000000000000000000000000000001::ascii::String"), @@ -51,8 +51,8 @@ module std::struct_tag_tests { // testing with multiple(two or more) generics with nested generic let new_test_struct_3_a = struct_tag::new_for_testing( - @0x1, - ascii::string(b"struct_tag_tests"), + @0x1, + ascii::string(b"struct_tag_tests"), ascii::string(b"TestStructGeneric3"), vector[ ascii::string(b"00000000000000000000000000000001::ascii::String"), @@ -63,8 +63,8 @@ module std::struct_tag_tests { // testing with multiple generics with nested two or more generics let new_test_struct_3_b = struct_tag::new_for_testing( - @0x1, - ascii::string(b"struct_tag_tests"), + @0x1, + ascii::string(b"struct_tag_tests"), ascii::string(b"TestStructGeneric3"), vector[ ascii::string(b"00000000000000000000000000000001::ascii::String"), @@ -81,7 +81,7 @@ module std::struct_tag_tests { } #[test] - fun test_module_authority() { + fun test_module_authority() { assert!(struct_tag::module_authority() == struct_tag::get(), 0); assert!(struct_tag::module_authority>>() == struct_tag::get(), 0); assert!(struct_tag::module_authority>>>() == struct_tag::get(), 0); @@ -100,40 +100,40 @@ module std::struct_tag_tests { fun test_invalid_properties_failure() { // supplying invalid address let new_test_struct_1_a = struct_tag::new_for_testing( - @0x2, - ascii::string(b"struct_tag_tests"), + @0x2, + ascii::string(b"struct_tag_tests"), ascii::string(b"TestStructGeneric1"), vector[ascii::string(b"00000000000000000000000000000001::ascii::String")] ); // supplying invalid module name let new_test_struct_1_b = struct_tag::new_for_testing( - @0x1, - ascii::string(b"fake_module_name"), + @0x1, + ascii::string(b"fake_module_name"), ascii::string(b"TestStructGeneric1"), vector[ascii::string(b"00000000000000000000000000000001::ascii::String")] ); // supplying invalid struct name let new_test_struct_1_c = struct_tag::new_for_testing( - @0x1, - ascii::string(b"struct_tag_tests"), + @0x1, + ascii::string(b"struct_tag_tests"), ascii::string(b"TestStructGeneric"), vector[ascii::string(b"00000000000000000000000000000001::ascii::String")] ); // supplying invalid generic let new_test_struct_1_d = struct_tag::new_for_testing( - @0x1, - ascii::string(b"fake_module_name"), + @0x1, + ascii::string(b"fake_module_name"), ascii::string(b"TestStructGeneric1"), vector[ascii::string(b"00000000000000000000000000000001::string::String")] ); // supplying incorrectly positioned generics let new_test_struct_3_a = struct_tag::new_for_testing( - @0x1, - ascii::string(b"struct_tag_tests"), + @0x1, + ascii::string(b"struct_tag_tests"), ascii::string(b"TestStructGeneric3"), vector[ ascii::string(b"address"), @@ -144,8 +144,8 @@ module std::struct_tag_tests { // supplying incomplete generics let new_test_struct_3_b = struct_tag::new_for_testing( - @0x1, - ascii::string(b"struct_tag_tests"), + @0x1, + ascii::string(b"struct_tag_tests"), ascii::string(b"TestStructGeneric3"), vector[ ascii::string(b"00000000000000000000000000000001::ascii::String"),