Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/dfinity/motoko into ryan/…
Browse files Browse the repository at this point in the history
…values-alias-for-vals
  • Loading branch information
rvanasa committed Jan 31, 2025
2 parents d753908 + b6b9b25 commit 56fc71c
Show file tree
Hide file tree
Showing 115 changed files with 703 additions and 271 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
30 changes: 25 additions & 5 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
# Motoko compiler changelog

## 0.13.7 (FUTURE)

* motoko (`moc`)

* Support passing cycles in primitive `call_raw` (resp. `ExperimentalInternetComputer.call`) (#4868).

## 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 +38,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 +50,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
2 changes: 2 additions & 0 deletions doc/md/base/Error.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type ErrorCode = {
#system_fatal;
// Transient error.
#system_transient;
// Response unknown due to missed deadline.
#system_unknown;
// Destination invalid.
#destination_invalid;
// Explicit reject by canister code.
Expand Down
9 changes: 9 additions & 0 deletions doc/md/base/ExperimentalInternetComputer.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,12 @@ 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
38 changes: 18 additions & 20 deletions doc/md/base/Timer.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
# Timer

Timers for one-off or periodic tasks. Applicable as part of the default mechanism.
If `moc` is invoked with `-no-timer`, the importing will fail. Furthermore, if passed `--trap-on-call-error`, a congested canister send queue may prevent timer expirations to execute at runtime. It may also deactivate the global timer.

Note: If `moc` is invoked with `-no-timer`, the importing will fail.

Note: The resolution of the timers is in the order of the block rate,
so durations should be chosen well above that. For frequent
canister wake-ups the heartbeat mechanism should be considered.
The resolution of the timers is similar to the block rate,
so durations should be chosen well above that. For frequent
canister wake-ups, consider using the [heartbeat](https://internetcomputer.org/docs/current/motoko/main/writing-motoko/heartbeats) mechanism; however, when possible, canisters should prefer timers.

Note: The functionality described below is enabled only when the actor does not override it by declaring an explicit `system func timer`.
The functionality described below is enabled only when the actor does not override it by declaring an explicit `system func timer`.

Note: Timers are _not_ persisted across upgrades. One possible strategy
to re-establish timers after an upgrade is to walk stable variables
in the `post_upgrade` hook and distill necessary timer information
from there.
Timers are _not_ persisted across upgrades. One possible strategy
to re-establish timers after an upgrade is to use stable variables
in the `post_upgrade` hook and distill necessary timer information
from there.

Note: Basing security (e.g. access control) on timers is almost always
the wrong choice. Be sure to inform yourself about state-of-the art
dApp security. If you _must use_ timers for security controls, be sure
to consider reentrancy issues, and the vanishing of timers on upgrades
and reinstalls.
Using timers for security (e.g., access control) is strongly discouraged.
Make sure to inform yourself about state-of-the-art dapp security.
If you must use timers for security controls, be sure
to consider reentrancy issues as well as the vanishing of timers on upgrades
and reinstalls.

Note: For further usage information for timers on the IC please consult
https://internetcomputer.org/docs/current/developer-docs/backend/periodic-tasks#timers-library-limitations
For further usage information for timers on the IC, please consult
[the documentation](https://internetcomputer.org/docs/current/developer-docs/backend/periodic-tasks#timers-library-limitations).

## Type `Duration`
``` motoko no-repl
Expand Down Expand Up @@ -79,8 +77,8 @@ Cancels a still active timer with `(id : TimerId)`. For expired timers
and not recognised `id`s nothing happens.

```motoko no-repl
func deleteAppt(appt : Appointment) {
cancelTimer (appt.reminder);
func deleteAppointment(appointment : Appointment) {
cancelTimer (appointment.reminder);
// ...
};
```
2 changes: 1 addition & 1 deletion doc/md/base/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
* [Stack](Stack.md) Class `Stack<X>` provides a Minimal LIFO stack of elements of type `X`.
* [Text](Text.md) Utility functions for `Text` values.
* [Time](Time.md) System time
* [Timer](Timer.md) Timers for one-off or periodic tasks.
* [Timer](Timer.md) Timers for one-off or periodic tasks. Applicable as part of the default mechanism.
* [Trie](Trie.md) Functional key-value hash maps.
* [TrieMap](TrieMap.md) Class `TrieMap<K, V>` provides a map from keys of type `K` to values of type `V`.
* [TrieSet](TrieSet.md) Functional set
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.
Loading

0 comments on commit 56fc71c

Please sign in to comment.