Better Syntax for borrow_global and borrow_global_mut
borrow_global<T>(a) ⇒ &T[a] borrow_global_mut<T>(a) ⇒ &mut T[a]
U256
Design (Option A)
Natively support the type u256 and let it behave similar to the existing integer types u8, u64, and u128. All operations and notations available for the existing integer types should be supported.
Design (Option B)
Move frameworks that want u256 for EVM compatibility or other reasons can implement it in pure Move (with or without native function support), as Starcoin has done here. We could also consider adding this to the Move stdlib and transparently compiling +, - etc on u256 to use this module. This would keep the rather EVM-specific u256 out of the platform-agnostic bytecode language.
Design (Option C)
Broaden this to filling in several missing integer types for Move: u16, u32, u256. This gets us closer to parity with BCS’s data types.
Method Call Syntax
If a struct `MyType` and function `foo` are both declared in the same module, and `foo`’s signature is something like `foo_mut(&mut MyType, …)` or `foo_immut(&MyType, …)`, the compiler should support the call syntax `t.foo_mut(...)` or `t.foo_immut(...). Specifically:
If `t: MyType`, either `t.foo_mut(...)` or `t.foo_immut(...)` can be called
If `t: &mut MyType, either `t.foo_mut(...)` or `t.foo_immut(...)` can be called
If `t: &MyType`, `t.foo_immut(...)` can be called
Signer Relaxation for MoveTo
Design (Option A)
Drop the requirement of passing a signer to move-to all together. For downwards compatibility reasons, the compiler allows passing either a signer or an address. Rationale for this quite radical step is that in-real world contracts (e.g. the Diem Payment Network) more complex access control patterns than enabled by signer/move_to are needed anyway. Moreover, since only modules which declare a resource R can call move_to<R>, preventing publishing without a signer can still be modeled by modular encapsulation.
Design (Option B)
Use an attribute on struct declarations to indicate a signer is not required for publishing this struct.
Design (Option C)
Have another function which does not require a signer, e.g. move_to_address. This, however, raises questions of adequate naming and methodology (when to use which function, should there be constraints when which function is allowed, etc.)
Design (Option D)
Add no new features and ask clients that want this feature (e.g., the Move -> EVM compilation effort) to implement it via design patterns and/or native functions. See SignerCapability in the Starcoin Account code for one example of a design pattern for (effectively) implementing move_to_address without changing the language.
Design (Option E)
Support this via a new internal ability that allows framework designers to implement more powerful native functions with the same encapsulation guarantees as bytecodes. For example, the framework designer can define a function `public native fun move_to_address<T: internal>(a: address, t: T)` that can only be invoked on `T`’s declared in the calling module.
Design (Option F)
Use tables when there is a need to index storage without signer.
Table
module Std::Table { native struct Table<K, V: store> has store; native fun create<K, V>(): Table<K, V> native fun destroy<K, V>(t: Table<K, V>); native fun insert<K, V>(t: &mut Table<K, V>, k: &K, v: V); native fun remove<K, V>(t: &mut Table<K, V>, k: &K): V; native fun contains_key<K, V>(t: &Table<K, V>, k: &K): bool; native fun borrow<K, V>(t: &Table<K, V>, k: &K): &V; native fun borrow_mut<K, V>(t: &mut Table<K, V>, k: &K): &mut V; }
KeyTable
module Std::KeyTable { native struct KeyTable has store; native fun create(): KeyTable native fun destroy(t: KeyTable); native fun insert<T>(t: &mut KeyTable, v: T); native fun remove<T>(t: &mut KeyTable<K>): T; native fun contains_key<T>(t: &KeyTable<T>): bool; native fun borrow<T>(t: &KeyTable): &T; native fun borrow_mut<T>(t: &mut KeyTable<T>): &mut T; }