From 491a820dbef4a8bc95904df112ce4c3629c30a01 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 5 Dec 2024 18:43:49 +0100 Subject: [PATCH 01/18] feat: add `prim deadline` for receiver-side best-effort messages (#4795) Cf. `ic0.msg_deadline` in https://github.com/dfinity/portal/pull/3764 Adds `prim "deadline"` and access to it via `func replyDeadline` in `mo:prim`. All mainnet subnets are providing the system interface API, so this is safe to deploy. Feature flag for `drun` is `Enabled`. [`motoko-base` support](dfinity/motoko-base/#677) will be merged in short order. --- Changelog.md | 11 +++++++++++ nix/sources.json | 6 +++--- src/codegen/compile_classical.ml | 21 ++++++++++++++++----- src/codegen/compile_enhanced.ml | 21 ++++++++++++++++----- src/ir_def/arrange_ir.ml | 1 + src/ir_def/check_ir.ml | 2 ++ src/ir_def/ir.ml | 4 +++- src/ir_interpreter/interpret_ir.ml | 2 ++ src/lowering/desugar.ml | 3 +++ src/mo_values/prim.ml | 1 + src/prelude/prim.mo | 4 ++++ test/fail/ok/no-timer-canc.tc.ok | 1 + test/fail/ok/no-timer-set.tc.ok | 1 + test/fail/ok/suggest-long-ai.tc.ok | 1 + test/fail/ok/suggest-short-ai.tc.ok | 1 + test/run-drun/composite-query.mo | 1 + test/run-drun/ok/composite-query.tc.ok | 4 ++-- test/run-drun/ok/query2.run-ir.ok | 2 +- test/run-drun/ok/query2.run-low.ok | 2 +- test/run-drun/ok/query2.run.ok | 2 +- test/run-drun/query2.mo | 2 ++ 21 files changed, 74 insertions(+), 19 deletions(-) diff --git a/Changelog.md b/Changelog.md index db00cebf387..56d87f3f39f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,7 @@ # Motoko compiler changelog +## 0.13.5 (FUTURE) + * motoko (`moc`) * Breaking change (minor): @@ -33,6 +35,15 @@ 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. + + * Added new primitive `replyDeadline : () -> Nat64` to obtain when a response for a best-effort message is due (#4795). + +* motoko-base + + * Added `Text.fromList` and `Text.toList` functions (dfinity/motoko-base#676). + + * Added `Text.fromArray/fromVarArray` functions (dfinity/motoko-base#674). + ## 0.13.4 (2024-11-29) * motoko (`moc`) diff --git a/nix/sources.json b/nix/sources.json index 9120bf939fc..cc6d4ab383e 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -26,10 +26,10 @@ "homepage": "", "owner": "luc-blaeser", "repo": "ic", - "rev": "33075cd385ea2ec4170f522406b1ff8f507fa744", - "sha256": "0swx7r78wjybx7fkfqsn9p3lqxmszgg24q4hrnxmscvyhb22hqia", + "rev": "bebe89514a6abd26e940b295323823169911a965", + "sha256": "1g68fyi5acbcgs2kjribk97fj8ki5g6pd99nwl5azz1rw1b0xycx", "type": "tarball", - "url": "https://github.com/luc-blaeser/ic/archive/33075cd385ea2ec4170f522406b1ff8f507fa744.tar.gz", + "url": "https://github.com/luc-blaeser/ic/archive/bebe89514a6abd26e940b295323823169911a965.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "ic-hs": { diff --git a/src/codegen/compile_classical.ml b/src/codegen/compile_classical.ml index e21c5f2eb39..a16282ca4db 100644 --- a/src/codegen/compile_classical.ml +++ b/src/codegen/compile_classical.ml @@ -5086,6 +5086,7 @@ module IC = struct E.add_func_import env "ic0" "msg_reject" (i32s 2) []; E.add_func_import env "ic0" "msg_reply_data_append" (i32s 2) []; E.add_func_import env "ic0" "msg_reply" [] []; + E.add_func_import env "ic0" "msg_deadline" [] [I64Type]; E.add_func_import env "ic0" "performance_counter" [I32Type] [I64Type]; E.add_func_import env "ic0" "trap" (i32s 2) []; E.add_func_import env "ic0" "stable64_write" (i64s 3) []; @@ -5351,7 +5352,7 @@ module IC = struct (fun env -> system_call env "msg_caller_copy") (fun env -> compile_unboxed_const 0l) | _ -> - E.trap_with env (Printf.sprintf "cannot get caller when running locally") + E.trap_with env "cannot get caller when running locally" let method_name env = match E.mode env with @@ -5361,7 +5362,7 @@ module IC = struct (fun env -> system_call env "msg_method_name_copy") (fun env -> compile_unboxed_const 0l) | _ -> - E.trap_with env (Printf.sprintf "cannot get method_name when running locally") + E.trap_with env "cannot get method_name when running locally" let arg_data env = match E.mode env with @@ -5371,7 +5372,14 @@ module IC = struct (fun env -> system_call env "msg_arg_data_copy") (fun env -> compile_unboxed_const 0l) | _ -> - E.trap_with env (Printf.sprintf "cannot get arg_data when running locally") + E.trap_with env "cannot get arg_data when running locally" + + let deadline env = + match E.mode env with + | Flags.(ICMode | RefMode) -> + system_call env "msg_deadline" + | _ -> + E.trap_with env "cannot get deadline when running locally" let reject env arg_instrs = match E.mode env with @@ -5381,7 +5389,7 @@ module IC = struct Blob.as_ptr_len env ^^ system_call env "msg_reject" | _ -> - E.trap_with env (Printf.sprintf "cannot reject when running locally") + E.trap_with env "cannot reject when running locally" let error_code env = Func.share_code0 Func.Always env "error_code" [I32Type] (fun env -> @@ -12095,7 +12103,7 @@ and compile_prim_invocation (env : E.t) ae p es at = Serialization.serialize env ts ^^ IC.reply_with_data env | _ -> - E.trap_with env (Printf.sprintf "cannot reply when running locally") + E.trap_with env "cannot reply when running locally" end | ICRejectPrim, [e] -> @@ -12144,6 +12152,9 @@ and compile_prim_invocation (env : E.t) ae p es at = | ICMethodNamePrim, [] -> SR.Vanilla, IC.method_name env + | ICReplyDeadlinePrim, [] -> + SR.UnboxedWord64 Type.Nat64, IC.deadline env + | ICStableRead ty, [] -> (* * On initial install: diff --git a/src/codegen/compile_enhanced.ml b/src/codegen/compile_enhanced.ml index 03699d03789..61d21e839f5 100644 --- a/src/codegen/compile_enhanced.ml +++ b/src/codegen/compile_enhanced.ml @@ -4744,6 +4744,7 @@ module IC = struct E.add_func_import env "ic0" "msg_reject" (i64s 2) []; E.add_func_import env "ic0" "msg_reply_data_append" (i64s 2) []; E.add_func_import env "ic0" "msg_reply" [] []; + E.add_func_import env "ic0" "msg_deadline" [] [I64Type]; E.add_func_import env "ic0" "performance_counter" [I32Type] [I64Type]; E.add_func_import env "ic0" "trap" (i64s 2) []; E.add_func_import env "ic0" "stable64_write" (i64s 3) []; @@ -5071,7 +5072,7 @@ module IC = struct system_call env "msg_caller_copy") (fun env -> compile_unboxed_const 0L) | _ -> - E.trap_with env (Printf.sprintf "cannot get caller when running locally") + E.trap_with env "cannot get caller when running locally" let method_name env = match E.mode env with @@ -5083,7 +5084,7 @@ module IC = struct system_call env "msg_method_name_copy") (fun env -> compile_unboxed_const 0L) | _ -> - E.trap_with env (Printf.sprintf "cannot get method_name when running locally") + E.trap_with env "cannot get method_name when running locally" let arg_data env = match E.mode env with @@ -5095,7 +5096,14 @@ module IC = struct system_call env "msg_arg_data_copy") (fun env -> compile_unboxed_const 0L) | _ -> - E.trap_with env (Printf.sprintf "cannot get arg_data when running locally") + E.trap_with env "cannot get arg_data when running locally" + + let deadline env = + match E.mode env with + | Flags.(ICMode | RefMode) -> + system_call env "msg_deadline" + | _ -> + E.trap_with env "cannot get deadline when running locally" let reject env arg_instrs = match E.mode env with @@ -5105,7 +5113,7 @@ module IC = struct Blob.as_ptr_len env ^^ system_call env "msg_reject" | _ -> - E.trap_with env (Printf.sprintf "cannot reject when running locally") + E.trap_with env "cannot reject when running locally" let error_code env = Func.share_code0 Func.Always env "error_code" [I64Type] (fun env -> @@ -12190,7 +12198,7 @@ and compile_prim_invocation (env : E.t) ae p es at = Serialization.serialize env ts ^^ IC.reply_with_data env | _ -> - E.trap_with env (Printf.sprintf "cannot reply when running locally") + E.trap_with env "cannot reply when running locally" end | ICRejectPrim, [e] -> @@ -12239,6 +12247,9 @@ and compile_prim_invocation (env : E.t) ae p es at = | ICMethodNamePrim, [] -> SR.Vanilla, IC.method_name env + | ICReplyDeadlinePrim, [] -> + SR.UnboxedWord64 Type.Nat64, IC.deadline env + | ICStableRead ty, [] -> SR.Vanilla, Persistence.load env ty diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 02cb40bde7d..b0f110029fb 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -118,6 +118,7 @@ and prim = function | ICCallPrim -> Atom "ICCallPrim" | ICCallRawPrim -> Atom "ICCallRawPrim" | ICMethodNamePrim -> Atom "ICMethodNamePrim" + | ICReplyDeadlinePrim -> Atom "ICReplyDeadlinePrim" | ICStableWrite t -> "ICStableWrite" $$ [typ t] | ICStableRead t -> "ICStableRead" $$ [typ t] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 0d9f45279a6..37e84da5623 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -627,6 +627,8 @@ let rec check_exp env (exp:Ir.exp) : unit = T.unit <: t | ICMethodNamePrim, [] -> T.text <: t + | ICReplyDeadlinePrim, [] -> + T.nat64 <: t | ICStableRead t1, [] -> check_typ env t1; check (store_typ t1) "Invalid type argument to ICStableRead"; diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 18b28c8b9ff..192a7453446 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -175,6 +175,7 @@ and prim = | ICCallPrim | ICCallRawPrim | ICMethodNamePrim + | ICReplyDeadlinePrim | ICArgDataPrim | ICStableWrite of Type.typ (* serialize value of stable type to stable memory *) | ICStableRead of Type.typ (* deserialize value of stable type from stable memory *) @@ -322,7 +323,8 @@ let map_prim t_typ t_id p = | ICCallerPrim | ICCallPrim | ICCallRawPrim - | ICMethodNamePrim -> p + | ICMethodNamePrim + | ICReplyDeadlinePrim -> p | ICStableWrite t -> ICStableWrite (t_typ t) | ICStableRead t -> ICStableRead (t_typ t) | ICStableSize t -> ICStableSize (t_typ t) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 6c0e5301013..ce426ac2f85 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -462,6 +462,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = f (V.Tup[vc; kv; rv; cv]) v2 k | ICCallerPrim, [] -> k env.caller + | ICReplyDeadlinePrim, [] -> + k (V.Nat64 Numerics.Nat64.zero) | ICStableRead t, [] -> let (_, tfs) = T.as_obj t in let ve = List.fold_left diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index d79d3ccb942..7049a6d8a6c 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -166,6 +166,9 @@ and exp' at note = function | S.CallE ({it=S.AnnotE ({it=S.PrimE "caller";_},_);_}, _, {it=S.TupE es;_}) -> assert (es = []); I.PrimE (I.ICCallerPrim, []) + | S.CallE ({it=S.AnnotE ({it=S.PrimE "deadline";_},_);_}, _, {it=S.TupE es;_}) -> + assert (es = []); + I.PrimE (I.ICReplyDeadlinePrim, []) | S.CallE ({it=S.AnnotE ({it=S.PrimE "time";_},_);_}, _, {it=S.TupE es;_}) -> assert (es = []); I.PrimE (I.SystemTimePrim, []) diff --git a/src/mo_values/prim.ml b/src/mo_values/prim.ml index 0248598a95a..a9cd01ad965 100644 --- a/src/mo_values/prim.ml +++ b/src/mo_values/prim.ml @@ -229,6 +229,7 @@ let prim trap = | "rts_upgrade_instructions") -> fun _ v k -> as_unit v; k (Int (Int.of_int 0)) | "time" -> fun _ v k -> as_unit v; k (Value.Nat64 (Numerics.Nat64.of_int 42)) + | "deadline" -> fun _ v k -> as_unit v; k (Value.Nat64 Numerics.Nat64.zero) | "idlHash" -> fun _ v k -> let s = as_text v in k (Nat32 (Nat32.wrapping_of_big_int (Big_int.big_int_of_int32 (Lib.Uint32.to_int32 (Idllib.IdlHash.idl_hash s))))) diff --git a/src/prelude/prim.mo b/src/prelude/prim.mo index 209337400e0..1ccda0c81ee 100644 --- a/src/prelude/prim.mo +++ b/src/prelude/prim.mo @@ -304,6 +304,10 @@ func error(message : Text) : Error { func errorCode(e : Error) : ErrorCode = ((prim "cast" : Error -> (ErrorCode, Text)) e).0; func errorMessage(e : Error) : Text = ((prim "cast" : Error -> (ErrorCode, Text)) e).1; +// Message deadline (best-effort messaging) + +func replyDeadline() : Nat64 = (prim "deadline" : () -> Nat64) (); + // Time func time() : Nat64 = (prim "time" : () -> Nat64)(); diff --git a/test/fail/ok/no-timer-canc.tc.ok b/test/fail/ok/no-timer-canc.tc.ok index e1877945e59..a78867d5f6e 100644 --- a/test/fail/ok/no-timer-canc.tc.ok +++ b/test/fail/ok/no-timer-canc.tc.ok @@ -204,6 +204,7 @@ no-timer-canc.mo:3.10-3.21: type error [M0119], object field cancelTimer is not regionStoreNat32 : (Region, Nat64, Nat32) -> (); regionStoreNat64 : (Region, Nat64, Nat64) -> (); regionStoreNat8 : (Region, Nat64, Nat8) -> (); + replyDeadline : () -> Nat64; rts_callback_table_count : () -> Nat; rts_callback_table_size : () -> Nat; rts_collector_instructions : () -> Nat; diff --git a/test/fail/ok/no-timer-set.tc.ok b/test/fail/ok/no-timer-set.tc.ok index f4951c74796..f539873cf9e 100644 --- a/test/fail/ok/no-timer-set.tc.ok +++ b/test/fail/ok/no-timer-set.tc.ok @@ -204,6 +204,7 @@ no-timer-set.mo:3.10-3.18: type error [M0119], object field setTimer is not cont regionStoreNat32 : (Region, Nat64, Nat32) -> (); regionStoreNat64 : (Region, Nat64, Nat64) -> (); regionStoreNat8 : (Region, Nat64, Nat8) -> (); + replyDeadline : () -> Nat64; rts_callback_table_count : () -> Nat; rts_callback_table_size : () -> Nat; rts_collector_instructions : () -> Nat; diff --git a/test/fail/ok/suggest-long-ai.tc.ok b/test/fail/ok/suggest-long-ai.tc.ok index 7f50d74de08..e7ecd37f791 100644 --- a/test/fail/ok/suggest-long-ai.tc.ok +++ b/test/fail/ok/suggest-long-ai.tc.ok @@ -205,6 +205,7 @@ suggest-long-ai.mo:4.1-4.5: type error [M0072], field stableM does not exist in regionStoreNat32 : (Region, Nat64, Nat32) -> (); regionStoreNat64 : (Region, Nat64, Nat64) -> (); regionStoreNat8 : (Region, Nat64, Nat8) -> (); + replyDeadline : () -> Nat64; rts_callback_table_count : () -> Nat; rts_callback_table_size : () -> Nat; rts_collector_instructions : () -> Nat; diff --git a/test/fail/ok/suggest-short-ai.tc.ok b/test/fail/ok/suggest-short-ai.tc.ok index da8382a1215..50afa55780a 100644 --- a/test/fail/ok/suggest-short-ai.tc.ok +++ b/test/fail/ok/suggest-short-ai.tc.ok @@ -205,6 +205,7 @@ suggest-short-ai.mo:4.1-4.5: type error [M0072], field s does not exist in type: regionStoreNat32 : (Region, Nat64, Nat32) -> (); regionStoreNat64 : (Region, Nat64, Nat64) -> (); regionStoreNat8 : (Region, Nat64, Nat8) -> (); + replyDeadline : () -> Nat64; rts_callback_table_count : () -> Nat; rts_callback_table_size : () -> Nat; rts_collector_instructions : () -> Nat; diff --git a/test/run-drun/composite-query.mo b/test/run-drun/composite-query.mo index 30695acad59..1aa83a93a11 100644 --- a/test/run-drun/composite-query.mo +++ b/test/run-drun/composite-query.mo @@ -16,6 +16,7 @@ actor Composites { }; public composite query func cq1() : async () { + assert 0 : Nat64 == Prim.replyDeadline(); }; public composite query func cq2() : async () { diff --git a/test/run-drun/ok/composite-query.tc.ok b/test/run-drun/ok/composite-query.tc.ok index 771ebcfc7fb..a312e5e19e8 100644 --- a/test/run-drun/ok/composite-query.tc.ok +++ b/test/run-drun/ok/composite-query.tc.ok @@ -1,8 +1,8 @@ -composite-query.mo:30.11-30.13: warning [M0145], this pattern of type +composite-query.mo:31.11-31.13: warning [M0145], this pattern of type ?Class__1 does not cover value null -composite-query.mo:35.11-35.13: warning [M0145], this pattern of type +composite-query.mo:36.11-36.13: warning [M0145], this pattern of type ?Class__1 does not cover value null diff --git a/test/run-drun/ok/query2.run-ir.ok b/test/run-drun/ok/query2.run-ir.ok index 61bf2dcd7f0..2d5d7ae3f3b 100644 --- a/test/run-drun/ok/query2.run-ir.ok +++ b/test/run-drun/ok/query2.run-ir.ok @@ -9,4 +9,4 @@ In read: 6 6 The following fails in the interpreter, for lack of query semantics -query2.mo:35.4-35.18: execution error, assertion failure +query2.mo:37.4-37.18: execution error, assertion failure diff --git a/test/run-drun/ok/query2.run-low.ok b/test/run-drun/ok/query2.run-low.ok index 61bf2dcd7f0..2d5d7ae3f3b 100644 --- a/test/run-drun/ok/query2.run-low.ok +++ b/test/run-drun/ok/query2.run-low.ok @@ -9,4 +9,4 @@ In read: 6 6 The following fails in the interpreter, for lack of query semantics -query2.mo:35.4-35.18: execution error, assertion failure +query2.mo:37.4-37.18: execution error, assertion failure diff --git a/test/run-drun/ok/query2.run.ok b/test/run-drun/ok/query2.run.ok index 61bf2dcd7f0..2d5d7ae3f3b 100644 --- a/test/run-drun/ok/query2.run.ok +++ b/test/run-drun/ok/query2.run.ok @@ -9,4 +9,4 @@ In read: 6 6 The following fails in the interpreter, for lack of query semantics -query2.mo:35.4-35.18: execution error, assertion failure +query2.mo:37.4-37.18: execution error, assertion failure diff --git a/test/run-drun/query2.mo b/test/run-drun/query2.mo index 0c29847042d..34d097d3b74 100644 --- a/test/run-drun/query2.mo +++ b/test/run-drun/query2.mo @@ -6,12 +6,14 @@ actor counter = { Prim.debugPrintNat c; }; public func printCounter () : async () { + assert 0 : Nat64 == Prim.replyDeadline(); Prim.debugPrintNat c; }; public func get() : async Nat { return c }; public query func read() : async Nat { + assert 0 : Nat64 == Prim.replyDeadline(); let tmp = c; c += 1; Prim.debugPrint "In read:"; From a57dddcc8e08c92a799002cceca0da1d4c3431dc Mon Sep 17 00:00:00 2001 From: Ryan Vandersmith Date: Thu, 5 Dec 2024 13:44:17 -0800 Subject: [PATCH 02/18] docs: update links for new docs validation (#4797) Modifies the docs to account for new URL validation in https://github.com/dfinity/portal/pull/3847. --- doc/md/base/OrderedMap.md | 2 +- doc/md/base/OrderedSet.md | 2 +- doc/md/base/RBTree.md | 2 +- doc/md/writing-motoko/pattern-matching.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/md/base/OrderedMap.md b/doc/md/base/OrderedMap.md index 6a2302f3fc8..e5c371c2971 100644 --- a/doc/md/base/OrderedMap.md +++ b/doc/md/base/OrderedMap.md @@ -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](http://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](https://www.cs.ukc.ac.uk/people/staff/smk/redblack/rb.html). ## Type `Map` ``` motoko no-repl diff --git a/doc/md/base/OrderedSet.md b/doc/md/base/OrderedSet.md index 97495b55ef3..cbe98e20b8c 100644 --- a/doc/md/base/OrderedSet.md +++ b/doc/md/base/OrderedSet.md @@ -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](http://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](https://www.cs.ukc.ac.uk/people/staff/smk/redblack/rb.html). ## Type `Set` ``` motoko no-repl diff --git a/doc/md/base/RBTree.md b/doc/md/base/RBTree.md index c767a247325..7f5c17f8f24 100644 --- a/doc/md/base/RBTree.md +++ b/doc/md/base/RBTree.md @@ -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](http://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](https://www.cs.ukc.ac.uk/people/staff/smk/redblack/rb.html). ## Type `Color` ``` motoko no-repl diff --git a/doc/md/writing-motoko/pattern-matching.md b/doc/md/writing-motoko/pattern-matching.md index 25c76155660..e4bd0850549 100644 --- a/doc/md/writing-motoko/pattern-matching.md +++ b/doc/md/writing-motoko/pattern-matching.md @@ -130,6 +130,6 @@ These blocks allow for safe unwrapping of optional values using a postfix `!` op Each use of `!` within the block is equivalent to a switch statement on an option, but with an added benefit: if `!` is applied to a `null` value, the entire block immediately abandons execution and returns `null`. This short-circuiting behavior simplifies the handling of multiple optional values in a more concise and readable manner. -For an example, see [option blocks and null breaks](control-flow#option-blocks-and-null-breaks). +For an example, see [option blocks and null breaks](./control-flow#option-blocks-and-null-breaks). Logo \ No newline at end of file From 947438f449065ee33ea7593855adac153a051680 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 5 Dec 2024 22:59:14 +0000 Subject: [PATCH 03/18] bugfix: bound subtyping depth to avoid reliance on unpredictable stack overflow (#4798) * repro for subtyping loop due to polymorhic recursion * Update test/fail/polyrec.mo * Update test/fail/polyrec.mo Co-authored-by: Gabor Greif * hack subtyping to accept polyrec.mo by treating equivalent instanstations of the same constructor as related by subtyping * add bound to subtyping instead of relying on unpredictable and expensive OOM/stackoverflow * tidy * missin file? * turn overflow into error (WIP) * add error code desc; use dedicated exception Undecided * Update src/lang_utils/error_codes/M0200.md * check issue-3057 * Update test/fail/issue-3057.mo --------- Co-authored-by: Gabor Greif --- src/lang_utils/error_codes.ml | 1 + src/lang_utils/error_codes/M0200.md | 44 ++++++++++++++ src/mo_frontend/typing.ml | 87 ++++++++++++++++----------- src/mo_types/type.ml | 91 +++++++++++++++-------------- src/mo_types/type.mli | 3 + test/fail/issue-3057.mo | 7 +++ test/fail/ok/issue-3057.tc.ok | 1 + test/fail/ok/issue-3057.tc.ret.ok | 1 + test/fail/ok/polyrec.tc.ok | 1 + test/fail/ok/polyrec.tc.ret.ok | 1 + test/fail/polyrec.mo | 13 +++++ test/run.sh | 4 +- 12 files changed, 175 insertions(+), 79 deletions(-) create mode 100644 src/lang_utils/error_codes/M0200.md create mode 100644 test/fail/issue-3057.mo create mode 100644 test/fail/ok/issue-3057.tc.ok create mode 100644 test/fail/ok/issue-3057.tc.ret.ok create mode 100644 test/fail/ok/polyrec.tc.ok create mode 100644 test/fail/ok/polyrec.tc.ret.ok create mode 100644 test/fail/polyrec.mo diff --git a/src/lang_utils/error_codes.ml b/src/lang_utils/error_codes.ml index 16cbd291704..5d7c4b1f70f 100644 --- a/src/lang_utils/error_codes.ml +++ b/src/lang_utils/error_codes.ml @@ -203,4 +203,5 @@ let error_codes : (string * string option) list = "M0197", Some([%blob "lang_utils/error_codes/M0197.md"]); (* `system` capability required *) "M0198", Some([%blob "lang_utils/error_codes/M0198.md"]); (* Unused field pattern warning *) "M0199", Some([%blob "lang_utils/error_codes/M0199.md"]); (* Deprecate experimental stable memory *) + "M0200", Some([%blob "lang_utils/error_codes/M0200.md"]) (* Cannot determine subtyping or equality *) ] diff --git a/src/lang_utils/error_codes/M0200.md b/src/lang_utils/error_codes/M0200.md new file mode 100644 index 00000000000..b27c2882cd0 --- /dev/null +++ b/src/lang_utils/error_codes/M0200.md @@ -0,0 +1,44 @@ +# M0200 + +This error means that the compiler encountered a subtyping, equivalence or constructor equivalence problem that it cannot decide is true or false in a timely manner. + +This is due to a limitation of the type system and may require you to rewrite +some of your code to avoid the problem. + +The most like cause is a recursive type or class whose definition involves +instantiating the type or class with nested type parameters. + +For example, this definition of `Box` + +``` motoko +class Box(v : T) { + public let value = t; + public func map(f : T -> R) : Box { + Box(f t) + }; +} +``` +is problematic because `Box` is instantiated at `R`, an inner type parameter, while + +``` motoko +class Box(v : T) { + public let value = v; + public func map(f : T -> T) : Box { + Box(f value) + }; +} +``` +is accepted (but also less useful). + +Another workaround is to define the problematic method as a separate +function, outside of the class: + +``` motoko +class Box(v : T) { + public let value = v +}; + +func map(b : Box, f : T -> R) : Box { + Box(f(b.value)) +}; +``` diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 632f51eb92d..eb0c2c36051 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -333,6 +333,23 @@ let disjoint_union env at code fmt env1 env2 = with T.Env.Clash k -> error env at code fmt k +let sub env at t1 t2 = + try T.sub t1 t2 with T.Undecided -> + error env at "M0200" "cannot decide subtyping between type%a\nand%a" + display_typ_expand t1 + display_typ_expand t2 + +let eq env at t1 t2 = + try T.eq t1 t2 with T.Undecided -> + error env at "M0200" "cannot decide equality between type%a\nand%a" + display_typ_expand t1 + display_typ_expand t2 + + +let eq_kind env at k1 k2 = + try T.eq_kind k1 k2 with T.Undecided -> + error env at "M0200" "cannot decide type constructor equality" + (* Coverage *) let coverage' warnOrError category env f x t at = @@ -562,7 +579,7 @@ let associated_region env typ at = | Some r -> Printf.sprintf "\n scope %s is %s" (T.string_of_typ_expand typ) (string_of_region r); | None -> - if T.eq typ (T.Con(C.top_cap,[])) then + if eq env at typ (T.Con(C.top_cap,[])) then Printf.sprintf "\n scope %s is the global scope" (T.string_of_typ_expand typ) else "" @@ -759,7 +776,7 @@ and check_typ' env typ : T.typ = error env typ2.at "M0168" "cannot compute intersection of types containing recursive or forward references to other type definitions" in - if not env.pre && T.sub t T.Non && not (T.sub t1 T.Non || T.sub t2 T.Non) then + if not env.pre && sub env typ.at t T.Non && not (sub env typ1.at t1 T.Non || sub env typ2.at t2 T.Non) then warn env typ.at "M0166" "this intersection results in type%a\nbecause operand types are inconsistent,\nleft operand is%a\nright operand is%a" display_typ t @@ -773,7 +790,7 @@ and check_typ' env typ : T.typ = error env typ2.at "M0168" "cannot compute union of types containing recursive or forward references to other type definitions" in - if not env.pre && T.sub T.Any t && not (T.sub T.Any t1 || T.sub T.Any t2) then + if not env.pre && sub env typ.at T.Any t && not (sub env typ1.at T.Any t1 || sub env typ2.at T.Any t2) then warn env typ.at "M0167" "this union results in type%a\nbecause operand types are inconsistent,\nleft operand is%a\nright operand is%a" display_typ t @@ -862,7 +879,7 @@ and check_typ_binds env typ_binds : T.con list * T.bind list * Scope.typ_env * S List.iter2 (fun c k -> match Cons.kind c with | T.Abs (_, T.Pre) -> T.set_kind c k - | k' -> assert (T.eq_kind k k') + | k' -> assert (eq_kind env Source.no_region k k') ) cs ks; let env' = add_typs env xs cs in let _ = List.map (fun typ_bind -> check_typ env' typ_bind.it.bound) typ_binds in @@ -891,7 +908,7 @@ and check_typ_bounds env (tbs : T.bind list) (ts : T.typ list) ats at = | tb::tbs', t::ts', at'::ats' -> if not env.pre then let u = T.open_ ts tb.T.bound in - if not (T.sub t u) then + if not (sub env at' t u) then local_error env at' "M0046" "type argument%a\ndoes not match parameter bound%a" display_typ_expand t @@ -1132,7 +1149,7 @@ let check_lit env t lit at suggest = lit := BlobLit s | t, _ -> let t' = T.Prim (infer_lit env lit at) in - if not (T.sub t' t) then + if not (sub env at t' t) then error env at "M0050" "literal of type%a\ndoes not have expected type%a%s" display_typ t' @@ -1254,7 +1271,7 @@ and infer_exp'' env exp : T.typ = assert (!ot = Type.Pre); if not (Operator.has_binop op t) then error_bin_op env exp.at t1 t2 - else if op = Operator.SubOp && T.eq t T.nat then + else if op = Operator.SubOp && eq env exp.at t T.nat then warn env exp.at "M0155" "operator may trap for inferred type%a" display_typ_expand t; ot := t @@ -1267,8 +1284,8 @@ and infer_exp'' env exp : T.typ = let t = Operator.type_relop op (T.lub (T.promote t1) (T.promote t2)) in if not (Operator.has_relop op t) then error_bin_op env exp.at t1 t2; - if not (T.eq t t1 || T.eq t t2) && not (T.sub T.nat t1 && T.sub T.nat t2) then - if T.eq t1 t2 then + if not (eq env exp1.at t t1 || eq env exp2.at t t2) && not (sub env exp1.at T.nat t1 && sub env exp2.at T.nat t2) then + if eq env exp.at t1 t2 then warn env exp.at "M0061" "comparing abstract type%a\nto itself at supertype%a" display_typ_expand t1 @@ -1362,7 +1379,7 @@ and infer_exp'' env exp : T.typ = begin match env.pre, typ_opt with | false, (_, Some typ) -> let t' = check_typ env' typ in - if not (T.sub t t') then + if not (sub env exp.at t t') then local_error env exp.at "M0192" "body of type%a\ndoes not match expected type%a" display_typ_expand t @@ -1396,11 +1413,11 @@ and infer_exp'' env exp : T.typ = let ambiguous_fields ft1 ft2 = homonymous_fields ft1 ft2 && (* allow equivalent type fields *) - T.(match ft1.typ, ft2.typ with + match ft1.T.typ, ft2.T.typ with (* homonymous type fields are ambiguous when unequal *) - | Typ c1, Typ c2 -> not (T.eq ft1.typ ft2.typ) + | T.Typ c1, T.Typ c2 -> not (eq env exp.at ft1.T.typ ft2.T.typ) (* homonymous value fields are always ambiguous *) - | _ -> true) + | _ -> true in (* field disjointness of stripped bases *) @@ -1643,7 +1660,7 @@ and infer_exp'' env exp : T.typ = let _, tfs = T.as_obj_sub ["next"] t1 in let t = T.lookup_val_field "next" tfs in let t1, t2 = T.as_mono_func_sub t in - if not (T.sub T.unit t1) then raise (Invalid_argument ""); + if not (sub env exp1.at T.unit t1) then raise (Invalid_argument ""); let t2' = T.as_opt_sub t2 in let ve = check_pat_exhaustive warn env t2' pat in check_exp_strong (adjoin_vals env ve) T.unit exp2 @@ -1715,7 +1732,7 @@ and infer_exp'' env exp : T.typ = let t1 = infer_exp_promote env exp1 in (try let (t2, t3) = T.as_async_sub s t0 t1 in - if not (T.eq t0 t2) then begin + if not (eq env exp.at t0 t2) then begin local_error env exp1.at "M0087" "ill-scoped await: expected async type from current scope %s, found async type from other scope %s%s%s" (T.string_of_typ_expand t0) @@ -1748,7 +1765,7 @@ and infer_exp'' env exp : T.typ = | IgnoreE exp1 -> if not env.pre then begin check_exp_strong env T.Any exp1; - if T.sub exp1.note.note_typ T.unit then + if sub env exp1.at exp1.note.note_typ T.unit then warn env exp.at "M0089" "redundant ignore, operand already has type ()" end; T.unit @@ -1812,14 +1829,14 @@ and check_exp' env0 t exp : T.typ = ot := t; check_exp env t exp1; check_exp env t exp2; - if env.weak && op = Operator.SubOp && T.eq t T.nat then + if env.weak && op = Operator.SubOp && eq env exp.at t T.nat then warn env exp.at "M0155" "operator may trap for inferred type%a" display_typ_expand t; t | ToCandidE exps, _ -> if not env.pre then begin let ts = List.map (infer_exp env) exps in - if not (T.sub (T.Prim T.Blob) t) then + if not (sub env exp.at (T.Prim T.Blob) t) then error env exp.at "M0172" "to_candid produces a Blob that is not a subtype of%a" display_typ_expand t; if not (T.shared (T.seq ts)) then @@ -1881,7 +1898,7 @@ and check_exp' env0 t exp : T.typ = else "Use keyword 'async*' (not 'async') to produce the expected type.") end; - if not (T.eq t1 t1') then begin + if not (eq env exp.at t1 t1') then begin local_error env exp.at "M0092" "async at scope%a\ncannot produce expected scope%a%s%s" display_typ_expand t1 @@ -1942,7 +1959,7 @@ and check_exp' env0 t exp : T.typ = "%sshared function does not match expected %sshared function type" (if sort = T.Local then "non-" else "") (if s = T.Local then "non-" else ""); - if not (T.sub t2 codom) then + if not (sub env Source.no_region t2 codom) then error env exp.at "M0095" "function return type%a\ndoes not match expected return type%a" display_typ_expand t2 @@ -1957,7 +1974,7 @@ and check_exp' env0 t exp : T.typ = t | CallE (exp1, inst, exp2), _ -> let t' = infer_call env exp1 inst exp2 exp.at (Some t) in - if not (T.sub t' t) then + if not (sub env exp1.at t' t) then local_error env0 exp.at "M0096" "expression of type%a\ncannot produce expected type%a" display_typ_expand t' @@ -1969,7 +1986,7 @@ and check_exp' env0 t exp : T.typ = t | _ -> let t' = infer_exp env0 exp in - if not (T.sub t' t) then + if not (sub env exp.at t' t) then begin local_error env0 exp.at "M0096" "expression of type%a\ncannot produce expected type%a%s" @@ -2243,22 +2260,22 @@ and check_pat_aux' env t pat val_kind : Scope.val_env = T.Env.singleton id.it (t, id.at, val_kind) | LitP lit -> if not env.pre then begin - let t' = if T.eq t T.nat then T.int else t in (* account for Nat <: Int *) + let t' = if eq env pat.at t T.nat then T.int else t in (* account for Nat <: Int *) if T.opaque t' then error env pat.at "M0110" "literal pattern cannot consume expected type%a" display_typ_expand t; - if T.sub t' T.Non + if sub env pat.at t' T.Non then ignore (infer_lit env lit pat.at) else check_lit env t' lit pat.at false end; T.Env.empty | SignP (op, lit) -> if not env.pre then begin - let t' = if T.eq t T.nat then T.int else t in (* account for Nat <: Int *) + let t' = if eq env pat.at t T.nat then T.int else t in (* account for Nat <: Int *) if not (Operator.has_unop op (T.promote t)) then error env pat.at "M0111" "operator pattern cannot consume expected type%a" display_typ_expand t; - if T.sub t' T.Non + if sub env pat.at t' T.Non then ignore (infer_lit env lit pat.at) else check_lit env t' lit pat.at false end; @@ -2308,7 +2325,7 @@ and check_pat_aux' env t pat val_kind : Scope.val_env = T.Env.merge (fun _ -> Lib.Option.map2 merge_entries) ve1 ve2 | AnnotP (pat1, typ) -> let t' = check_typ env typ in - if not (T.sub t t') then + if not (sub env pat.at t t') then error env pat.at "M0117" "pattern of type%a\ncannot consume expected type%a" display_typ_expand t' @@ -2544,7 +2561,7 @@ and check_system_fields env sort scope tfs dec_fields = if vis = System then begin let (t1, _, _) = T.Env.find id.it scope.Scope.val_env in - if not (T.sub t1 t) then + if not (sub env id.at t1 t) then local_error env df.at "M0127" "system function %s is declared with type%a\ninstead of expected type%a" id.it display_typ t1 display_typ t @@ -2704,7 +2721,7 @@ and infer_dec env dec : T.typ = warn env dec.at "M0135" "actor classes with non non-async return types are deprecated; please declare the return type as 'async ...'"; let t'' = check_typ env'' typ in - if not (T.sub t' t'') then + if not (sub env dec.at t' t'') then local_error env dec.at "M0134" "class body of type%a\ndoes not match expected type%a" display_typ_expand t' @@ -2732,7 +2749,7 @@ and check_block env t decs at : Scope.t = and check_block_exps env t decs at = match decs with | [] -> - if not (T.sub T.unit t) then + if not (sub env at T.unit t) then local_error env at "M0136" "empty block cannot produce expected type%a" display_typ_expand t | [dec] -> @@ -2748,7 +2765,7 @@ and check_dec env t dec = dec.note <- exp.note | _ -> let t' = infer_dec env dec in - if not (T.eq t T.unit || T.sub t' t) then + if not (eq env dec.at t T.unit || sub env dec.at t' t) then local_error env dec.at "M0096" "expression of type%a\ncannot produce expected type%a" display_typ_expand t' @@ -2910,7 +2927,7 @@ and infer_dec_typdecs env dec : Scope.t = let c = T.Env.find id.it env.typs in Scope.{ empty with typ_env = T.Env.singleton id.it c; - con_env = infer_id_typdecs id c k; + con_env = infer_id_typdecs env dec.at id c k; } | ClassD (shared_pat, id, binds, pat, _typ_opt, obj_sort, self_id, dec_fields) -> let c = T.Env.find id.it env.typs in @@ -2933,14 +2950,14 @@ and infer_dec_typdecs env dec : Scope.t = check_closed env id k dec.at; Scope.{ empty with typ_env = T.Env.singleton id.it c; - con_env = infer_id_typdecs id c k; + con_env = infer_id_typdecs env dec.at id c k; } -and infer_id_typdecs id c k : Scope.con_env = +and infer_id_typdecs env at id c k : Scope.con_env = assert (match k with T.Abs (_, T.Pre) -> false | _ -> true); (match Cons.kind c with | T.Abs (_, T.Pre) -> T.set_kind c k; id.note <- Some c - | k' -> assert (T.eq_kind k' k) (* may diverge on expansive types *) + | k' -> assert (eq_kind env at k' k) (* may diverge on expansive types *) ); T.ConSet.singleton c diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index bc8aeb5b451..3c0b25609ff 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -904,13 +904,18 @@ let str = ref (fun _ -> failwith "") exception PreEncountered +exception Undecided module SS = Set.Make (OrdPair) -let rel_list p rel eq xs1 xs2 = - try List.for_all2 (p rel eq) xs1 xs2 with Invalid_argument _ -> false +let max_depth = 10_000 -let rec rel_typ rel eq t1 t2 = +let rel_list d p rel eq xs1 xs2 = + try List.for_all2 (p d rel eq) xs1 xs2 with Invalid_argument _ -> false + +let rec rel_typ d rel eq t1 t2 = + let d = d + 1 in + if d > max_depth then raise Undecided else t1 == t2 || SS.mem (t1, t2) !rel || begin rel := SS.add (t1, t2) !rel; match t1, t2 with @@ -918,9 +923,9 @@ let rec rel_typ rel eq t1 t2 = | Pre, _ | _, Pre -> raise PreEncountered | Mut t1', Mut t2' -> - eq_typ rel eq t1' t2' + eq_typ d rel eq t1' t2' | Typ c1, Typ c2 -> - eq_con eq c1 c2 + eq_con d eq c1 c2 | Mut _, _ | _, Mut _ | Typ _, _ | _, Typ _ -> false @@ -935,28 +940,28 @@ let rec rel_typ rel eq t1 t2 = | Con (con1, ts1), Con (con2, ts2) -> (match Cons.kind con1, Cons.kind con2 with | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - rel_typ rel eq (open_ ts1 t) t2 + rel_typ d rel eq (open_ ts1 t) t2 | _, Def (tbs, t) -> (* TBR this may fail to terminate *) - rel_typ rel eq t1 (open_ ts2 t) + rel_typ d rel eq t1 (open_ ts2 t) | _ when Cons.eq con1 con2 -> - rel_list eq_typ rel eq ts1 ts2 + rel_list d eq_typ rel eq ts1 ts2 | Abs (tbs, t), _ when rel != eq -> - rel_typ rel eq (open_ ts1 t) t2 + rel_typ d rel eq (open_ ts1 t) t2 | _ -> false ) | Con (con1, ts1), t2 -> (match Cons.kind con1, t2 with | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - rel_typ rel eq (open_ ts1 t) t2 + rel_typ d rel eq (open_ ts1 t) t2 | Abs (tbs, t), _ when rel != eq -> - rel_typ rel eq (open_ ts1 t) t2 + rel_typ d rel eq (open_ ts1 t) t2 | _ -> false ) | t1, Con (con2, ts2) -> (match Cons.kind con2 with | Def (tbs, t) -> (* TBR this may fail to terminate *) - rel_typ rel eq t1 (open_ ts2 t) + rel_typ d rel eq t1 (open_ ts2 t) | _ -> false ) | Prim p1, Prim p2 when p1 = p2 -> @@ -965,33 +970,33 @@ let rec rel_typ rel eq t1 t2 = p1 = Nat && p2 = Int | Obj (s1, tfs1), Obj (s2, tfs2) -> s1 = s2 && - rel_fields rel eq tfs1 tfs2 + rel_fields d rel eq tfs1 tfs2 | Array t1', Array t2' -> - rel_typ rel eq t1' t2' + rel_typ d rel eq t1' t2' | Opt t1', Opt t2' -> - rel_typ rel eq t1' t2' + rel_typ d rel eq t1' t2' | Prim Null, Opt t2' when rel != eq -> true | Variant fs1, Variant fs2 -> - rel_tags rel eq fs1 fs2 + rel_tags d rel eq fs1 fs2 | Tup ts1, Tup ts2 -> - rel_list rel_typ rel eq ts1 ts2 + rel_list d rel_typ rel eq ts1 ts2 | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> s1 = s2 && c1 = c2 && - (match rel_binds eq eq tbs1 tbs2 with + (match rel_binds d eq eq tbs1 tbs2 with | Some ts -> - rel_list rel_typ rel eq (List.map (open_ ts) t21) (List.map (open_ ts) t11) && - rel_list rel_typ rel eq (List.map (open_ ts) t12) (List.map (open_ ts) t22) + rel_list d rel_typ rel eq (List.map (open_ ts) t21) (List.map (open_ ts) t11) && + rel_list d rel_typ rel eq (List.map (open_ ts) t12) (List.map (open_ ts) t22) | None -> false ) | Async (s1, t11, t12), Async (s2, t21, t22) -> s1 = s2 && - eq_typ rel eq t11 t21 && - rel_typ rel eq t12 t22 + eq_typ d rel eq t11 t21 && + rel_typ d rel eq t12 t22 | _, _ -> false end -and rel_fields rel eq tfs1 tfs2 = +and rel_fields d rel eq tfs1 tfs2 = (* Assume that tfs1 and tfs2 are sorted. *) match tfs1, tfs2 with | [], [] -> @@ -1001,15 +1006,15 @@ and rel_fields rel eq tfs1 tfs2 = | tf1::tfs1', tf2::tfs2' -> (match compare_field tf1 tf2 with | 0 -> - rel_typ rel eq tf1.typ tf2.typ && - rel_fields rel eq tfs1' tfs2' + rel_typ d rel eq tf1.typ tf2.typ && + rel_fields d rel eq tfs1' tfs2' | -1 when rel != eq -> - rel_fields rel eq tfs1' tfs2 + rel_fields d rel eq tfs1' tfs2 | _ -> false ) | _, _ -> false -and rel_tags rel eq tfs1 tfs2 = +and rel_tags d rel eq tfs1 tfs2 = (* Assume that tfs1 and tfs2 are sorted. *) match tfs1, tfs2 with | [], [] -> @@ -1019,46 +1024,46 @@ and rel_tags rel eq tfs1 tfs2 = | tf1::tfs1', tf2::tfs2' -> (match compare_field tf1 tf2 with | 0 -> - rel_typ rel eq tf1.typ tf2.typ && - rel_tags rel eq tfs1' tfs2' + rel_typ d rel eq tf1.typ tf2.typ && + rel_tags d rel eq tfs1' tfs2' | +1 when rel != eq -> - rel_tags rel eq tfs1 tfs2' + rel_tags d rel eq tfs1 tfs2' | _ -> false ) | _, _ -> false -and rel_binds rel eq tbs1 tbs2 = +and rel_binds d rel eq tbs1 tbs2 = let ts = open_binds tbs2 in - if rel_list (rel_bind ts) rel eq tbs2 tbs1 + if rel_list d (rel_bind ts) rel eq tbs2 tbs1 then Some ts else None -and rel_bind ts rel eq tb1 tb2 = +and rel_bind ts d rel eq tb1 tb2 = tb1.sort == tb2.sort && - rel_typ rel eq (open_ ts tb1.bound) (open_ ts tb2.bound) + rel_typ d rel eq (open_ ts tb1.bound) (open_ ts tb2.bound) -and eq_typ rel eq t1 t2 = rel_typ eq eq t1 t2 +and eq_typ d rel eq t1 t2 = rel_typ d eq eq t1 t2 and eq t1 t2 : bool = - let eq = ref SS.empty in eq_typ eq eq t1 t2 + let eq = ref SS.empty in eq_typ 0 eq eq t1 t2 and sub t1 t2 : bool = - rel_typ (ref SS.empty) (ref SS.empty) t1 t2 + rel_typ 0 (ref SS.empty) (ref SS.empty) t1 t2 and eq_binds tbs1 tbs2 = - let eq = ref SS.empty in rel_binds eq eq tbs1 tbs2 <> None + let eq = ref SS.empty in rel_binds 0 eq eq tbs1 tbs2 <> None and eq_kind' eq k1 k2 : bool = match k1, k2 with | Def (tbs1, t1), Def (tbs2, t2) | Abs (tbs1, t1), Abs (tbs2, t2) -> - (match rel_binds eq eq tbs1 tbs2 with - | Some ts -> eq_typ eq eq (open_ ts t1) (open_ ts t2) + (match rel_binds 0 eq eq tbs1 tbs2 with + | Some ts -> eq_typ 0 eq eq (open_ ts t1) (open_ ts t2) | None -> false ) | _ -> false -and eq_con eq c1 c2 = +and eq_con d eq c1 c2 = match Cons.kind c1, Cons.kind c2 with | (Def (tbs1, t1)) as k1, (Def (tbs2, t2) as k2) -> eq_kind' eq k1 k2 @@ -1066,8 +1071,8 @@ and eq_con eq c1 c2 = Cons.eq c1 c2 | Def (tbs1, t1), Abs (tbs2, t2) | Abs (tbs2, t2), Def (tbs1, t1) -> - (match rel_binds eq eq tbs1 tbs2 with - | Some ts -> eq_typ eq eq (open_ ts t1) (Con (c2, ts)) + (match rel_binds d eq eq tbs1 tbs2 with + | Some ts -> eq_typ d eq eq (open_ ts t1) (Con (c2, ts)) | None -> false ) diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 1e52866700c..b94c9eb7468 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -221,8 +221,11 @@ val span : typ -> int option val cons: typ -> ConSet.t val cons_kind : kind -> ConSet.t + (* Equivalence and Subtyping *) +exception Undecided (* raised if termination depth exceeded *) + val eq : typ -> typ -> bool val eq_kind : kind -> kind -> bool diff --git a/test/fail/issue-3057.mo b/test/fail/issue-3057.mo new file mode 100644 index 00000000000..046591d2fdd --- /dev/null +++ b/test/fail/issue-3057.mo @@ -0,0 +1,7 @@ +module { + public class Id(x : A) { + public func map(f : A -> B) : Id { + Id(f(x)); + }; + }; +}; diff --git a/test/fail/ok/issue-3057.tc.ok b/test/fail/ok/issue-3057.tc.ok new file mode 100644 index 00000000000..91d02cf67b1 --- /dev/null +++ b/test/fail/ok/issue-3057.tc.ok @@ -0,0 +1 @@ +issue-3057.mo:2.10-6.4: type error [M0200], cannot decide type constructor equality diff --git a/test/fail/ok/issue-3057.tc.ret.ok b/test/fail/ok/issue-3057.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/issue-3057.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/polyrec.tc.ok b/test/fail/ok/polyrec.tc.ok new file mode 100644 index 00000000000..4d3a11f7808 --- /dev/null +++ b/test/fail/ok/polyrec.tc.ok @@ -0,0 +1 @@ +polyrec.mo:4.10-11.4: type error [M0200], cannot decide type constructor equality diff --git a/test/fail/ok/polyrec.tc.ret.ok b/test/fail/ok/polyrec.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/polyrec.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/polyrec.mo b/test/fail/polyrec.mo new file mode 100644 index 00000000000..79c2c55be50 --- /dev/null +++ b/test/fail/polyrec.mo @@ -0,0 +1,13 @@ +// this example triggers non-termination in subtyping due to non-regular type recursion in map +module { + + public class Iter({next = n : () -> ?T}) = this { + + public let next = n; + + public func map(f : T -> R) : Iter { + loop {} + }; + } + +} diff --git a/test/run.sh b/test/run.sh index b0713334276..8919150d85f 100755 --- a/test/run.sh +++ b/test/run.sh @@ -90,7 +90,8 @@ function normalize () { sed -e 's/wasm `unreachable` instruction executed/unreachable/g' | # cross-version normalisation sed -e 's/Ignore Diff:.*/Ignore Diff: (ignored)/ig' \ -e 's/Motoko compiler (source .*)/Motoko compiler (source XXX)/ig' \ - -e 's/Motoko compiler [^ ]* (source .*)/Motoko compiler (source XXX)/ig' | + -e 's/Motoko compiler [^ ]* (source .*)/Motoko compiler (source XXX)/ig' \ + -e 's/Motoko (source .*)/Motoko (source XXX)/ig' | # Normalize canister id prefixes and timestamps in debug prints sed -e 's/\[Canister [0-9a-z\-]*\]/debug.print:/g' \ @@ -331,6 +332,7 @@ do # Typecheck run tc $moc_with_flags --check $base.mo tc_succeeded=$? + normalize $out/$base.tc if [ "$tc_succeeded" -eq 0 -a "$ONLY_TYPECHECK" = "no" ] then From 952f3d11b0aa292401b51f017a1e5fb79dc179d1 Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Fri, 6 Dec 2024 01:29:28 +0100 Subject: [PATCH 04/18] niv motoko-base: update adb24da4 -> 4ace2667 (#4803) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Changelog for motoko-base: Branch: next-moc Commits: [dfinity/motoko-base@adb24da4...4ace2667](https://github.com/dfinity/motoko-base/compare/adb24da4ce084a26bcd8daf046140eca8f76ac4a...4ace26675fc1222daefb24ac160e0d03000429d2) * [`4ace2667`](https://github.com/dfinity/motoko-base/commit/4ace26675fc1222daefb24ac160e0d03000429d2) feat: add `replyDeadline` to `ExperimentalInternetComputer` ([dfinity/motoko-base⁠#677](https://togithub.com/dfinity/motoko-base/issues/677)) --- nix/sources.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index cc6d4ab383e..cafef8ee1ff 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -75,10 +75,10 @@ "homepage": "", "owner": "dfinity", "repo": "motoko-base", - "rev": "adb24da4ce084a26bcd8daf046140eca8f76ac4a", - "sha256": "0lhyskqpsijc84c168icivmcg30pcac3645m6s3qa28zsw58k73h", + "rev": "4ace26675fc1222daefb24ac160e0d03000429d2", + "sha256": "0v05djp8ymwc5c9y8ms80cqzx8h2jb9fskfmw8l2mszdcwn8ahsw", "type": "tarball", - "url": "https://github.com/dfinity/motoko-base/archive/adb24da4ce084a26bcd8daf046140eca8f76ac4a.tar.gz", + "url": "https://github.com/dfinity/motoko-base/archive/4ace26675fc1222daefb24ac160e0d03000429d2.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "motoko-matchers": { From fcd7b81323978b02157b22e7d6ad57b8e5842450 Mon Sep 17 00:00:00 2001 From: "Jennifer K. Tran" <38402540+jennifertrin@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:44:42 -0800 Subject: [PATCH 05/18] docs: add statement about import and actor sequence (#4688) Add a statement about import and actor sequence based on question related to this forum post: https://forum.dfinity.org/t/misplaced-await-and-misplaced-async/34479 Co-authored-by: Jessie Mongeon <133128541+jessiemongeon1@users.noreply.github.com> Co-authored-by: Luc Blaeser <112870813+luc-blaeser@users.noreply.github.com> --- doc/md/writing-motoko/actors-async.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/md/writing-motoko/actors-async.md b/doc/md/writing-motoko/actors-async.md index 437636d40cd..3d96c9307d4 100644 --- a/doc/md/writing-motoko/actors-async.md +++ b/doc/md/writing-motoko/actors-async.md @@ -32,6 +32,8 @@ In Motoko, actors have dedicated syntax and types: - Waiting on `f` to be completed is expressed using `await f` to obtain a value of type `T`. To avoid introducing shared state through messaging, for example, by sending an object or mutable array, the data that can be transmitted through shared functions is restricted to immutable, shared types. +- All state should be encapsulated within the actor or actor class. The main actor file should begin with imports, followed by the actor or actor class definition. + ## Defining an actor Consider the following actor declaration: From 81f04e9a765f4a00cfad86a48aac59abe7dd89a8 Mon Sep 17 00:00:00 2001 From: "Jennifer K. Tran" <38402540+jennifertrin@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:57:37 -0800 Subject: [PATCH 06/18] docs: add StableTrie as an option for stable memory storage based on Regions (#4709) Co-authored-by: Jessie Mongeon <133128541+jessiemongeon1@users.noreply.github.com> Co-authored-by: Gabor Greif --- doc/md/stable-memory/stablememory.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/md/stable-memory/stablememory.md b/doc/md/stable-memory/stablememory.md index fb2716bee12..5c0e84d47d3 100644 --- a/doc/md/stable-memory/stablememory.md +++ b/doc/md/stable-memory/stablememory.md @@ -22,6 +22,8 @@ New applications should use the `Region` library: it offers additional isolation - [`memory-hashtable`](https://mops.one/memory-hashtable): A library for storing, updating, deleting, and retrieving a single blob-value per key. +- [`StableTrie`](https://mops.one/stable-trie): A key-value map data structure that has its main data living permanently in stable memory using Regions. + ## Samples - [motoko-bucket](https://github.com/PrimLabs/Bucket): A key value database library that uses stable memory. From 76f9087c645f9010e1e92f1c3f81fd22c05ae8ae Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Fri, 6 Dec 2024 02:17:14 +0100 Subject: [PATCH 07/18] chore: Releasing 0.13.5 (#4805) --- Changelog.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 56d87f3f39f..35686efe229 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,6 @@ # Motoko compiler changelog -## 0.13.5 (FUTURE) +## 0.13.5 (2024-12-06) * motoko (`moc`) @@ -38,12 +38,16 @@ * Added new primitive `replyDeadline : () -> Nat64` to obtain when a response for a best-effort message is due (#4795). + * bugfix: fail-fast by limiting subtyping depth to avoid reliance on unpredictable stack overflow (#3057, #4798). + * motoko-base * Added `Text.fromList` and `Text.toList` functions (dfinity/motoko-base#676). * Added `Text.fromArray/fromVarArray` functions (dfinity/motoko-base#674). + * Added `replyDeadline` to `ExperimentalInternetComputer` (dfinity/motoko-base⁠#677). + ## 0.13.4 (2024-11-29) * motoko (`moc`) From adfa138e168a4a6828b79553bb3d5f5357628854 Mon Sep 17 00:00:00 2001 From: Jessie Mongeon <133128541+jessiemongeon1@users.noreply.github.com> Date: Fri, 6 Dec 2024 14:55:15 -0800 Subject: [PATCH 08/18] docs: Remove overview (#4806) * Remove overview * fix --- doc/md/canister-maintenance/compatibility.md | 9 ++++--- doc/md/canister-maintenance/cycles.md | 2 +- doc/md/canister-maintenance/optimization.md | 14 +++++------ doc/md/canister-maintenance/upgrades.md | 5 ++-- doc/md/getting-started/basic-concepts.md | 2 +- doc/md/getting-started/dev-env.md | 6 ++--- doc/md/getting-started/examples.md | 2 +- doc/md/getting-started/motoko-introduction.md | 24 ++++++++++++++----- doc/md/getting-started/quickstart.md | 2 +- .../0.11.0-migration-guide.md | 2 +- doc/md/migration-guides/overview.md | 4 +--- doc/md/motoko-tools/embed-motoko.md | 2 +- doc/md/motoko-tools/mo-dev.md | 6 ++--- doc/md/motoko-tools/motoko-formatter.md | 2 +- doc/md/motoko-tools/motoko-js.md | 2 +- doc/md/reference/compiler-ref.md | 2 +- doc/md/reference/generating-docs.md | 8 +++---- doc/md/reference/language-manual.md | 4 ++-- doc/md/reference/style.md | 2 +- doc/md/stable-memory/_category_.yml | 2 +- doc/md/stable-memory/stable-regions.md | 4 ++-- doc/md/stable-memory/stablememory.md | 2 +- doc/md/writing-motoko/actor-classes.md | 2 +- doc/md/writing-motoko/actors-async.md | 2 +- doc/md/writing-motoko/arguments.md | 2 +- doc/md/writing-motoko/async-data.md | 2 +- doc/md/writing-motoko/async-star.md | 2 +- doc/md/writing-motoko/caller-id.md | 2 +- doc/md/writing-motoko/candid-ui.md | 6 ++--- doc/md/writing-motoko/candid.md | 2 +- doc/md/writing-motoko/control-flow.md | 2 +- doc/md/writing-motoko/errors.md | 2 +- doc/md/writing-motoko/heartbeats.md | 2 +- doc/md/writing-motoko/incomplete-code.md | 2 +- doc/md/writing-motoko/integers.md | 2 +- doc/md/writing-motoko/intercanister-calls.md | 2 +- .../writing-motoko/local-objects-classes.md | 2 +- doc/md/writing-motoko/message-inspection.md | 2 +- doc/md/writing-motoko/message-restrictions.md | 4 ++-- doc/md/writing-motoko/modules-and-imports.md | 2 +- doc/md/writing-motoko/mutable-state.md | 2 +- doc/md/writing-motoko/object-subtyping.md | 2 +- doc/md/writing-motoko/pattern-matching.md | 10 ++++---- doc/md/writing-motoko/pipes.md | 2 +- doc/md/writing-motoko/query-functions.md | 2 +- doc/md/writing-motoko/randomness.md | 2 +- doc/md/writing-motoko/recursive-types.md | 4 ++-- doc/md/writing-motoko/sharing.md | 2 +- doc/md/writing-motoko/static-types.md | 2 +- doc/md/writing-motoko/structural-equality.md | 2 +- doc/md/writing-motoko/timers.md | 4 ++-- doc/md/writing-motoko/writing-intro.md | 2 +- 52 files changed, 97 insertions(+), 89 deletions(-) diff --git a/doc/md/canister-maintenance/compatibility.md b/doc/md/canister-maintenance/compatibility.md index 56f89b7fb6a..9592856ad83 100644 --- a/doc/md/canister-maintenance/compatibility.md +++ b/doc/md/canister-maintenance/compatibility.md @@ -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 @@ -233,7 +233,7 @@ 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). @@ -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, @@ -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. diff --git a/doc/md/canister-maintenance/cycles.md b/doc/md/canister-maintenance/cycles.md index 1c05399b116..229ad715513 100644 --- a/doc/md/canister-maintenance/cycles.md +++ b/doc/md/canister-maintenance/cycles.md @@ -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). diff --git a/doc/md/canister-maintenance/optimization.md b/doc/md/canister-maintenance/optimization.md index f92d08939f0..acf44cf5dfd 100644 --- a/doc/md/canister-maintenance/optimization.md +++ b/doc/md/canister-maintenance/optimization.md @@ -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: @@ -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: @@ -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: @@ -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. diff --git a/doc/md/canister-maintenance/upgrades.md b/doc/md/canister-maintenance/upgrades.md index 2bb278d5907..1e788cf7a69 100644 --- a/doc/md/canister-maintenance/upgrades.md +++ b/doc/md/canister-maintenance/upgrades.md @@ -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. @@ -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 @@ -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 diff --git a/doc/md/getting-started/basic-concepts.md b/doc/md/getting-started/basic-concepts.md index 31eb8967a82..b98cec333fa 100644 --- a/doc/md/getting-started/basic-concepts.md +++ b/doc/md/getting-started/basic-concepts.md @@ -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. diff --git a/doc/md/getting-started/dev-env.md b/doc/md/getting-started/dev-env.md index ea923eba016..e3606be301b 100644 --- a/doc/md/getting-started/dev-env.md +++ b/doc/md/getting-started/dev-env.md @@ -5,7 +5,7 @@ sidebar_position: 3 # Developer environment -## Overview + To develop and deploy Motoko canister smart contracts, you will need a developer environment that contains the Motoko compiler and base library. It is recommended to use the [IC SDK](https://github.com/dfinity/sdk#readme), which includes Motoko, along with `dfx`, a command-line tool used to create, build, and deploy canisters on ICP. @@ -54,14 +54,14 @@ Before you start developing Motoko, verify the following: ## Motoko version -The following table details which version of Motoko shipped with each major version of the IC SDK. +The following table details which version of Motoko shipped with each major version of the IC SDK. | IC SDK version | Motoko version | |-----------------|------------------| | 0.20.0 | 0.11.1 | | 0.19.0 | 0.11.1 | | 0.18.0 | 0.11.0 | -| 0.17.0 | 0.10.4 | +| 0.17.0 | 0.10.4 | | 0.16.0 | 0.10.4 | | 0.15.0 | 0.9.7 | | 0.14.0 | 0.8.7 | diff --git a/doc/md/getting-started/examples.md b/doc/md/getting-started/examples.md index c22bd82875f..6554ef5b0e7 100644 --- a/doc/md/getting-started/examples.md +++ b/doc/md/getting-started/examples.md @@ -4,7 +4,7 @@ sidebar_position: 5 # Sample projects and resources -## Overview + Want to get started building with Motoko? Check out some of these sample projects and Motoko resources to help you get started. diff --git a/doc/md/getting-started/motoko-introduction.md b/doc/md/getting-started/motoko-introduction.md index b4d450cade0..81ae2c49b42 100644 --- a/doc/md/getting-started/motoko-introduction.md +++ b/doc/md/getting-started/motoko-introduction.md @@ -2,14 +2,28 @@ sidebar_position: 1 --- -# Introduction +# Meet Motoko: The language shaping the future of Web3 -## Overview +Logo Motoko is a modern, general-purpose programming language you can use specifically to author ICP canister smart contracts. Although aimed primarily at ICP canister development, its design is general enough to support future compilation to other targets. Motoko is designed to be approachable for programmers who have some basic familiarity with object-oriented and/or functional programming idioms in either JavaScript, or another modern programming language, such as Rust, Swift, TypeScript, C#, or Java. + +```motoko +// A simple Motoko smart contract. + +actor Main { + public query func hello() : async Text { + "Hello, world!" + }; +}; + +await Main.hello(); +``` + + Motoko provides: - A high-level language for programming applications to run on ICP. @@ -47,7 +61,7 @@ Its core is a call-by-value, impure functional language with imperative and obje Motoko is strongly typed and offers option types, records, variants, generics and subtyping. The type system is structural so that types with different names but equivalent definition are interchangeable; subtyping allows values to be used at their precise type but also at any more general supertype. -- Motoko is safety-oriented. +- Motoko is safety-oriented. - Memory management is automated using a garbage collector. - Implicit null values are avoided. Nulls must be handled explicitly using option types. - The type system cannot be circumvented using unsafe casts. @@ -93,6 +107,4 @@ Once upgraded, the new interface is compatible with the previous one, meaning ex ## Getting started -Get started with Motoko by [setting up your developer environment](dev-env.md) and creating a simple [Hello, world!](quickstart.md) program. - -Logo +Get started with Motoko by [setting up your developer environment](dev-env.md) and creating a simple [Hello, world!](quickstart.md) program. \ No newline at end of file diff --git a/doc/md/getting-started/quickstart.md b/doc/md/getting-started/quickstart.md index ea2f52183bb..15549953af7 100644 --- a/doc/md/getting-started/quickstart.md +++ b/doc/md/getting-started/quickstart.md @@ -5,7 +5,7 @@ sidebar_position: 4 # Motoko quickstart -## Overview + This quickstart guide showcases how to deploy a simple 'Hello, world!' Motoko smart contract. diff --git a/doc/md/migration-guides/0.11.0-migration-guide.md b/doc/md/migration-guides/0.11.0-migration-guide.md index e5c58de492a..d9f864bc275 100644 --- a/doc/md/migration-guides/0.11.0-migration-guide.md +++ b/doc/md/migration-guides/0.11.0-migration-guide.md @@ -5,7 +5,7 @@ sidebar_position: 2 # Motoko v0.11.0: Safety feature migration guide -## Overview + Motoko v0.11.0 and newer introduces a new safety feature that could cause breaking changes to existing code. diff --git a/doc/md/migration-guides/overview.md b/doc/md/migration-guides/overview.md index a11f4211582..764c79bf069 100644 --- a/doc/md/migration-guides/overview.md +++ b/doc/md/migration-guides/overview.md @@ -2,12 +2,10 @@ sidebar_position: 1 --- -# Overview +# Migration guides New versions of Motoko may introduce breaking changes that are not backwards compatible with older versions. In these scenarios, there are migration guides created to explain how to update your code to migrate to the new version properly. -## Migration guides - - [0.11.0 Migration guide](0.11.0-migration-guide.md) Logo diff --git a/doc/md/motoko-tools/embed-motoko.md b/doc/md/motoko-tools/embed-motoko.md index 872886fdb3a..f5189ee0593 100644 --- a/doc/md/motoko-tools/embed-motoko.md +++ b/doc/md/motoko-tools/embed-motoko.md @@ -4,7 +4,7 @@ sidebar_position: 1 # Embed Motoko -## Overview + The Embed Motoko tool enables Motoko smart contracts to be embedded in web pages such as a blog, web application, or even a Medium article. Simply insert your Motoko smart contract into the Embed Motoko tool and copy either the generated embedded URL or the HTML iframe to use in your web page. diff --git a/doc/md/motoko-tools/mo-dev.md b/doc/md/motoko-tools/mo-dev.md index 8d036095709..5162bb0b6e1 100644 --- a/doc/md/motoko-tools/mo-dev.md +++ b/doc/md/motoko-tools/mo-dev.md @@ -4,7 +4,7 @@ sidebar_position: 3 # Motoko dev server -## Overview + Motoko dev server, or `mo-dev` for short, is a command line tool that features a development server with live reloading for Motoko. @@ -87,13 +87,13 @@ To configure the runtime of an individual unit test, include the following comme ## Examples -The [Vite + React + Motoko](https://github.com/rvanasa/vite-react-motoko#readme) project showcases how to integrate `mo-dev` into a full-stack dapp. +The [Vite + React + Motoko](https://github.com/rvanasa/vite-react-motoko#readme) project showcases how to integrate `mo-dev` into a full-stack dapp. [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/rvanasa/vite-react-motoko) ## Important notes -`mo-dev` is early in development. Please feel free to report a bug, ask a question, or request a feature on the project's [GitHub issues](https://github.com/dfinity/motoko-dev-server/issues) page. +`mo-dev` is early in development. Please feel free to report a bug, ask a question, or request a feature on the project's [GitHub issues](https://github.com/dfinity/motoko-dev-server/issues) page. Logo diff --git a/doc/md/motoko-tools/motoko-formatter.md b/doc/md/motoko-tools/motoko-formatter.md index 9a305ae6fcf..d4ec78bfc35 100644 --- a/doc/md/motoko-tools/motoko-formatter.md +++ b/doc/md/motoko-tools/motoko-formatter.md @@ -4,7 +4,7 @@ sidebar_position: 2 # Motoko formatting tools -## Overview + The Motoko Prettier plugin can be used to format and validate Motoko source code files. It can be used through the [Prettier CLI](https://prettier.io/docs/en/cli.html) or through VS Code. diff --git a/doc/md/motoko-tools/motoko-js.md b/doc/md/motoko-tools/motoko-js.md index 64d20d547f7..178306eb4a1 100644 --- a/doc/md/motoko-tools/motoko-js.md +++ b/doc/md/motoko-tools/motoko-js.md @@ -4,7 +4,7 @@ sidebar_position: 4 # Motoko.js -## Overview + The Motoko.js package can be used to compile and run Motoko smart contracts in a web browser or Node.js. diff --git a/doc/md/reference/compiler-ref.md b/doc/md/reference/compiler-ref.md index 926cacde603..3e6af6f456d 100644 --- a/doc/md/reference/compiler-ref.md +++ b/doc/md/reference/compiler-ref.md @@ -4,7 +4,7 @@ sidebar_position: 2 # Compiler reference -## Overview + The Motoko compiler (`moc`) is the primary tool for compiling Motoko programs into executable WebAssembly (Wasm) modules. The compiler runs in the background when you build projects using the [IC SDK](https://internetcomputer.org/docs/current/developer-docs/setup/install). If you invoke the compiler directly on the command-line, you can press CTRL-C to exit. diff --git a/doc/md/reference/generating-docs.md b/doc/md/reference/generating-docs.md index 5ac1210701d..20b0322c2d0 100644 --- a/doc/md/reference/generating-docs.md +++ b/doc/md/reference/generating-docs.md @@ -4,7 +4,7 @@ sidebar_position: 4 # Generating Motoko documentation -## Overview + `mo-doc` is a command-line tool for generating documentation for Motoko source code. It processes source files and generates documentation in various formats. @@ -26,7 +26,7 @@ $(dfx cache show)/mo-doc [options] - `html`: Generates HTML format documentation. - `adoc`: Generates AsciiDoc format documentation. - `plain`: Generates Markdown documentation. - + Defaults to `html`. - `--help`: Shows usage information. @@ -59,7 +59,7 @@ Doc comments can be used to provide explanations for functions, classes, types, ```motoko no-repl /// Calculate the factorial of a given positive integer. -/// +/// /// Example: /// ```motoko /// factorial(0); // => null @@ -71,7 +71,7 @@ func factorial(n : Nat) : ?Nat { ``` ## Resources -Check out Motoko's [base library source code](https://github.com/dfinity/motoko-base/tree/master/src) for additional examples and best practices. +Check out Motoko's [base library source code](https://github.com/dfinity/motoko-base/tree/master/src) for additional examples and best practices. The source code for `mo-doc` is available in the [dfinity/motoko](https://github.com/dfinity/motoko/tree/master/src/docs) GitHub repository. Contributions are welcome! diff --git a/doc/md/reference/language-manual.md b/doc/md/reference/language-manual.md index 7c4d392eb94..3901601b4d6 100644 --- a/doc/md/reference/language-manual.md +++ b/doc/md/reference/language-manual.md @@ -31,7 +31,7 @@ sidebar_position: 1 * [ ] Re-section so headings appear in content outline --> -## Overview + This reference page provides technical details of interest to the following audiences: @@ -2416,7 +2416,7 @@ The expression `return ` has type `None` provided: - `T` is the return type of the nearest enclosing function with no intervening `async` expression. - - `async T` is the type of the nearest enclosing, perhaps implicit, `async` expression with no intervening function declaration. + - `async T` is the type of the nearest enclosing, perhaps implicit, `async` expression with no intervening function declaration. The `return` expression exits the corresponding dynamic function invocation or completes the corresponding dynamic `async` or `async*` expression with the result of ``. diff --git a/doc/md/reference/style.md b/doc/md/reference/style.md index 38ec8a46a10..61fddb430c4 100644 --- a/doc/md/reference/style.md +++ b/doc/md/reference/style.md @@ -4,7 +4,7 @@ sidebar_position: 3 # Motoko style guidelines -## Overview + To increase readability and uniformity of Motoko source code, the style guide provides suggestions for formatting Motoko sources and other basic conventions. diff --git a/doc/md/stable-memory/_category_.yml b/doc/md/stable-memory/_category_.yml index a3b10a914ef..657d0ec450f 100644 --- a/doc/md/stable-memory/_category_.yml +++ b/doc/md/stable-memory/_category_.yml @@ -1,4 +1,4 @@ position: 4 -label: 'Stable memory' +label: 'Persistent data' collapsible: true # make the category collapsible collapsed: true diff --git a/doc/md/stable-memory/stable-regions.md b/doc/md/stable-memory/stable-regions.md index 7a24ea4667a..2d895e74705 100644 --- a/doc/md/stable-memory/stable-regions.md +++ b/doc/md/stable-memory/stable-regions.md @@ -4,7 +4,7 @@ sidebar_position: 1 # Stable regions -## Overview + The `Region` library provides low-level access to ICP stable memory feature. @@ -79,7 +79,7 @@ module { A stable region exposes low-level linear memory and it is the programmer's task to properly manipulate and interpret this data. This can be very error-prone when managing data in a stable region. However, the safety of Motoko's native values heap objects is always guaranteed, independent of the stable region content. -::: +::: :::note The cost of accessing stable regions is significantly higher than using Motoko's native memory, i.e. regular Motoko values and objects. diff --git a/doc/md/stable-memory/stablememory.md b/doc/md/stable-memory/stablememory.md index 5c0e84d47d3..4f433da677f 100644 --- a/doc/md/stable-memory/stablememory.md +++ b/doc/md/stable-memory/stablememory.md @@ -4,7 +4,7 @@ sidebar_position: 2 # Stable memory -## Overview + The [`Region` library](stable-regions.md) can be used to interact with stable memory on ICP. diff --git a/doc/md/writing-motoko/actor-classes.md b/doc/md/writing-motoko/actor-classes.md index 3c11a4ca3ae..d899e117b1d 100644 --- a/doc/md/writing-motoko/actor-classes.md +++ b/doc/md/writing-motoko/actor-classes.md @@ -5,7 +5,7 @@ sidebar_position: 3 # Actor classes -## Overview + Actor classes enable you to create networks of actors programmatically. Actor classes have to be defined in a separate source file. To illustrate how to define and import actor classes, the following example implements a distributed map of keys of type [`Nat`](../base/Nat.md) to values of type [`Text`](../base/Text.md). It provides simple insert and lookup functions, `put(k, v)` and `get(k)`, for working with these keys and values. diff --git a/doc/md/writing-motoko/actors-async.md b/doc/md/writing-motoko/actors-async.md index 3d96c9307d4..e90b715a23d 100644 --- a/doc/md/writing-motoko/actors-async.md +++ b/doc/md/writing-motoko/actors-async.md @@ -4,7 +4,7 @@ sidebar_position: 2 # Actors -## Overview + The programming model of the Internet Computer consists of memory-isolated canisters communicating by asynchronous message passing of binary data encoding Candid values. A canister processes its messages one-at-a-time, preventing race conditions. A canister uses call-backs to register what needs to be done with the result of any inter-canister messages it issues. diff --git a/doc/md/writing-motoko/arguments.md b/doc/md/writing-motoko/arguments.md index 0a463092ec6..4eabf721aeb 100644 --- a/doc/md/writing-motoko/arguments.md +++ b/doc/md/writing-motoko/arguments.md @@ -4,7 +4,7 @@ sidebar_position: 4 # Arguments -## Overview + Arguments can be passed to an actor's function for the function to use as input. Arguments can be [primitive values](../getting-started/basic-concepts#primitive-values), such as [`Int`](../base/Int.md), [`Nat`](../base/Nat.md), [`Bool`](../base/Bool.md), or [`Text`](../base/Text.md), or they can be non-primitive values such as tuples, arrays, or objects. To showcase a basic example of how an actor can accept an argument, this page will use an example Motoko actor that accepts multiple text arguments. diff --git a/doc/md/writing-motoko/async-data.md b/doc/md/writing-motoko/async-data.md index 5211c14438a..6c4d3c985c5 100644 --- a/doc/md/writing-motoko/async-data.md +++ b/doc/md/writing-motoko/async-data.md @@ -4,7 +4,7 @@ sidebar_position: 5 # Async data -## Overview + On ICP, communication between canisters is asynchronous. Sending a message together with a callback from one canister to another schedules a request in the receiver. Completion of the request triggers the callback to the sender, allowing the sender to process the result. diff --git a/doc/md/writing-motoko/async-star.md b/doc/md/writing-motoko/async-star.md index abc821d201d..0a1c5fd2cc1 100644 --- a/doc/md/writing-motoko/async-star.md +++ b/doc/md/writing-motoko/async-star.md @@ -4,7 +4,7 @@ sidebar_position: 28 # Abstracting asynchronous code -## Overview + Functions are an abstraction mechanism, allowing you to name a computation and re-use that computation in different locations within your code simply by invoking the name of that function. When the function takes parameters, you can tailor the computation to different call sites by providing different arguments. Programmers often improve their code by re-factoring common patterns of code into diff --git a/doc/md/writing-motoko/caller-id.md b/doc/md/writing-motoko/caller-id.md index b033ef496bf..b4ae9b778c3 100644 --- a/doc/md/writing-motoko/caller-id.md +++ b/doc/md/writing-motoko/caller-id.md @@ -4,7 +4,7 @@ sidebar_position: 6 # Caller identification -## Overview + Motoko’s shared functions support a simple form of caller identification that allows you to inspect the ICP **principal** associated with the caller of a function. Principals are a value that identifies a unique user or canister. diff --git a/doc/md/writing-motoko/candid-ui.md b/doc/md/writing-motoko/candid-ui.md index a318e91cdfe..8178b30aa75 100644 --- a/doc/md/writing-motoko/candid-ui.md +++ b/doc/md/writing-motoko/candid-ui.md @@ -2,14 +2,14 @@ sidebar_position: 7 --- -# Candid UI +# Candid UI + -## Overview The canister interface description language, often referred to as Candid or more generally as the IDL, provides a common language for specifying the signature of a canister smart contract. Candid provides a unified way for you to interact with canister smart contracts that are written in different languages or accessed using different tools. -For example, Candid provides a consistent view of a service whether the underlying program is native Rust, JavaScript, or any other programming language. +For example, Candid provides a consistent view of a service whether the underlying program is native Rust, JavaScript, or any other programming language. Candid also enables different tools, such as the `dfx` command-line interface and the Network Nervous System dapp, to share a common description for a service. Based on the type signature of the actor, Candid also provides a web interface that allows you to call canister functions for testing and debugging. diff --git a/doc/md/writing-motoko/candid.md b/doc/md/writing-motoko/candid.md index 26473c11247..c6c341a7f4e 100644 --- a/doc/md/writing-motoko/candid.md +++ b/doc/md/writing-motoko/candid.md @@ -4,7 +4,7 @@ sidebar_position: 28 # Candid serialization -## Overview + Candid is an interface description language and serialization format designed specifically for the Internet Computer protocol. It's a crucial component that enables seamless communication between different services and canister smart contracts on ICP, regardless of the programming languages they're implemented in. diff --git a/doc/md/writing-motoko/control-flow.md b/doc/md/writing-motoko/control-flow.md index db5e0912a6f..8c3e93fd859 100644 --- a/doc/md/writing-motoko/control-flow.md +++ b/doc/md/writing-motoko/control-flow.md @@ -4,7 +4,7 @@ sidebar_position: 8 # Control flow -## Overview + There are two key categories of control flow: diff --git a/doc/md/writing-motoko/errors.md b/doc/md/writing-motoko/errors.md index 65212bac916..f11789e624f 100644 --- a/doc/md/writing-motoko/errors.md +++ b/doc/md/writing-motoko/errors.md @@ -4,7 +4,7 @@ sidebar_position: 9 # Error handling -## Overview + There are three primary ways to represent and handle errors values in Motoko: diff --git a/doc/md/writing-motoko/heartbeats.md b/doc/md/writing-motoko/heartbeats.md index 6c18b406f0b..16de70fa570 100644 --- a/doc/md/writing-motoko/heartbeats.md +++ b/doc/md/writing-motoko/heartbeats.md @@ -4,7 +4,7 @@ sidebar_position: 10 # Heartbeats -## Overview + ICP canisters can elect to receive regular heartbeat messages by exposing a particular `canister_heartbeat` function (see [heartbeat](https://smartcontracts.org/docs/interface-spec/index.html#heartbeat)). diff --git a/doc/md/writing-motoko/incomplete-code.md b/doc/md/writing-motoko/incomplete-code.md index 96221f4c189..861b018ba1f 100644 --- a/doc/md/writing-motoko/incomplete-code.md +++ b/doc/md/writing-motoko/incomplete-code.md @@ -3,7 +3,7 @@ sidebar_position: 27 --- # Writing incomplete code -## Overview + In the midst of writing a program, you may want to run an incomplete version or a version where one or more execution paths are either missing or simply invalid. diff --git a/doc/md/writing-motoko/integers.md b/doc/md/writing-motoko/integers.md index e6465b45601..42f251bc3d7 100644 --- a/doc/md/writing-motoko/integers.md +++ b/doc/md/writing-motoko/integers.md @@ -5,7 +5,7 @@ sidebar_position: 11 # Integers and numbers -## Overview + Motoko offers a variety types to represent integers and natural numbers, with the usual suite of arithmetic operators (`+`, `-`, `*`, '/' etc.) and comparison operators (`==`, `!=`, `<`, `>`, `<=`, `>=`). diff --git a/doc/md/writing-motoko/intercanister-calls.md b/doc/md/writing-motoko/intercanister-calls.md index 68e94218050..adecd9b232e 100644 --- a/doc/md/writing-motoko/intercanister-calls.md +++ b/doc/md/writing-motoko/intercanister-calls.md @@ -4,7 +4,7 @@ sidebar_position: 12 # Inter-canister calls -## Overview + One of the most important features of ICP for developers is the ability to call functions in one canister from another canister. This capability to make calls between canisters, also sometimes referred to as **inter-canister calls**, enables you to reuse and share functionality in multiple dapps. diff --git a/doc/md/writing-motoko/local-objects-classes.md b/doc/md/writing-motoko/local-objects-classes.md index 3741dbd7282..ff3be96ad0b 100644 --- a/doc/md/writing-motoko/local-objects-classes.md +++ b/doc/md/writing-motoko/local-objects-classes.md @@ -8,7 +8,7 @@ sidebar_position: 13 TODO: Move examples into doc/modules/language-guide/examples --> -## Overview + In Motoko, an object is just a collection of named fields, holding values. These values can either be plain data, or function values. In addition, each field can be mutable or immutable. A simple object containing just fields of data is like a record in a database. diff --git a/doc/md/writing-motoko/message-inspection.md b/doc/md/writing-motoko/message-inspection.md index 046262c696a..8e61d0c134a 100644 --- a/doc/md/writing-motoko/message-inspection.md +++ b/doc/md/writing-motoko/message-inspection.md @@ -4,7 +4,7 @@ sidebar_position: 14 # Message inspection -## Overview + On ICP, a canister can selectively inspect, then choose to accept or decline ingress messages submitted through the HTTP interface. diff --git a/doc/md/writing-motoko/message-restrictions.md b/doc/md/writing-motoko/message-restrictions.md index ad892c1b2a0..13c023df710 100644 --- a/doc/md/writing-motoko/message-restrictions.md +++ b/doc/md/writing-motoko/message-restrictions.md @@ -4,7 +4,7 @@ sidebar_position: 15 # Messaging restrictions -## Overview + ICP places restrictions on when and how canisters are allowed to communicate. These restrictions are enforced dynamically but prevented statically in Motoko, ruling out a class of dynamic execution errors. Two examples are: @@ -12,7 +12,7 @@ ICP places restrictions on when and how canisters are allowed to communicate. Th - A canister query method cannot send messages. -These ICP restrictions are surfaced in Motoko as constraints on the program context in which certain expressions can be appear. +These ICP restrictions are surfaced in Motoko as constraints on the program context in which certain expressions can be appear. Violations of these constraints are reported as errors by the type checker. In Motoko, an expression occurs in an asynchronous context if it appears in the body of an `async` expression, which may be the body of a shared or local function or a stand-alone expression. The only exception are `query` functions, whose body is not considered to open an asynchronous context. diff --git a/doc/md/writing-motoko/modules-and-imports.md b/doc/md/writing-motoko/modules-and-imports.md index 74322dc3e2a..db9ea81ce77 100644 --- a/doc/md/writing-motoko/modules-and-imports.md +++ b/doc/md/writing-motoko/modules-and-imports.md @@ -4,7 +4,7 @@ sidebar_position: 16 # Modules and imports -## Overview + The design of Motoko strives to minimize built-in types and operations. Instead of built-in types, Motoko provides a base library of modules to handle many kinds of common operations and make the language feel complete. This base library is still evolving with modules that support core features, and the base library APIs are subject to change over time to varying degrees. You should note, in particular, that the size and number of modules and functions included in the base library is likely to increase dramatically. Updates to the base library modules might introduce breaking changes that require you to update your programs to remain compatible. Breaking changes are communicated through the [Motoko migration guides](../migration-guides/overview.md). diff --git a/doc/md/writing-motoko/mutable-state.md b/doc/md/writing-motoko/mutable-state.md index ca60b24c67e..b8d14eadc5c 100644 --- a/doc/md/writing-motoko/mutable-state.md +++ b/doc/md/writing-motoko/mutable-state.md @@ -4,7 +4,7 @@ sidebar_position: 17 # Mutable state -## Overview + Each actor in Motoko may use, but may never directly share, internal mutable state. diff --git a/doc/md/writing-motoko/object-subtyping.md b/doc/md/writing-motoko/object-subtyping.md index e0370754bea..f0830ea4573 100644 --- a/doc/md/writing-motoko/object-subtyping.md +++ b/doc/md/writing-motoko/object-subtyping.md @@ -4,7 +4,7 @@ sidebar_position: 18 # Object subtyping -## Overview + **Object subtyping** : In Motoko, objects have types that may relate by subtyping. Types with more fields are less general and are subtypes of types with fewer fields. Consider the following general types and subtypes: diff --git a/doc/md/writing-motoko/pattern-matching.md b/doc/md/writing-motoko/pattern-matching.md index e4bd0850549..8f4a5c48067 100644 --- a/doc/md/writing-motoko/pattern-matching.md +++ b/doc/md/writing-motoko/pattern-matching.md @@ -4,7 +4,7 @@ sidebar_position: 19 # Pattern matching -## Overview + Pattern matching is a language feature that makes it easy to both test and decompose structured data into its constituent parts. While most programming languages provide familiar ways to build structured data, pattern matching enables you to take apart structured data and bring its fragments into scope by binding them to the names you specify. Syntactically, the patterns resemble the construction of structured data, but generally appear in input-direction positions, such as in function argument positions, after the `case` keyword in `switch` expressions, and after `let` or `var` declarations. @@ -123,11 +123,11 @@ In a `let-else` construct, the expression or block following the `else` keyword ## Option blocks for streamlined processing of optional data -Motoko offers a preferred method for handling optional data (of type `?T`) through pattern matching, which helps avoid the notorious `null`-exception issues common in other programming languages. -However, using multiple switch statements on several options can become cumbersome and result in deeply nested, hard-to-read code. -To address this, Motoko introduces a feature called *option blocks*, written as `do ? { ... }`. +Motoko offers a preferred method for handling optional data (of type `?T`) through pattern matching, which helps avoid the notorious `null`-exception issues common in other programming languages. +However, using multiple switch statements on several options can become cumbersome and result in deeply nested, hard-to-read code. +To address this, Motoko introduces a feature called *option blocks*, written as `do ? { ... }`. These blocks allow for safe unwrapping of optional values using a postfix `!` operator. -Each use of `!` within the block is equivalent to a switch statement on an option, but with an added benefit: if `!` is applied to a `null` value, the entire block immediately abandons execution and returns `null`. +Each use of `!` within the block is equivalent to a switch statement on an option, but with an added benefit: if `!` is applied to a `null` value, the entire block immediately abandons execution and returns `null`. This short-circuiting behavior simplifies the handling of multiple optional values in a more concise and readable manner. For an example, see [option blocks and null breaks](./control-flow#option-blocks-and-null-breaks). diff --git a/doc/md/writing-motoko/pipes.md b/doc/md/writing-motoko/pipes.md index e12435a8076..5fa8392000c 100644 --- a/doc/md/writing-motoko/pipes.md +++ b/doc/md/writing-motoko/pipes.md @@ -4,7 +4,7 @@ sidebar_position: 20 # Piping values into expressions -## Overview + It can sometimes be hard to read deeply nested expressions involving several function applications. diff --git a/doc/md/writing-motoko/query-functions.md b/doc/md/writing-motoko/query-functions.md index d59ee7e5c8a..9003f81dad1 100644 --- a/doc/md/writing-motoko/query-functions.md +++ b/doc/md/writing-motoko/query-functions.md @@ -4,7 +4,7 @@ sidebar_position: 21 # Query functions -## Overview + In ICP terminology, **update** messages, also referred to as calls, can alter the state of the canister when called. Effecting a state change requires agreement amongst the distributed replicas before the network can commit the change and return a result. Reaching consensus is an expensive process with relatively high latency. diff --git a/doc/md/writing-motoko/randomness.md b/doc/md/writing-motoko/randomness.md index 9deb06f2b1d..7c945368e50 100644 --- a/doc/md/writing-motoko/randomness.md +++ b/doc/md/writing-motoko/randomness.md @@ -4,7 +4,7 @@ sidebar_position: 22 # Randomness -## Overview + The Motoko [`Random`](../base/Random.md) base library can be used for generating random values within smart contracts on ICP. Randomness on ICP is an intricate process, since ICP uses deterministic computing to obtain cryptographic random values. diff --git a/doc/md/writing-motoko/recursive-types.md b/doc/md/writing-motoko/recursive-types.md index 01906425196..e73c32f8559 100644 --- a/doc/md/writing-motoko/recursive-types.md +++ b/doc/md/writing-motoko/recursive-types.md @@ -4,7 +4,7 @@ sidebar_position: 29 # Recursive types -## Overview + A recursive type is a type that contains the values of the same type. Recursive types enable you to create complex recursive data structures, such as linked lists or trees. @@ -38,7 +38,7 @@ This generic function `last` takes one argument `l` of type `List`, which In this switch statement, the `last` function is used recursively, since it is called within itself with `t` as the argument. The function is called again each time the case statement is satisfied, and the function receives a list head that it can switch on until the last element is returned. -:::info +:::info Note that you will need to use recursive functions to access all data in a recursive type. ::: diff --git a/doc/md/writing-motoko/sharing.md b/doc/md/writing-motoko/sharing.md index 4a9f1791946..928034db2a1 100644 --- a/doc/md/writing-motoko/sharing.md +++ b/doc/md/writing-motoko/sharing.md @@ -4,7 +4,7 @@ sidebar_position: 23 # Sharing data and behavior -## Overview + In Motoko, mutable state is always private to an actor. However, two actors can share message data, and those messages can refer to actors, including themselves and one another. Additionally, messages can refer to individual functions, if those functions are `shared`. diff --git a/doc/md/writing-motoko/static-types.md b/doc/md/writing-motoko/static-types.md index 08268b84111..0cce121c9b8 100644 --- a/doc/md/writing-motoko/static-types.md +++ b/doc/md/writing-motoko/static-types.md @@ -4,7 +4,7 @@ sidebar_position: 24 # Static types -## Overview + Like other modern programming languages, Motoko permits each variable to carry the value of a function, object, or a primitive datum such as a string, word, or integer. Other [types of values](../getting-started/basic-concepts.md#intro-values) exist as well, including records, tuples, and tagged data are called variants. diff --git a/doc/md/writing-motoko/structural-equality.md b/doc/md/writing-motoko/structural-equality.md index 1c57b277a20..b8d4aeb15cb 100644 --- a/doc/md/writing-motoko/structural-equality.md +++ b/doc/md/writing-motoko/structural-equality.md @@ -4,7 +4,7 @@ sidebar_position: 25 # Structural equality -## Overview + Equality (`==`) — and by extension inequality (`!=`) — is **structural**. Two values, `a` and `b`, are equal, `a == b`. They have equal contents regardless of the physical representation or identity of those values in memory. diff --git a/doc/md/writing-motoko/timers.md b/doc/md/writing-motoko/timers.md index 0c37edd9eb5..bfcac4c5b31 100644 --- a/doc/md/writing-motoko/timers.md +++ b/doc/md/writing-motoko/timers.md @@ -4,9 +4,9 @@ sidebar_position: 26 # Timers -## Overview -On ICP, canisters can set recurring timers that execute a piece of code after a specified period of time or regular interval. Times in Motoko are implemented using the [`Timer.mo`](../base/Timer.md) module, and return a `TimerId`. `TimerId`s are unique for each timer instance. A canister can contain multiple timers. + +On ICP, canisters can set recurring timers that execute a piece of code after a specified period of time or regular interval. Times in Motoko are implemented using the [`Timer.mo`](../base/Timer.md) module, and return a `TimerId`. `TimerId`s are unique for each timer instance. A canister can contain multiple timers. ## Example diff --git a/doc/md/writing-motoko/writing-intro.md b/doc/md/writing-motoko/writing-intro.md index a2d5006f121..fae678344fa 100644 --- a/doc/md/writing-motoko/writing-intro.md +++ b/doc/md/writing-motoko/writing-intro.md @@ -2,7 +2,7 @@ sidebar_position: 1 --- -# Overview +# Writing Motoko code The Motoko programming language is a new, modern and type safe language for developers who want to build the next generation of distributed applications on ICP, as it is specifically designed to support the unique features of ICP while providing a familiar, yet robust, programming environment. As a new language, Motoko is constantly evolving with support for new features and other improvements. From ac26d8cd6d4f8887d4da6b652abe85634469844c Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Sat, 7 Dec 2024 15:12:56 +0100 Subject: [PATCH 09/18] niv motoko-base: update 4ace2667 -> 3cf818d7 (#4807) ## Changelog for motoko-base: Branch: next-moc Commits: [dfinity/motoko-base@4ace2667...3cf818d7](https://github.com/dfinity/motoko-base/compare/4ace26675fc1222daefb24ac160e0d03000429d2...3cf818d70bf877458d1ebe7a2f047fa0b9fec105) * [`6c608a3d`](https://github.com/dfinity/motoko-base/commit/6c608a3d3f8653fa1a51bdd3763324e071be690f) Motoko 0.13.5 --- nix/sources.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index cafef8ee1ff..fea1a5b6e88 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -75,10 +75,10 @@ "homepage": "", "owner": "dfinity", "repo": "motoko-base", - "rev": "4ace26675fc1222daefb24ac160e0d03000429d2", - "sha256": "0v05djp8ymwc5c9y8ms80cqzx8h2jb9fskfmw8l2mszdcwn8ahsw", + "rev": "3cf818d70bf877458d1ebe7a2f047fa0b9fec105", + "sha256": "0jkck8f5dlba4w52nk9kxnwww4zhfm4kh7kmwcwjns9py7bn7xcv", "type": "tarball", - "url": "https://github.com/dfinity/motoko-base/archive/4ace26675fc1222daefb24ac160e0d03000429d2.tar.gz", + "url": "https://github.com/dfinity/motoko-base/archive/3cf818d70bf877458d1ebe7a2f047fa0b9fec105.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "motoko-matchers": { From 3d9cdf3c871b810175d94ea7f13de13d255a0635 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 10 Dec 2024 17:55:46 +0100 Subject: [PATCH 10/18] chore: first cut of bot-modifiable files (#4814) See policy change https://dfinity.slack.com/archives/CH4CADCJX/p1733844276935979 and (more in-depth) https://docs.google.com/document/d/1B8QeCsyUPws3gQj76lX-wTBMPls4V6qYRrR8tPg8o1Q/edit?tab=t.0 --- .github/repo_policies/BOT_APPROVED_FILES | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/repo_policies/BOT_APPROVED_FILES diff --git a/.github/repo_policies/BOT_APPROVED_FILES b/.github/repo_policies/BOT_APPROVED_FILES new file mode 100644 index 00000000000..46bb21e5391 --- /dev/null +++ b/.github/repo_policies/BOT_APPROVED_FILES @@ -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 + From 107980b83a6658d0d52e24dc28182293298722bb Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Wed, 11 Dec 2024 01:23:20 +0100 Subject: [PATCH 11/18] niv candid: update c2419ac6 -> 067025a8 (#4816) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Changelog for candid: Branch: master Commits: [dfinity/candid@c2419ac6...067025a8](https://github.com/dfinity/candid/compare/c2419ac6b7dfba4dd5e53f964b99bbdebc0308e2...067025a8c55c2b843fce40f6ba38ffe6dd543b84) * [`7758917b`](https://github.com/dfinity/candid/commit/7758917b5b63f40c33fe7a83d8ee1443801d656c) chore: elide needless lifetimes for rust 1.83.0 update to stable ([dfinity/candid⁠#587](https://togithub.com/dfinity/candid/issues/587)) * [`5ee6538e`](https://github.com/dfinity/candid/commit/5ee6538eece1b30e6e719f4e7f3794e915929765) feat: IDLBuilder.try_reserve_value_serializer_capacity ([dfinity/candid⁠#586](https://togithub.com/dfinity/candid/issues/586)) * [`067025a8`](https://github.com/dfinity/candid/commit/067025a8c55c2b843fce40f6ba38ffe6dd543b84) chore: release candid 0.10.11 ([dfinity/candid⁠#588](https://togithub.com/dfinity/candid/issues/588)) --- nix/sources.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index fea1a5b6e88..7c13da184aa 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -6,10 +6,10 @@ "homepage": "", "owner": "dfinity", "repo": "candid", - "rev": "c2419ac6b7dfba4dd5e53f964b99bbdebc0308e2", - "sha256": "1pf0yb8f876n6d14j55x5dwkywnx1fxbznrnz28545bm8nxjc6k0", + "rev": "067025a8c55c2b843fce40f6ba38ffe6dd543b84", + "sha256": "047j585rlfilcczrslvyanycp4qqfnzy31crxgcz8sazz7jbk1za", "type": "tarball", - "url": "https://github.com/dfinity/candid/archive/c2419ac6b7dfba4dd5e53f964b99bbdebc0308e2.tar.gz", + "url": "https://github.com/dfinity/candid/archive/067025a8c55c2b843fce40f6ba38ffe6dd543b84.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "esm": { From 8e9a53a57e53239cd986befaa85530ffc18ae04a Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 12 Dec 2024 16:32:21 +0100 Subject: [PATCH 12/18] perf: `ShrU 31` before `If` can be `Clz` (#4813) `i32.shr_u 31; if` is emitted when testing if a `Nat32` fits into a word. This peephole scrapes off one instruction. Similarly for `i32.and (2^31); if`! Added it to https://github.com/WebAssembly/binaryen/issues/5752. --- src/codegen/instrList.ml | 7 +++++++ test/bench/ok/heap-32.drun-run.ok | 2 +- test/run/top-bit.mo | 12 ++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 test/run/top-bit.mo diff --git a/src/codegen/instrList.ml b/src/codegen/instrList.ml index 886a103cdd1..b885c3c3e62 100644 --- a/src/codegen/instrList.ml +++ b/src/codegen/instrList.ml @@ -125,6 +125,13 @@ let optimize : instr list -> instr list = fun is -> ({it = Const cr; _} as const) :: ({it = Binary opr; _} as op) :: r' when Option.is_some (combine_shifts const op (opl, cl, opr, cr.it)) -> go l' (Option.get (combine_shifts const op (opl, cl, opr, cr.it)) @ r') + (* Examining topmost bit *) + | {it = Binary (I32 I32Op.ShrU); _} as shift :: {it = Const {it = I32 31l; _}; _} :: l', + ({it = If (res,then_,else_); _} as if_) :: r' -> + go l' ({ shift with it = Unary (I32 I32Op.Clz) } :: { if_ with it = If (res,else_,then_) } :: r') + | {it = Binary (I32 I32Op.And); _} as and_ :: {it = Const {it = I32 2147483648l; _}; _} :: l', + ({it = If (res,then_,else_); _} as if_) :: r' -> + go l' ({ and_ with it = Unary (I32 I32Op.Clz) } :: { if_ with it = If (res,else_,then_) } :: r') (* Null shifts can be eliminated *) | l', {it = Const {it = I32 0l; _}; _} :: {it = Binary (I32 I32Op.(Shl|ShrS|ShrU)); _} :: r' -> go l' r' diff --git a/test/bench/ok/heap-32.drun-run.ok b/test/bench/ok/heap-32.drun-run.ok index 8ae164a705f..5d3d216fe42 100644 --- a/test/bench/ok/heap-32.drun-run.ok +++ b/test/bench/ok/heap-32.drun-run.ok @@ -1,5 +1,5 @@ ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 ingress Completed: Reply: 0x4449444c0000 -debug.print: (50_227, +29_863_068, 723_684_961) +debug.print: (50_227, +29_863_068, 723_584_961) debug.print: (50_070, +32_992_212, 785_200_313) ingress Completed: Reply: 0x4449444c0000 diff --git a/test/run/top-bit.mo b/test/run/top-bit.mo new file mode 100644 index 00000000000..7981ea7a0db --- /dev/null +++ b/test/run/top-bit.mo @@ -0,0 +1,12 @@ +//CLASSICAL-PERSISTENCE-ONLY + +var x : Nat32 = 4294967295; +assert (x >> 31 != 0); +assert (x & 2147483648 != 0); + +// CHECK-LABEL: (func $init +// CHECK: i32.clz +// CHECK-NEXT: if ;; +// CHECK: i32.clz +// CHECK-NEXT: if ;; +// CHECK: end) From e88efd9f9b7a7631586ea4ea06432426a1dcb986 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 21:43:24 +0000 Subject: [PATCH 13/18] chore(deps): Bump nanoid from 3.3.6 to 3.3.8 in /doc/docusaurus (#4821) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.6 to 3.3.8.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=nanoid&package-manager=npm_and_yarn&previous-version=3.3.6&new-version=3.3.8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/dfinity/motoko/network/alerts).
--- doc/docusaurus/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/docusaurus/package-lock.json b/doc/docusaurus/package-lock.json index 13dfb59a064..88dba11c435 100644 --- a/doc/docusaurus/package-lock.json +++ b/doc/docusaurus/package-lock.json @@ -9104,9 +9104,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "funding": [ { "type": "github", @@ -20300,9 +20300,9 @@ } }, "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==" }, "negotiator": { "version": "0.6.3", From 481b8e21452425b561a734f7aa8cc4faa51640c5 Mon Sep 17 00:00:00 2001 From: Ryan Vandersmith Date: Mon, 16 Dec 2024 12:38:17 -0700 Subject: [PATCH 14/18] Update CODEOWNERS (#4824) --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8f1b29d8c54..15bd79c8276 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -@dfinity/languages +* @dfinity/languages From 606e9e4ffb742829f8e616587e97493833d7aa3c Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 18 Dec 2024 13:56:54 +0100 Subject: [PATCH 15/18] chore: update `BOT_APPROVED_FILES` (#4827) It gets updated by @dfinity-bot, see https://github.com/dfinity/motoko/pull/4826. --- .github/repo_policies/BOT_APPROVED_FILES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/repo_policies/BOT_APPROVED_FILES b/.github/repo_policies/BOT_APPROVED_FILES index 46bb21e5391..c9aba6b6290 100644 --- a/.github/repo_policies/BOT_APPROVED_FILES +++ b/.github/repo_policies/BOT_APPROVED_FILES @@ -2,4 +2,4 @@ Changelog.md doc/docusaurus/package-lock.json - +nix/sources.json From 9ae06e3d1c9df21a9406dc6546bd0ba89b8b7941 Mon Sep 17 00:00:00 2001 From: Luc Blaeser <112870813+luc-blaeser@users.noreply.github.com> Date: Wed, 18 Dec 2024 14:08:57 +0100 Subject: [PATCH 16/18] Fix small docu bug (#4828) --- doc/md/canister-maintenance/compatibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/md/canister-maintenance/compatibility.md b/doc/md/canister-maintenance/compatibility.md index 9592856ad83..06c9a65e320 100644 --- a/doc/md/canister-maintenance/compatibility.md +++ b/doc/md/canister-maintenance/compatibility.md @@ -240,7 +240,7 @@ Adding a new record field to the type of existing stable variable is not support ### 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. From aa676b21cf0b51d83323251572a3d4a3338631bb Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Wed, 18 Dec 2024 14:35:05 +0100 Subject: [PATCH 17/18] niv candid: update 067025a8 -> 87f42eef (#4825) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Changelog for candid: Branch: master Commits: [dfinity/candid@067025a8...87f42eef](https://github.com/dfinity/candid/compare/067025a8c55c2b843fce40f6ba38ffe6dd543b84...87f42eefb1070381565d8de3235628a674641fbd) * [`87f42eef`](https://github.com/dfinity/candid/commit/87f42eefb1070381565d8de3235628a674641fbd) Update CODEOWNERS ([dfinity/candid⁠#589](https://togithub.com/dfinity/candid/issues/589)) --- nix/sources.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index 7c13da184aa..978ae600115 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -6,10 +6,10 @@ "homepage": "", "owner": "dfinity", "repo": "candid", - "rev": "067025a8c55c2b843fce40f6ba38ffe6dd543b84", - "sha256": "047j585rlfilcczrslvyanycp4qqfnzy31crxgcz8sazz7jbk1za", + "rev": "87f42eefb1070381565d8de3235628a674641fbd", + "sha256": "1kfchlrfwk5b6ahhkkrkf9iby9znjri4jcjwbm3kwiqx8g9v97dp", "type": "tarball", - "url": "https://github.com/dfinity/candid/archive/067025a8c55c2b843fce40f6ba38ffe6dd543b84.tar.gz", + "url": "https://github.com/dfinity/candid/archive/87f42eefb1070381565d8de3235628a674641fbd.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "esm": { From d87550d3ff875c69140e02be5749811a4fee3bb6 Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Wed, 18 Dec 2024 14:44:33 +0100 Subject: [PATCH 18/18] niv motoko-base: update 3cf818d7 -> bf3b522b (#4826) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Changelog for motoko-base: Branch: next-moc Commits: [dfinity/motoko-base@3cf818d7...bf3b522b](https://github.com/dfinity/motoko-base/compare/3cf818d70bf877458d1ebe7a2f047fa0b9fec105...bf3b522b3e2dab992c9d2544cb438e10ef2fac1a) * [`c6331b0f`](https://github.com/dfinity/motoko-base/commit/c6331b0f236e13581b6b094a9b6442ffbc0b254c) Update CODEOWNERS ([dfinity/motoko-base⁠#679](https://togithub.com/dfinity/motoko-base/issues/679)) --- nix/sources.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index 978ae600115..bef8be1fa0a 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -75,10 +75,10 @@ "homepage": "", "owner": "dfinity", "repo": "motoko-base", - "rev": "3cf818d70bf877458d1ebe7a2f047fa0b9fec105", - "sha256": "0jkck8f5dlba4w52nk9kxnwww4zhfm4kh7kmwcwjns9py7bn7xcv", + "rev": "bf3b522b3e2dab992c9d2544cb438e10ef2fac1a", + "sha256": "0pyqwv7af6ccd3imwbnww64959k56vl8r9dsr2g25spmnfsnrl7a", "type": "tarball", - "url": "https://github.com/dfinity/motoko-base/archive/3cf818d70bf877458d1ebe7a2f047fa0b9fec105.tar.gz", + "url": "https://github.com/dfinity/motoko-base/archive/bf3b522b3e2dab992c9d2544cb438e10ef2fac1a.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "motoko-matchers": {
Changelog

Sourced from nanoid's changelog.

3.3.8

  • Fixed a way to break Nano ID by passing non-integer size (by @​myndzi).

3.3.7

  • Fixed node16 TypeScript support (by Saadi Myftija).