From afaf2f3e743f7d13d6023ca74bc358dbdcef503c Mon Sep 17 00:00:00 2001 From: "pr-automation-bot-public[bot]" Date: Tue, 19 May 2026 19:35:32 +0000 Subject: [PATCH] chore: bump Motoko to v1.8.0 --- .sources/VERSIONS | 2 +- .sources/motoko | 2 +- .../fundamentals/basic-syntax/comments.md | 4 +- .../motoko/fundamentals/error-handling.md | 2 +- .../fundamentals/implicit-parameters.md | 70 +++++++++++++++---- .../motoko/fundamentals/pattern-matching.md | 3 +- .../motoko/icp-features/randomness.md | 2 +- .../motoko/icp-features/system-functions.md | 10 +-- docs/languages/motoko/reference/changelog.md | 10 +++ .../motoko/reference/compiler-ref.md | 1 + .../motoko/reference/language-manual.md | 17 ++++- 11 files changed, 98 insertions(+), 25 deletions(-) diff --git a/.sources/VERSIONS b/.sources/VERSIONS index ef67ed02..32e6a9c9 100644 --- a/.sources/VERSIONS +++ b/.sources/VERSIONS @@ -57,7 +57,7 @@ chain-fusion-signer v0.3.0 papi v0.1.1 168bc9d ic-pub-key v1.0.1 f89fa55 icp-cli v0.2.3 caeac37 -motoko v1.7.0 1e65e26 +motoko v1.8.0 75c4123 motoko-core v2.4.0 cd37dbf cdk-rs ic-cdk v0.20.1 / ic-cdk-timers v1.0.0 / ic-cdk-executor v2.0.0 317f55c candid 2025-12-18 # candid v0.10.20, didc v0.5.4 2e4a2cf diff --git a/.sources/motoko b/.sources/motoko index 1e65e263..75c4123f 160000 --- a/.sources/motoko +++ b/.sources/motoko @@ -1 +1 @@ -Subproject commit 1e65e26346b35927869dda044bb76763627c2c57 +Subproject commit 75c4123f4d117f334d174656d049423efe6dcaab diff --git a/docs/languages/motoko/fundamentals/basic-syntax/comments.md b/docs/languages/motoko/fundamentals/basic-syntax/comments.md index dfaef518..27332c67 100644 --- a/docs/languages/motoko/fundamentals/basic-syntax/comments.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/comments.md @@ -14,7 +14,7 @@ Use `//` for comments that extend to the end of a line. // This is a single-line comment ``` -Use `///` for function or module documentation (also known as "doc comments"). Module documentation can be exported into documentation files such as Markdown or HTML using [mo-doc](../../../../developer-tools/index.md#mo-doc). +Use `///` for function or module documentation (also known as "doc comments"). Module documentation can be exported into documentation files such as Markdown or HTML using [mo-doc](/developer-tools/#mo-doc). ```motoko no-repl /// Returns the sum of two integers. @@ -46,5 +46,5 @@ Multi-line comments can be nested within each other. - [Comment style guide](/languages/motoko/reference/style-guide#comments) -- [Generating Motoko documentation](../../../../developer-tools/index.md#mo-doc) +- [Generating Motoko documentation](/developer-tools/#mo-doc) diff --git a/docs/languages/motoko/fundamentals/error-handling.md b/docs/languages/motoko/fundamentals/error-handling.md index 6562929e..43bd0625 100644 --- a/docs/languages/motoko/fundamentals/error-handling.md +++ b/docs/languages/motoko/fundamentals/error-handling.md @@ -39,7 +39,7 @@ type Result = { #ok : Ok; #err : Err } Unlike option types, the Result type includes a second type parameter `Err` which allows you to specify exactly what kind of error occurred. This makes error handling more informative and flexible. -```motoko no-repl file=/todo-error.mo#L60-L60 +```motoko no-repl file=/todo-error.mo#L59-L59 ``` The previous example can be revised to use `Result` types: diff --git a/docs/languages/motoko/fundamentals/implicit-parameters.md b/docs/languages/motoko/fundamentals/implicit-parameters.md index 98e4e6b2..762dbcb1 100644 --- a/docs/languages/motoko/fundamentals/implicit-parameters.md +++ b/docs/languages/motoko/fundamentals/implicit-parameters.md @@ -6,7 +6,7 @@ description: "Motoko language documentation" ## Overview Implicit parameters allow you to omit frequently-used function arguments at call sites when the compiler can infer them from context. This feature is particularly useful when working with ordered collections like `Map` and `Set` from the `core` library, which require comparison functions but where the comparison logic is usually obvious from the key type. -Other exampes are `equal` and `toText` functions. +Other examples are `equal` and `toText` functions. ## Basic usage @@ -14,7 +14,7 @@ Other exampes are `equal` and `toText` functions. When declaring a function, any function parameter can be declared implicit using the `implicit` type constructor: -For example, the core Map library, declares a function: +For example, the core `Map` library declares a function: ```motoko no-repl public func add(self: Map, compare : (implicit : (K, K) -> Order), key : K, value : V) { @@ -22,9 +22,9 @@ public func add(self: Map, compare : (implicit : (K, K) -> Order), k } ``` -The `implicit` marker on the type of parameter `compare` indicates the call-site can omit it the `compare` argument, provided it can be inferred the call site. +The `implicit` marker on the type of parameter `compare` indicates the call-site can omit the `compare` argument, provided it can be inferred at the call site. -A function can declare more than on implicit parameter, even of the same name. +A function can declare more than one implicit parameter, even of the same name. ```motoko @@ -58,7 +58,7 @@ Map.add(map, 5, "five"); ``` The compiler automatically finds an appropriate comparison function based on the type of the key argument. -The availabe candidates are: +The available candidates are: * Any value named `compare` whose type matches the parameter type. If there is no such value, @@ -69,7 +69,7 @@ An ambiguous call can always be disambiguated by supplying the explicit argument ### Contextual dot notation -Implicit parameters dovetail nicely with the [contextual dot notation](contextual-dot). +Implicit parameters dovetail nicely with [contextual dot notation](10-contextual-dot.md). The dot notation and implicit arguments can be used in conjunction to shorten code. For example, since the first parameter of `Map.add` is called `self`, we can both use `map` as the receiver of `add` "method" calls @@ -84,7 +84,7 @@ let map = Map.empty(); // Using contextual dot notation, without implicits - must provide compare function explicitly map.add(Nat.compare, 5, "five"); -// Using contextual dot nation together with implicits - compare function inferred from key type +// Using contextual dot notation together with implicits - compare function inferred from key type map.add(5, "five"); ``` @@ -150,7 +150,7 @@ let scores = Map.empty(); // Add player scores scores.add("Alice", 100); scores.add("Bob", 85); -scores.add( "Charlie", 92); +scores.add("Charlie", 92); // Update a score scores.add("Bob", 95); @@ -161,7 +161,7 @@ if (scores.containsKey("Alice")) { }; // Get size -let playerCount = scores.size() +let playerCount = scores.size(); ``` ## How inference works @@ -170,13 +170,57 @@ The compiler infers an implicit argument by: 1. Examining the types of the explicit arguments provided. 2. Looking for all candidate values for the implicit argument in the current scope that match the required type and name. -3. From these, selecting the best unique candidate based on type specifity. +3. From these, selecting the best unique candidate based on type specificity. If there is no unique best candidate the compiler rejects the call as ambiguous. -If a callee takes several implicits parameter, either all implicit arguments must be omitted, or all explicit and implicit arguments must be provided at the call site, +If a callee takes several implicit parameters, either all implicit arguments must be omitted, or all explicit and implicit arguments must be provided at the call site, in their declared order. +### Resolution order + +The compiler searches for implicit arguments in the following order, stopping at the first tier that produces a unique match: + +1. **Direct** — values whose type directly matches: + 1. Local values in the current scope. + 2. Module fields of modules in scope (e.g., `Nat.compare`). + 3. Fields of unimported modules (requires `--implicit-package`). +2. **Derived** — functions with implicit parameters that, after stripping their own implicits and instantiating type parameters, match the required type (see [Implicit derivation](#implicit-derivation) below): + 1. Local values in the current scope. + 2. Module fields (e.g., `Array.compare`). + 3. Fields of unimported modules (requires `--implicit-package`). +Within each tier, if multiple candidates match, the compiler picks the most specific one (by subtyping). If no unique best candidate exists, the call is rejected as ambiguous. + +This ordering guarantees that direct matches are always preferred over derived ones, and local definitions take precedence over imported or unimported module definitions. + +### Implicit derivation + +When no direct match exists, the compiler can **derive** an implicit argument from a function that itself has implicit parameters. This eliminates the need for boilerplate wrapper functions. The candidate function can be polymorphic (the compiler infers the type instantiation) or monomorphic. + +For example, suppose `Array.compare` is declared as: + +```motoko no-repl +public func compare(a : [T], b : [T], compare : (implicit : (T, T) -> Order)) : Order +``` + +and a function requires an implicit `compare : ([Nat], [Nat]) -> Order`. Without derivation, you would need to write a wrapper: + +```motoko no-repl +module MyArray { + public func compare(a : [Nat], b : [Nat]) : Order { + Array.compare(a, b) // resolves inner `compare` to Nat.compare + }; +}; +``` + +With derivation, the compiler handles this automatically. It recognizes that `Array.compare`, after removing its implicit `compare` parameter and instantiating `T := Nat`, has the right type. It then recursively resolves the inner implicit (`Nat.compare`) and synthesizes the wrapper for you. + +This works transitively: a `compare` for `[[Nat]]` is derived via `Array.compare<[Nat]>`, which needs `[Nat]` compare, which is derived via `Array.compare`, which needs `Nat.compare` — all resolved automatically. + +The resolution depth is bounded to guarantee termination. If you encounter a depth limit, you can increase it with `--implicit-derivation-depth` or provide the argument explicitly. + +When derivation is attempted but fails (for example, because an inner implicit can't be resolved), the compiler reports which inner implicits were missing and, when applicable, a hint about which module to import. + ### Supported types The core library provides comparison functions for common types: @@ -278,7 +322,9 @@ There is no need to update existing code unless you want to take advantage of th ## Performance considerations -Implicit arguments have no runtime overhead. The comparison function is resolved at compile time, so there is no performance difference between using implicit and explicit arguments. The resulting code is identical. +Implicit arguments are resolved at compile time. +- For direct matches, the resulting code is identical to explicitly passing the argument. +- For derived implicits, the compiler synthesizes a wrapper function at each call site. This creates a small overhead per call site, which could be mitigated by caching in the future. For now, if this becomes a performance issue, consider defining the function explicitly so all call sites share a single definition. ## See also diff --git a/docs/languages/motoko/fundamentals/pattern-matching.md b/docs/languages/motoko/fundamentals/pattern-matching.md index 4f56db0c..d8d5bf67 100644 --- a/docs/languages/motoko/fundamentals/pattern-matching.md +++ b/docs/languages/motoko/fundamentals/pattern-matching.md @@ -20,6 +20,7 @@ Motoko supports several types of patterns: | Named | Introduces identifiers into a new scope. | `age`, `x` | | Tuple | Must have at least two components. | `( component0, component1, …​ )` | | Alternative (`or`-pattern) | Match multiple patterns. | `0 or 1` | +| Conjunctive (`and`-pattern) | Match both patterns; bindings combine. | `?x and s` | ## Concepts @@ -29,7 +30,7 @@ Unlike traditional `enum` types in other languages, which define fixed sets of v ### Irrefutable and refutable patterns -Patterns are either refutable** or irrefutable. A refutable pattern can fail to match (like literal patterns or specific variant tags). An irrefutable pattern always matches any value of its type. Examples include the wildcard `_`, simple variable names, or structured patterns (like records or tuples) made only from irrefutable parts. +Patterns are either **refutable** or **irrefutable**. A refutable pattern can fail to match (like literal patterns or specific variant tags). An irrefutable pattern always matches any value of its type. Examples include the wildcard `_`, simple variable names, or structured patterns (like records or tuples) made only from irrefutable parts. ### Singleton types diff --git a/docs/languages/motoko/icp-features/randomness.md b/docs/languages/motoko/icp-features/randomness.md index d185764c..aaedd55d 100644 --- a/docs/languages/motoko/icp-features/randomness.md +++ b/docs/languages/motoko/icp-features/randomness.md @@ -105,7 +105,7 @@ persistent actor { ## Resources -- [`raw_rand`](/references/ic-interface-spec/#ic-raw_rand) +- [`raw_rand`](/references/ic-interface-spec/management-canister#ic-raw_rand) - [`Random`](https://mops.one/core/docs/Random) - [`fuzz`](https://mops.one/fuzz) - [`idempotency-keys`](https://mops.one/idempotency-keys) diff --git a/docs/languages/motoko/icp-features/system-functions.md b/docs/languages/motoko/icp-features/system-functions.md index e2d8e627..a1beb372 100644 --- a/docs/languages/motoko/icp-features/system-functions.md +++ b/docs/languages/motoko/icp-features/system-functions.md @@ -7,12 +7,12 @@ title: "System functions" ICP supports five system functions that canisters can call to interact with the ICP runtime environment: -- [`timer`](/references/ic-interface-spec/#global-timer) +- [`timer`](/references/ic-interface-spec/canister-interface#global-timer) - [`preupgrade`](#preupgrade) - [`postupgrade`](#postupgrade) - [`lowmemory`](#lowmemory) -- [`inspect`](/references/ic-interface-spec/#system-api-inspect-message) -- [`heartbeat`](/references/ic-interface-spec/#heartbeat) +- [`inspect`](/references/ic-interface-spec/canister-interface#system-api-inspect-message) +- [`heartbeat`](/references/ic-interface-spec/canister-interface#heartbeat) Declaring any other system function will result in an error. Canisters can use these functions to efficiently manage state transitions, automate tasks, or handle system-level operations. @@ -122,7 +122,7 @@ The following properties apply to the low memory hook: ## `inspect()` -The [`inspect()` system function](/references/ic-interface-spec/#system-api-inspect-message) allows a canister to inspect ingress messages before execution, determining whether to accept or reject them. The function receives a record of message attributes, including the caller’s principal, the raw argument `Blob`, and a variant identifying the target function. +The [`inspect()` system function](/references/ic-interface-spec/canister-interface#system-api-inspect-message) allows a canister to inspect ingress messages before execution, determining whether to accept or reject them. The function receives a record of message attributes, including the caller’s principal, the raw argument `Blob`, and a variant identifying the target function. It returns a `Bool`, where `true` permits execution and `false` rejects the message. Similar to a [query](/references/message-execution-properties), any side effects are discarded. If `inspect()` traps, it is equivalent to returning `false`. Unlike other system functions, the argument type of `inspect()` depends on the actor's exposed interface, meaning it can selectively handle different methods or ignore unnecessary fields. @@ -179,6 +179,6 @@ Since `heartbeat()` is async, it can invoke other asynchronous functions and awa Every async call in Motoko causes a context switch, which means the actual execution of the heartbeat function may be delayed relative to when the subnet triggers it. The function’s result is ignored, so any errors or traps during execution do not impact future heartbeat calls. -If a canister exports a function named `canister_heartbeat`, it must have the type `() -> ()`, ensuring it adheres to the expected [system function signature](/references/ic-interface-spec/#heartbeat). +If a canister exports a function named `canister_heartbeat`, it must have the type `() -> ()`, ensuring it adheres to the expected [system function signature](/references/ic-interface-spec/canister-interface#heartbeat). Heartbeats should be considered deprecated as they have been superseded by timers. diff --git a/docs/languages/motoko/reference/changelog.md b/docs/languages/motoko/reference/changelog.md index 2159ac54..5803f5ba 100644 --- a/docs/languages/motoko/reference/changelog.md +++ b/docs/languages/motoko/reference/changelog.md @@ -22,6 +22,16 @@ $(dfx cache show)/moc --version # Motoko compiler changelog +## 1.8.0 (2026-05-15) + +* motoko (`moc`) + + * feat: Implicit argument derivation — the compiler can derive implicit arguments from functions that themselves have implicit parameters (e.g., `compare` for `[Nat]` from `Array.compare` + `Nat.compare`). Works transitively and is depth-limited via `--implicit-derivation-depth` (#5966). + + * feat: `and`-patterns — `p1 and p2` matches when both legs match, binding from both (#6049). + + * bugfix: M0236 dot-notation auto-fix on unparenthesized single-argument calls (e.g. `List.reverse b`) no longer rewrites them into a bare function reference (`b.reverse`), which silently turned a call into a no-op; the suggestion now produces `b.reverse()` (#6096). + ## 1.7.0 (2026-04-29) * motoko (`moc`) diff --git a/docs/languages/motoko/reference/compiler-ref.md b/docs/languages/motoko/reference/compiler-ref.md index 3be90c0f..46505522 100644 --- a/docs/languages/motoko/reference/compiler-ref.md +++ b/docs/languages/motoko/reference/compiler-ref.md @@ -52,6 +52,7 @@ You can use the following options with the `moc` command. | `--incremental-gc` | Use incremental GC (default, works with both enhanced orthogonal persistence and legacy/classical persistence). | | `--idl` | Compile binary and emit Candid IDL specification to `.did` file. | | `-i` | Runs the compiler in an interactive read–eval–print loop (REPL) shell so you can evaluate program execution (implies -r). | +| `--implicit-derivation-depth ` | Maximum recursion depth for [implicit](/languages/motoko/fundamentals/implicit-parameters) argument derivation (default 100). Raise if a complex derivation is rejected as depth-limited. | | `--legacy-persistence` | Use legacy (classical) persistence. This also enables the usage of --copying-gc, --compacting-gc, and --generational-gc. Deprecated in favor of the new enhanced orthogonal persistence, which is default. Legacy persistence will be removed in the future.| | `--map` | Outputs a JavaScript source map. | | `--max-stable-pages ` | Set maximum number of pages available for library `ExperimentStableMemory.mo` (default 65536). | diff --git a/docs/languages/motoko/reference/language-manual.md b/docs/languages/motoko/reference/language-manual.md index f766ea5d..3c3fb4a0 100644 --- a/docs/languages/motoko/reference/language-manual.md +++ b/docs/languages/motoko/reference/language-manual.md @@ -1618,7 +1618,17 @@ The or pattern ` or ` is a disjunctive pattern. The result of matching ` or ` against a value is the result of matching ``, if it succeeds, or the result of matching ``, if the first match fails. -An `or`-pattern may contain identifier (``) patterns with the restriction that both alternatives must bind the same set of identifiers. Each identifier's type is the least upper bound of its type in `` and ``. +An `or`-pattern may contain identifier (``) patterns with the restriction that both alternatives must bind the same set of identifiers. Each identifier's type is the least upper bound of the types assigned to it by `` and ``. + +### And pattern + +The and pattern ` and ` is a conjunctive pattern. + +The result of matching ` and ` against a value is the union of the bindings produced by matching `` and then ``, both against the same value. The match fails if either sub-match fails. + +Unlike an `or`-pattern, the two sides of an `and`-pattern must bind *disjoint* sets of identifiers; a name bound in both sides is a type error. + +`and` binds tighter than `or`, so ` or and ` parses as ` or ( and )`. ### Expression declaration @@ -2373,6 +2383,11 @@ the expanded function call expression `? ? < * Ds is the disambiguated set of candidates, filtered by generality. * `.` is the name of the unique disambiguation, if one exists (that is, when Ds is a singleton set). + **Implicit derivation**: When no direct candidate is found (neither from local values, module fields, nor library fields of unimported modules when `--implicit-package` is set), the compiler additionally searches for *derivable* candidates — first among local values, then among module fields, then among library fields. + A derivable candidate is a function (possibly polymorphic) that has implicit parameters of its own, and whose type, after removing its implicit parameters and instantiating its type parameters, matches the required hole type. + If the derivable candidate's own implicit parameters can be recursively resolved (up to a configurable depth limit), the compiler synthesizes a wrapper function that calls the candidate with the resolved inner implicits. + This allows, for example, an implicit `compare : ([Nat], [Nat]) -> Order` to be derived from `Array.compare` when `Nat.compare` is in scope. The derivation depth is bounded by the `--implicit-derivation-depth` flag. + The call expression ` ? ` evaluates `` to a result `r1`. If `r1` is `trap`, then the result is `trap`. Otherwise, `` (the hole expansion of ``) is evaluated to a result `r2`. If `r2` is `trap`, the expression results in `trap`.