Skip to content

Commit

Permalink
Merge branch 'master' into claudio/migration
Browse files Browse the repository at this point in the history
  • Loading branch information
crusso authored Jan 21, 2025
2 parents 21f1f23 + a194159 commit 9cc961b
Show file tree
Hide file tree
Showing 110 changed files with 638 additions and 224 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
@dfinity/languages
* @dfinity/languages
5 changes: 5 additions & 0 deletions .github/repo_policies/BOT_APPROVED_FILES
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# List of approved files that can be changed by a bot via an automated PR

Changelog.md
doc/docusaurus/package-lock.json
nix/sources.json
24 changes: 19 additions & 5 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
# Motoko compiler changelog

## 0.13.6 (2025-01-21)

* motoko (`moc`)

* Support the low Wasm memory hook: `system func lowmemory() : async* () { ... }` (#4849).

* Breaking change (minor) (#4854):

* For enhanced orthogonal persistence: The Wasm persistence modes used internally for canister upgrades have been changed to lower case names,
`keep` and `replace` and instead of `Keep` and `Replace`:

If using actor class instances with enhanced orthogonal persistence, you would need to recompile the program and upgrade with latest `moc` and `dfx`.
Otherwise, no action is needed.

* bugfix: Checks and mitigations that timer servicing works (#4846).

* bugfix: Some valid upgrades deleting a stable variable could fail the `--enhanced-orthogonal-persistence` stable compatibility check due to a bug (#4855).

## 0.13.5 (2024-12-06)

* motoko (`moc`)

* Breaking change (minor):
* Breaking change (minor) (#4786):

* Add new keyword `transient` with exactly the same meaning as the old keyword `flexible` (but a more familiar reading).

Expand All @@ -14,10 +32,8 @@
`let` or `var` declaration is `stable` (not `flexible` or `transient`).

For example, a stateful counter can now be declared as:

``` motoko
persistent actor {
// counts increments since last upgrade
transient var invocations = 0;
Expand All @@ -28,10 +44,8 @@
value += 1;
invocations += 1;
}
}
```
On upgrade, the transient variable `invocations` will be reset to `0` and `value`, now implicitly `stable`, will retain its current value.
Legacy actors and classes declared without the `persistent` keyword have the same semantics as before.
Expand Down
12 changes: 6 additions & 6 deletions doc/docusaurus/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions doc/md/base/Debug.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ func print(text : Text)

Prints `text` to output stream.

NOTE: The output is placed in the replica log. When running on mainnet,
this function has no effect.
NOTE: When running on an ICP network, all output is written to the [canister log](https://internetcomputer.org/docs/current/developer-docs/smart-contracts/maintain/logs) with the exclusion of any output
produced during the execution of non-replicated queries and composite queries.
In other environments, like the interpreter and stand-alone wasm engines, the output is written to standard out.

```motoko include=import
Debug.print "Hello New World!";
Expand Down
10 changes: 10 additions & 0 deletions doc/md/base/ExperimentalInternetComputer.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,13 @@ let c1 = IC.performanceCounter(1);
work();
let diff : Nat64 = IC.performanceCounter(1) - c1;
```

## Function `replyDeadline`
``` motoko no-repl
func replyDeadline() : Nat
```

Returns the time (in nanoseconds from the epoch start) by when the update message should
reply to the best effort message so that it can be received by the requesting canister.
Queries and non-best-effort update messages return zero.

2 changes: 1 addition & 1 deletion doc/md/base/OrderedMap.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Credits:
The core of this implementation is derived from:

* Ken Friis Larsen's [RedBlackMap.sml](https://github.com/kfl/mosml/blob/master/src/mosmllib/Redblackmap.sml), which itself is based on:
* Stefan Kahrs, "Red-black trees with types", Journal of Functional Programming, 11(4): 425-432 (2001), [version 1 in web appendix](https://www.cs.ukc.ac.uk/people/staff/smk/redblack/rb.html).
* Stefan Kahrs, "Red-black trees with types", Journal of Functional Programming, 11(4): 425-432 (2001), [version 1 in web appendix](http://www.cs.ukc.ac.uk/people/staff/smk/redblack/rb.html).

## Type `Map`
``` motoko no-repl
Expand Down
2 changes: 1 addition & 1 deletion doc/md/base/OrderedSet.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Credits:
The core of this implementation is derived from:

* Ken Friis Larsen's [RedBlackMap.sml](https://github.com/kfl/mosml/blob/master/src/mosmllib/Redblackmap.sml), which itself is based on:
* Stefan Kahrs, "Red-black trees with types", Journal of Functional Programming, 11(4): 425-432 (2001), [version 1 in web appendix](https://www.cs.ukc.ac.uk/people/staff/smk/redblack/rb.html).
* Stefan Kahrs, "Red-black trees with types", Journal of Functional Programming, 11(4): 425-432 (2001), [version 1 in web appendix](http://www.cs.ukc.ac.uk/people/staff/smk/redblack/rb.html).

## Type `Set`
``` motoko no-repl
Expand Down
2 changes: 1 addition & 1 deletion doc/md/base/RBTree.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Credits:
The core of this implementation is derived from:

* Ken Friis Larsen's [RedBlackMap.sml](https://github.com/kfl/mosml/blob/master/src/mosmllib/Redblackmap.sml), which itself is based on:
* Stefan Kahrs, "Red-black trees with types", Journal of Functional Programming, 11(4): 425-432 (2001), [version 1 in web appendix](https://www.cs.ukc.ac.uk/people/staff/smk/redblack/rb.html).
* Stefan Kahrs, "Red-black trees with types", Journal of Functional Programming, 11(4): 425-432 (2001), [version 1 in web appendix](http://www.cs.ukc.ac.uk/people/staff/smk/redblack/rb.html).

## Type `Color`
``` motoko no-repl
Expand Down
58 changes: 58 additions & 0 deletions doc/md/base/Text.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,34 @@ Converts the given `Char` to a `Text` value.
let text = Text.fromChar('A'); // "A"
```

## Function `fromArray`
``` motoko no-repl
func fromArray(a : [Char]) : Text
```

Converts the given `[Char]` to a `Text` value.

```motoko include=import
let text = Text.fromArray(['A', 'v', 'o', 'c', 'a', 'd', 'o']); // "Avocado"
```

Runtime: O(a.size())
Space: O(a.size())

## Function `fromVarArray`
``` motoko no-repl
func fromVarArray(a : [var Char]) : Text
```

Converts the given `[var Char]` to a `Text` value.

```motoko include=import
let text = Text.fromVarArray([var 'E', 'g', 'g', 'p', 'l', 'a', 'n', 't']); // "Eggplant"
```

Runtime: O(a.size())
Space: O(a.size())

## Function `toIter`
``` motoko no-repl
func toIter(t : Text) : Iter.Iter<Char>
Expand Down Expand Up @@ -105,6 +133,36 @@ Creates a `Text` value from a `Char` iterator.
let text = Text.fromIter(['a', 'b', 'c'].vals()); // "abc"
```

## Function `fromList`
``` motoko no-repl
func fromList(cs : List.List<Char>) : Text
```

Create a text from a character list.
Example:
```motoko include=initialize
fromList(?('H', ?('e', ?('l', ?('l', ?('o', null))))));
// => "Hello"
```

Runtime: O(size cs)
Space: O(size cs)

## Function `toList`
``` motoko no-repl
func toList(t : Text) : List.List<Char>
```

Create a character list from a text.
Example:
```motoko include=initialize
toList("Hello");
// => ?('H', ?('e', ?('l', ?('l', ?('o', null)))))
```

Runtime: O(t.size())
Space: O(t.size())

## Function `size`
``` motoko no-repl
func size(t : Text) : Nat
Expand Down
11 changes: 5 additions & 6 deletions doc/md/canister-maintenance/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ sidebar_position: 4

# Verifying upgrade compatibility

## Overview


When upgrading a canister, it is important to verify that the upgrade can proceed without:

- Introducing an incompatible change in stable declarations.
- Breaking clients due to a Candid interface change.

`dfx` checks these properties statically before attempting the upgrade.
`dfx` checks these properties statically before attempting the upgrade.
Moreover, with [enhanced orthogonal persistence](orthogonal-persistence/enhanced.md), Motoko rejects incompatible changes of stable declarations.

## Upgrade example
Expand Down Expand Up @@ -233,14 +233,14 @@ cannot be consumed at new type
Do you want to proceed? yes/No
```
It is recommended not to continue, as you will lose the state in older versions of Motoko that use [classical orthogonal persistence](orthogonal-persistence/classical.md).
It is recommended not to continue, as you will lose the state in older versions of Motoko that use [classical orthogonal persistence](orthogonal-persistence/classical.md).
Upgrading with [enhanced orthogonal persistence](orthogonal-persistence/enhanced.md) will trap and roll back, keeping the old state.

Adding a new record field to the type of existing stable variable is not supported. The reason is simple: The upgrade would need to supply values for the new field out of thin air. In this example, the upgrade would need to conjure up some value for the `description` field of every existing `card` in `map`. Moreover, allowing adding optional fields is also a problem, as a record can be shared from various variables with different static types, some of them already declaring the added field or adding a same-named optional field with a potentially different type (and/or different semantics).

### Solution

To resolve this issue, an [explicit](#explicit-migration) is needed:
To resolve this issue, an [explicit migration](#explicit-migration) is needed:

1. You must keep the old variable `map` with the same structural type. However, you are allowed to change type alias name (`Card` to `OldCard`).
2. You can introduce a new variable `newMap` and copy the old state to the new one, initializing the new field as needed.
Expand All @@ -257,7 +257,6 @@ persistent actor {
title : Text;
description : Text;
};
var map : [(Nat32, OldCard)] = [];
var newMap : [(Nat32, NewCard)] = Array.map<(Nat32, OldCard), (Nat32, NewCard)>(
map,
Expand All @@ -278,7 +277,7 @@ persistent actor {
};
```

`dfx` will issue a warning that `map` will be dropped.
`dfx` will issue a warning that `map` will be dropped.

Make sure, you have previously migrated the old state to `newMap` before applying this final reduced version.

Expand Down
2 changes: 1 addition & 1 deletion doc/md/canister-maintenance/cycles.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ sidebar_position: 1

# Cycles

## Overview


Usage of a canister's resources on ICP is measured and paid for in [cycles](/docs/current/developer-docs/defi/cycles/converting_icp_tokens_into_cycles).

Expand Down
26 changes: 26 additions & 0 deletions doc/md/canister-maintenance/memory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
sidebar_position: 5
---

# Memory diagnostics

## Low memory hook

The IC allows to implement a low memory hook, which is a warning trigger when main memory is becoming scarce.

For this purpose, a Motoko actor or actor class instance can implement the system function `lowmemory()`. This system function is scheduled when canister's free main memory space has fallen below the defined threshold `wasm_memory_threshold`, that is is part of the canister settings. In Motoko, `lowmemory()` implements the `canister_on_low_wasm_memory` hook defined in the IC specification.

Example of using the low memory hook:
```
actor {
system func lowmemory() : async* () {
Debug.print("Low memory!");
}
}
```

The following properties apply to the low memory hook:
* The execution of `lowmemory` happens with a certain delay, as it is scheduled as a separate asynchronous message that runs after the message in which the threshold was crossed.
* Once executed, `lowmemory` is only triggered again when the main memory free space first exceeds and then falls below the threshold.
* Traps or unhandled errors in `lowmemory` are ignored. Traps only revert the changes done in `lowmemory`.
* Due to its `async*` return type, the `lowmemory` function may send further messages and `await` results.
14 changes: 7 additions & 7 deletions doc/md/canister-maintenance/optimization.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ sidebar_position: 2

# Optimizing canisters

## Overview

The Motoko compiler produces small binaries with reasonably efficient code, but is not a highly optimized compiler.

The Motoko compiler produces small binaries with reasonably efficient code, but is not a highly optimized compiler.
It is possible to further optimize Motoko binaries, both for code size and cycle usage, using additional tools such as `wasm-opt`.

## Using `wasm-opt`

`Wasm-opt` is a general purpose Wasm optimizer that is now available in dfx, versions 0.14.0 and newer.
`Wasm-opt` is a general purpose Wasm optimizer that is now available in dfx, versions 0.14.0 and newer.

`Wasm-opt` can be used to enable canister optimizations through a configuration option in the project's `dfx.json` file, such as:

Expand All @@ -27,9 +27,9 @@ It is possible to further optimize Motoko binaries, both for code size and cycle

### Optimization levels for cycle usage

Using the `"optimize": "cycles"` option, you can expect a rough estimate of decreased cycles usage for Motoko canisters by around 10%.
Using the `"optimize": "cycles"` option, you can expect a rough estimate of decreased cycles usage for Motoko canisters by around 10%.

The `"optimize": "cycles"` option is the recommended default, as it maps to optimization level 3 in the `wasm-opt` package.
The `"optimize": "cycles"` option is the recommended default, as it maps to optimization level 3 in the `wasm-opt` package.

The optimization levels for cycles usage are as follows:

Expand All @@ -43,7 +43,7 @@ O0 (performs no optimizations)

### Optimization levels for binary size

To optimize the binary size instead, you can use the `"optimize": "size"` option. By using the size option, binary sizes can be reduced by roughly 16%.
To optimize the binary size instead, you can use the `"optimize": "size"` option. By using the size option, binary sizes can be reduced by roughly 16%.

The optimization levels for binary size are as follows:

Expand All @@ -52,7 +52,7 @@ Oz (equivalent to “size”)
Os
```

Each optimization preserves the Internet Computer specific metadata sections of each canister.
Each optimization preserves the Internet Computer specific metadata sections of each canister.

:::info
Note that in certain cases the optimizations can increase the complexity of certain functions in your Wasm module such that they are rejected by the replica. If you run into this issue, it is recommended to use a less aggressive optimization level such that you do not exceed the complexity limit.
Expand Down
5 changes: 2 additions & 3 deletions doc/md/canister-maintenance/upgrades.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ sidebar_position: 3

# Stable variables and upgrade methods

## Overview


One key feature of Motoko is its ability to automatically persist the program's state without explicit user instruction, called **orthogonal persistence**. This not only covers persistence across transactions but also includes canister upgrades. For this purpose, Motoko features a bespoke compiler and runtime system that manages upgrades in a sophisticated way such that a new program version can pick up the state left behind by a previous program version. As a result, Motoko data persistence is not simple but also prevents data corruption or loss, while being efficient at the same time. No database, stable memory API, or stable data structure is required to retain state across upgrades. Instead, a simple `stable` keyword is sufficient to declare an data structure of arbitrary shape persistent, even if the structure uses sharing, has a deep complexity, or contains cycles.

Expand Down Expand Up @@ -92,7 +92,6 @@ For example, the stable type `TemperatureSeries` covers the persistent data, whi
``` motoko no-repl file=../examples/WeatherActor.mo
```


3. __Discouraged and not recommended__: [Pre- and post-upgrade hooks](#preupgrade-and-postupgrade-system-methods) allow copying non-stable types to stable types during upgrades. This approach is error-prone and does not scale for large data. **Per best practices, using these methods should be avoided if possible.** Conceptually, it also does not align well with the idea of orthogonal persistence.

## Stable type signatures
Expand Down Expand Up @@ -212,7 +211,7 @@ The following aspects are retained for historical reasons and backwards compatib
Using the pre- and post-upgrade system methods is discouraged. It is error-prone and can render a canister unusable. In particular, if a `preupgrade` method traps and cannot be prevented from trapping by other means, then your canister may be left in a state in which it can no longer be upgraded. Per best practices, using these methods should be avoided if possible.
:::

Motoko supports user-defined upgrade hooks that run immediately before and after an upgrade. These upgrade hooks allow triggering additional logic on upgrade.
Motoko supports user-defined upgrade hooks that run immediately before and after an upgrade. These upgrade hooks allow triggering additional logic on upgrade.
These hooks are declared as `system` functions with special names, `preugrade` and `postupgrade`. Both functions must have type `: () → ()`.

:::danger
Expand Down
2 changes: 1 addition & 1 deletion doc/md/getting-started/basic-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ sidebar_position: 2

# Basic concepts and terms

## Overview


Motoko is designed for distributed programming with **actors**. When programming on ICP in Motoko, each actor represents an ICP canister smart contract with a Candid interface.
Within Motoko, the term actor is used to refer to any canister authored in any language that deploys to ICP. The role of Motoko is to make these actors easy to author and use programmatically once deployed.
Expand Down
Loading

0 comments on commit 9cc961b

Please sign in to comment.