v0.20.0-alpha
Pre-release0.20.0-alpha "Tokyoite" (2022-12-05)
Features
-
Removed the
event
type as well as theemit
keyword.
Instead thestruct
type now automatically implements
theEmittable
trait and can be emitted viactx.emit(..)
.Indexed fields can be annotated via the
#indexed
attribute.E.g.
struct Signed { book_msg: String<100> } contract GuestBook { messages: Map<address, String<100>> pub fn sign(mut self, mut ctx: Context, book_msg: String<100>) { self.messages[ctx.msg_sender()] = book_msg ctx.emit(Signed(book_msg)) } }
(#717)
-
Allow to call trait methods on types when trait is in scope
So far traits were only useful as bounds for generic functions.
With this change traits can also be used as illustrated with
the following example:trait Double { fn double(self) -> u256; } impl Double for (u256, u256) { fn double(self) -> u256 { return (self.item0 + self.item1) * 2 } } contract Example { pub fn run_test(self) { assert (0, 1).double() == 2 } }
If a call turns out to be ambigious the compiler currently asks the
user to disambiguate via renaming. In the future we will likely
introduce a syntax to allow to disambiguate at the callsite. (#757) -
Allow contract associated functions to be called via
ContractName::function_name()
syntax. (#767) -
Add
enum
types andmatch
statement.enum
can now be defined, e.g.,pub enum MyEnum { Unit Tuple(u32, u256, bool) fn unit() -> MyEnum { return MyEnum::Unit } }
Also,
match
statement is introduced, e.g.,pub fn eval_enum() -> u256{ match MyEnum { MyEnum::Unit => { return 0 } MyEnum::Tuple(a, _, false) => { return u256(a) } MyEnum::Tuple(.., true) => { return u256(1) } } }
For now, available patterns are restricted to
- Wildcard(
_
), which matches all patterns:_
- Named variable, which matches all patterns and binds the value to make the value usable in the arm. e.g.,
a
,b
andc
inMyEnum::Tuple(a, b, c)
- Boolean literal(
true
andfalse
) - Enum variant. e.g.,
MyEnum::Tuple(a, b, c)
- Tuple pattern. e.g.,
(a, b, c)
- Struct pattern. e.g.,
MyStruct {x: x1, y: y1, b: true}
- Rest pattern(
..
), which matches the rest of the pattern. e.g.,MyEnum::Tuple(.., true)
- Or pattern(|). e.g., MyEnum::Unit | MyEnum::Tuple(.., true)
Fe compiler performs the exhaustiveness and usefulness checks for
match
statement.
So the compiler will emit an error when all patterns are not covered or an unreachable arm are detected. (#770) - Wildcard(
-
Changed comments to use
//
instead of#
(#776) -
Added the
mut
keyword, to mark things as mutable. Any variable or function parameter
not markedmut
is now immutable.contract Counter { count: u256 pub fn increment(mut self) -> u256 { // `self` is mutable, so storage can be modified self.count += 1 return self.count } } struct Point { pub x: u32 pub y: u32 pub fn add(mut self, _ other: Point) { self.x += other.x self.y += other.y // other.x = 1000 // ERROR: `other` is not mutable } } fn pointless() { let origin: Point = Point(x: 0, y: 0) // origin.x = 10 // ERROR: origin is not mutable let x: u32 = 10 // x_coord = 100 // ERROR: `x_coord` is not mutable let mut y: u32 = 0 y = 10 // OK let mut p: Point = origin // copies `origin` p.x = 10 // OK, doesn't modify `origin` let mut q: Point = p // copies `p` q.x = 100 // doesn't modify `p` p.add(q) assert p.x == 110 }
Note that, in this release, primitive type function parameters
can't bemut
. This restriction might be lifted in a future release.For example:
fn increment(mut x: u256) { // ERROR: primitive type parameters can't be mut x += 1 }
(#777)
-
The contents of the
std::prelude
module (currently just theContext
struct)
are now automaticallyuse
d by every module, souse std::context::Context
is
no longer required. (#779) -
When the Fe compiler generates a JSON ABI file for a contract, the
"stateMutability" field for each function now reflects whether the function can
read or modify chain or contract state, based on the presence or absence of the
self
andctx
parameters, and whether those parameters aremut
able.If a function doesn't take
self
orctx
, it's "pure".
If a function takesself
orctx
immutably, it can read state but not mutate
state, so it's a "view"
If a function takesmut self
ormut ctx
, it can mutate state, and is thus
marked "payable".Note that we're following the convention set by Solidity for this field, which
isn't a perfect fit for Fe. The primary issue is that Fe doesn't currently
distinguish between "payable" and "nonpayable" functions; if you want a function
to revert when Eth is sent, you need to do it manually
(egassert ctx.msg_value() == 0
). (#783) -
Trait associated functions
This change allows trait functions that do not take a
self
parameter.
The following demonstrates a possible trait associated function and its usage:trait Max { fn max(self) -> u8; } impl Max for u8 { fn max() -> u8 { return u8(255) } } contract Example { pub fn run_test(self) { assert u8::max() == 255 } }
(#805)
Bugfixes
-
Fix issue where calls to assiciated functions did not enforce visibility rules.
E.g the following code should be rejected but previously wasn't:
struct Foo { fn do_private_things() { } } contract Bar { fn test() { Foo::do_private_things() } }
With this change, the above code is now rejected because
do_private_things
is notpub
. (#767) -
Padding on
bytes
andstring
ABI types is zeroed out. (#769) -
Ensure traits from other modules or even ingots can be implemented (#773)
-
Certain cases where the compiler would not reject pure functions
being called on instances are now properly rejected. (#775) -
Reject calling
to_mem()
on primitive types in storage (#801) -
Disallow importing private type via
use
The following was previously allowed but will now error:
use foo::PrivateStruct
(#815)