From b524bd455f672f9d709a7374d17ce137370df250 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Mon, 15 Sep 2025 10:53:46 +0200 Subject: [PATCH 01/22] rename artifacts on draft release --- .github/workflows/release.yml | 145 ++++++++++++++++++++++------------ 1 file changed, 94 insertions(+), 51 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ad56b69f5cf..71f232058e8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,7 @@ name: release on: push: tags: - - '*' + - "*" workflow_dispatch: # To test this workflow: Go to Actions -> release -> Run workflow # Or using the CLI: gh workflow run release --ref -f version=test-draft-release @@ -11,7 +11,7 @@ on: # Remember to delete the draft release after testing! inputs: version: - description: 'Version for draft release (default: test-draft-release)' + description: "Version for draft release (default: test-draft-release)" required: false default: test-draft-release type: string @@ -25,19 +25,34 @@ jobs: - name: Prepare release run: echo "Preparing release for version ${{ inputs.version || github.ref_name }}" + - name: Validate draft suffix (workflow_dispatch only) + if: ${{ github.event_name == 'workflow_dispatch' }} + run: | + set -eu + SUFFIX="${{ inputs.version }}" + if [ -z "${SUFFIX:-}" ]; then + echo "Error: inputs.version (draft suffix) is empty" + exit 1 + fi + # Allow only letters and hyphens + if ! printf '%s' "${SUFFIX}" | grep -Eq '^[A-Za-z-]+$'; then + echo "Error: inputs.version must contain only letters and hyphens (e.g., experimental-stable-functions)" + exit 1 + fi + # Check that the changelog is in good order and extract the changelog. changelog: runs-on: ubuntu-latest needs: prepare steps: - - uses: actions/checkout@v5 - - name: Extract changelog - # Skip this step for draft releases. Leave the release body empty. - if: ${{ github.event_name != 'workflow_dispatch' }} - id: read_changelog - uses: ./.github/actions/extract-changelog - with: - version: ${{ needs.prepare.outputs.version }} + - uses: actions/checkout@v5 + - name: Extract changelog + # Skip this step for draft releases. Leave the release body empty. + if: ${{ github.event_name != 'workflow_dispatch' }} + id: read_changelog + uses: ./.github/actions/extract-changelog + with: + version: ${{ needs.prepare.outputs.version }} outputs: release_body: ${{ steps.read_changelog.outputs.release_body }} @@ -45,59 +60,87 @@ jobs: needs: prepare strategy: matrix: - os: [ ubuntu-latest, macos-13, ubuntu-24.04-arm, macos-latest ] + os: [ubuntu-latest, macos-13, ubuntu-24.04-arm, macos-latest] concurrency: group: release-build-${{ matrix.os }}-${{ needs.prepare.outputs.version }} cancel-in-progress: true runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v5 - - uses: cachix/install-nix-action@v31 - - uses: cachix/cachix-action@v16 - with: - name: ic-hs-test - # NB: No auth token, we don't expect to push new stuff here + - uses: actions/checkout@v5 + - uses: cachix/install-nix-action@v31 + - uses: cachix/cachix-action@v16 + with: + name: ic-hs-test + # NB: No auth token, we don't expect to push new stuff here - - name: Build platform-specific release files - run: nix build --max-jobs 1 '.#"release-files-${{ matrix.os }}"' + - name: Build platform-specific release files + run: nix build --max-jobs 1 '.#"release-files-${{ matrix.os }}"' - - name: Upload Release Artifacts - uses: actions/upload-artifact@v4 - with: - name: release-files-${{ matrix.os }} - path: result/* + - name: Upload Release Artifacts + uses: actions/upload-artifact@v4 + with: + name: release-files-${{ matrix.os }} + path: result/* - - name: Test release files - run: | - uname -s -m - moc="$(nix build --max-jobs 1 .#release.moc --print-out-paths)" - "$moc/bin/moc" --version - file "$moc/bin/moc" - ldd "$moc/bin/moc" || true + - name: Test release files + run: | + uname -s -m + moc="$(nix build --max-jobs 1 .#release.moc --print-out-paths)" + "$moc/bin/moc" --version + file "$moc/bin/moc" + ldd "$moc/bin/moc" || true publish: runs-on: ubuntu-latest needs: [prepare, changelog, build] steps: - - name: Download all release artifacts - uses: actions/download-artifact@v5 - with: - path: release-assets - pattern: release-files-* - merge-multiple: true + - name: Download all release artifacts + uses: actions/download-artifact@v5 + with: + path: release-assets + pattern: release-files-* + merge-multiple: true + + - name: Rewrite artifact filenames with draft suffix + if: ${{ github.event_name == 'workflow_dispatch' }} + env: + DRAFT_SUFFIX: ${{ inputs.version }} + run: | + set -eu + echo "Applying draft suffix: ${DRAFT_SUFFIX}" + dir="release-assets" + # Extract numeric version from moc-.js + version="$(ls "$dir"/moc-*.js 2>/dev/null | sed -n 's#.*moc-\([0-9.]\+\)\.js#\1#p' | head -n1 || true)" + if [ -z "${version}" ]; then + echo "Could not determine base version from moc-*.js; skipping rename." + exit 0 + fi + echo "Detected base version: ${version}" + # Rename JS artifacts + if [ -f "$dir/moc-${version}.js" ]; then + mv "$dir/moc-${version}.js" "$dir/moc-${version}-${DRAFT_SUFFIX}.js" + fi + if [ -f "$dir/moc-interpreter-${version}.js" ]; then + mv "$dir/moc-interpreter-${version}.js" "$dir/moc-interpreter-${version}-${DRAFT_SUFFIX}.js" + fi + # Rename tarballs + for f in "$dir"/*-"${version}".tar.gz; do + [ -e "$f" ] || continue + mv "$f" "${f%.tar.gz}-${DRAFT_SUFFIX}.tar.gz" + done - - name: List downloaded files - run: | - echo "Contents of release-assets directory:" - find release-assets -type f -ls || true + - name: List downloaded files + run: | + echo "Contents of release-assets directory:" + find release-assets -type f -ls || true - - name: Upload Release Assets - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - tag: ${{ needs.prepare.outputs.version }} - file: release-assets/* - file_glob: true - body: ${{ needs.changelog.outputs.release_body || 'Draft release created for testing purposes' }} - draft: ${{ github.event_name == 'workflow_dispatch' }} - prerelease: ${{ github.event_name == 'workflow_dispatch' }} + - name: Upload Release Assets + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ needs.prepare.outputs.version }} + file: release-assets/* + file_glob: true + body: ${{ needs.changelog.outputs.release_body || 'Draft release created for testing purposes' }} + draft: ${{ github.event_name == 'workflow_dispatch' }} + prerelease: ${{ github.event_name == 'workflow_dispatch' }} From f65a429597ab4d336c8f2f8c4eb40e8c43777252 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Mon, 15 Sep 2025 10:59:38 +0200 Subject: [PATCH 02/22] try to link motoko-core to luc/oo-data-structures --- flake.lock | 7 ++++--- flake.nix | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index d39bb2b6898..c6b156a6d51 100644 --- a/flake.lock +++ b/flake.lock @@ -137,15 +137,16 @@ "motoko-core-src": { "flake": false, "locked": { - "lastModified": 1756913868, - "narHash": "sha256-zLJShje+X/+4yM0wTwNB9Bri00SH6G3vOvyUP56KdwU=", + "lastModified": 1757337895, + "narHash": "sha256-G5BlQfm/TJ0Trk5owOGDOTxoigcf5ErgnSEDyPe20fk=", "owner": "dfinity", "repo": "motoko-core", - "rev": "e397d7e577491703d94a1f82dc88ff01c59c0dbd", + "rev": "59310bfed843c072882ad48980a366fb87f19f03", "type": "github" }, "original": { "owner": "dfinity", + "ref": "luc/oo-data-structures", "repo": "motoko-core", "type": "github" } diff --git a/flake.nix b/flake.nix index 0489f9d7e63..67843862985 100644 --- a/flake.nix +++ b/flake.nix @@ -46,7 +46,7 @@ flake = false; }; motoko-core-src = { - url = "github:dfinity/motoko-core"; + url = "github:dfinity/motoko-core/luc/oo-data-structures"; flake = false; }; motoko-matchers-src = { From cc4fab23814bd8857821ed84305a1b3433ae9c11 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Mon, 15 Sep 2025 11:35:22 +0200 Subject: [PATCH 03/22] allow digits --- .github/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 71f232058e8..ddbd8ed0d53 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,9 +34,9 @@ jobs: echo "Error: inputs.version (draft suffix) is empty" exit 1 fi - # Allow only letters and hyphens - if ! printf '%s' "${SUFFIX}" | grep -Eq '^[A-Za-z-]+$'; then - echo "Error: inputs.version must contain only letters and hyphens (e.g., experimental-stable-functions)" + # Allow only letters, digits, and hyphens + if ! printf '%s' "${SUFFIX}" | grep -Eq '^[A-Za-z0-9-]+$'; then + echo "Error: inputs.version must contain only letters, digits, and hyphens (e.g., experimental-foo-2)" exit 1 fi From 2a5e94e10f45c92ad5f40ddaa10c0259fa48be15 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Mon, 15 Sep 2025 12:47:17 +0200 Subject: [PATCH 04/22] repro type inference needs fixing --- test/run/use-persistent-function.mo | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 test/run/use-persistent-function.mo diff --git a/test/run/use-persistent-function.mo b/test/run/use-persistent-function.mo new file mode 100644 index 00000000000..f561345cb63 --- /dev/null +++ b/test/run/use-persistent-function.mo @@ -0,0 +1,25 @@ +import Prim "mo:⛔"; + +type Order = { #less; #equal; #greater }; + +module Array { + public func sort(array : [T], compare : (T, T) -> Order) : [T] { + if (compare(array[0], array[1]) == #less) { + [array[0], array[1]]; + } else { + array; + }; + }; +}; + +module Nat { + public persistent func compare(x : Nat, y : Nat) : Order { + if (x < y) { #less } else if (x == y) { #equal } else { #greater }; + }; +}; + +let a : [Nat] = [2, 1]; +let b : [Nat] = [1, 2]; + +assert Array.sort(a, Nat.compare) == [1, 2]; +assert Array.sort(b, Nat.compare) == [1, 2]; From 9ccfb8caf191d1e32f1a2da1c3f9be0e2e583ac4 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Mon, 15 Sep 2025 14:00:56 +0200 Subject: [PATCH 05/22] bug? --- test/run/use-persistent-function.mo | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/run/use-persistent-function.mo b/test/run/use-persistent-function.mo index f561345cb63..5e5d9634517 100644 --- a/test/run/use-persistent-function.mo +++ b/test/run/use-persistent-function.mo @@ -1,5 +1,3 @@ -import Prim "mo:⛔"; - type Order = { #less; #equal; #greater }; module Array { From e016f2fe53c226757d41c9c5eab77b5336dec63e Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Mon, 15 Sep 2025 14:22:29 +0200 Subject: [PATCH 06/22] claudio bimatch repro --- test/run-drun/bimatch-persistent-func.mo | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 test/run-drun/bimatch-persistent-func.mo diff --git a/test/run-drun/bimatch-persistent-func.mo b/test/run-drun/bimatch-persistent-func.mo new file mode 100644 index 00000000000..4e8648ac800 --- /dev/null +++ b/test/run-drun/bimatch-persistent-func.mo @@ -0,0 +1,7 @@ +persistent actor { + persistent func g(x : T) : persistent () -> T { + persistent func h() : T { x }; + h; + }; + stable let h = g ()>(func () {}); +} \ No newline at end of file From 1447d0f0214ca42778c6a08d76f4b4087970d1c5 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Mon, 15 Sep 2025 20:39:00 +0200 Subject: [PATCH 07/22] missing error where assert was --- src/mo_frontend/typing.ml | 3 ++- test/run-drun/bimatch-persistent-func.mo | 12 ++++++------ test/run-drun/ok/bimatch-persistent-func.tc.ok | 5 +++++ test/run-drun/ok/bimatch-persistent-func.tc.ret.ok | 1 + 4 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 test/run-drun/ok/bimatch-persistent-func.tc.ok create mode 100644 test/run-drun/ok/bimatch-persistent-func.tc.ret.ok diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index cb577c71f35..333a3dafc62 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -2308,7 +2308,8 @@ and check_func_step in_actor env (shared_pat, pat, typ_opt, exp) (s, c, ts1, ts2 if sort <> s then (match sort, s with | T.Local T.Stable, T.Local T.Flexible -> () (* okay *) - | T.Local _, T.Local _ -> assert false (* caught by sub-type check *) + | T.Local _, T.Local _ -> + error env exp.at "M0220" "this function should be declared `persistent`" | _, _ -> error env exp.at "M0094" "%sshared function does not match expected %sshared function type" diff --git a/test/run-drun/bimatch-persistent-func.mo b/test/run-drun/bimatch-persistent-func.mo index 4e8648ac800..feba3833f99 100644 --- a/test/run-drun/bimatch-persistent-func.mo +++ b/test/run-drun/bimatch-persistent-func.mo @@ -1,7 +1,7 @@ persistent actor { - persistent func g(x : T) : persistent () -> T { - persistent func h() : T { x }; - h; - }; - stable let h = g ()>(func () {}); -} \ No newline at end of file + persistent func g(x : T) : persistent() -> T { + persistent func h() : T { x }; + h; + }; + stable let h = g ()>(func() {}); +}; diff --git a/test/run-drun/ok/bimatch-persistent-func.tc.ok b/test/run-drun/ok/bimatch-persistent-func.tc.ok new file mode 100644 index 00000000000..7c09f182921 --- /dev/null +++ b/test/run-drun/ok/bimatch-persistent-func.tc.ok @@ -0,0 +1,5 @@ +bimatch-persistent-func.mo:4.5-4.6: type error [M0096], expression of type + () -> T +cannot produce expected type + persistent () -> T +bimatch-persistent-func.mo:6.47-6.49: type error [M0220], this function should be declared `persistent` diff --git a/test/run-drun/ok/bimatch-persistent-func.tc.ret.ok b/test/run-drun/ok/bimatch-persistent-func.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/bimatch-persistent-func.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 From b309b935ff2e79087fb3f799ae763420c56e57a8 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Tue, 16 Sep 2025 10:34:58 +0200 Subject: [PATCH 08/22] claudio test with module in test/fail --- .../ok/persistent-func-type-argument-and-return.tc.ok | 1 + .../ok/persistent-func-type-argument-and-return.tc.ret.ok | 1 + test/fail/persistent-func-type-argument-and-return.mo | 8 ++++++++ 3 files changed, 10 insertions(+) create mode 100644 test/fail/ok/persistent-func-type-argument-and-return.tc.ok create mode 100644 test/fail/ok/persistent-func-type-argument-and-return.tc.ret.ok create mode 100644 test/fail/persistent-func-type-argument-and-return.mo diff --git a/test/fail/ok/persistent-func-type-argument-and-return.tc.ok b/test/fail/ok/persistent-func-type-argument-and-return.tc.ok new file mode 100644 index 00000000000..81d632c9bc0 --- /dev/null +++ b/test/fail/ok/persistent-func-type-argument-and-return.tc.ok @@ -0,0 +1 @@ +persistent-func-type-argument-and-return.mo:6.40-6.42: type error [M0220], this function should be declared `persistent` diff --git a/test/fail/ok/persistent-func-type-argument-and-return.tc.ret.ok b/test/fail/ok/persistent-func-type-argument-and-return.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/persistent-func-type-argument-and-return.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/persistent-func-type-argument-and-return.mo b/test/fail/persistent-func-type-argument-and-return.mo new file mode 100644 index 00000000000..e0038ac4edd --- /dev/null +++ b/test/fail/persistent-func-type-argument-and-return.mo @@ -0,0 +1,8 @@ +module { + persistent func g(x : T) : persistent() -> T { + persistent func h() : T { x }; + h; // TODO: non-eop should still typecheck here + }; + // don't allow `func() {}` to typecheck as `persistent() -> ()` for now + let h = g ()>(func() {}); +}; From ad5b9d1efb5c5688ba046aee77544f129f818268 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Tue, 16 Sep 2025 10:41:48 +0200 Subject: [PATCH 09/22] eop only test, running --- test/run-drun/ok/bimatch-persistent-func.tc.ok | 5 ----- test/run-drun/ok/bimatch-persistent-func.tc.ret.ok | 1 - ...with-persistent-funcs-in-type-args-and-return.drun-run.ok | 2 ++ ...t-actor-with-persistent-funcs-in-type-args-and-return.mo} | 4 +++- 4 files changed, 5 insertions(+), 7 deletions(-) delete mode 100644 test/run-drun/ok/bimatch-persistent-func.tc.ok delete mode 100644 test/run-drun/ok/bimatch-persistent-func.tc.ret.ok create mode 100644 test/run-drun/ok/persistent-actor-with-persistent-funcs-in-type-args-and-return.drun-run.ok rename test/run-drun/{bimatch-persistent-func.mo => persistent-actor-with-persistent-funcs-in-type-args-and-return.mo} (53%) diff --git a/test/run-drun/ok/bimatch-persistent-func.tc.ok b/test/run-drun/ok/bimatch-persistent-func.tc.ok deleted file mode 100644 index 7c09f182921..00000000000 --- a/test/run-drun/ok/bimatch-persistent-func.tc.ok +++ /dev/null @@ -1,5 +0,0 @@ -bimatch-persistent-func.mo:4.5-4.6: type error [M0096], expression of type - () -> T -cannot produce expected type - persistent () -> T -bimatch-persistent-func.mo:6.47-6.49: type error [M0220], this function should be declared `persistent` diff --git a/test/run-drun/ok/bimatch-persistent-func.tc.ret.ok b/test/run-drun/ok/bimatch-persistent-func.tc.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/bimatch-persistent-func.tc.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/persistent-actor-with-persistent-funcs-in-type-args-and-return.drun-run.ok b/test/run-drun/ok/persistent-actor-with-persistent-funcs-in-type-args-and-return.drun-run.ok new file mode 100644 index 00000000000..a6f776f43c6 --- /dev/null +++ b/test/run-drun/ok/persistent-actor-with-persistent-funcs-in-type-args-and-return.drun-run.ok @@ -0,0 +1,2 @@ +ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 +ingress Completed: Reply: 0x4449444c0000 diff --git a/test/run-drun/bimatch-persistent-func.mo b/test/run-drun/persistent-actor-with-persistent-funcs-in-type-args-and-return.mo similarity index 53% rename from test/run-drun/bimatch-persistent-func.mo rename to test/run-drun/persistent-actor-with-persistent-funcs-in-type-args-and-return.mo index feba3833f99..64f2f986dd4 100644 --- a/test/run-drun/bimatch-persistent-func.mo +++ b/test/run-drun/persistent-actor-with-persistent-funcs-in-type-args-and-return.mo @@ -1,7 +1,9 @@ +//ENHANCED-ORTHOGONAL-PERSISTENCE-ONLY persistent actor { persistent func g(x : T) : persistent() -> T { persistent func h() : T { x }; h; }; - stable let h = g ()>(func() {}); + let h = g ()>(persistent func _anon() {}); + h(); }; From 4600bd3f34ddbfc2e8c49dcabf03f6e1eaf016df Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Tue, 16 Sep 2025 10:42:38 +0200 Subject: [PATCH 10/22] rel_sort, combine_sort --- src/mo_frontend/bi_match.ml | 2 +- src/mo_types/type.ml | 17 +++++++++++++++-- src/mo_types/type.mli | 1 + 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index 8fdaa24dcf4..60f2bc6a0a4 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -261,7 +261,7 @@ let bi_match_typs ctx = | Tup ts1, Tup ts2 -> bi_match_list bi_match_typ rel eq inst any ts1 ts2 | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> - if s1 = s2 && c1 = c2 then + if rel_sort s1 s2 tbs1 && c1 = c2 then (match bi_match_binds rel eq inst any tbs1 tbs2 with | Some (inst, ts) -> let any' = List.fold_right diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index c749175a558..1c691ab50d2 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1593,15 +1593,17 @@ let rec combine rel lubs glbs t1 t2 = (try Obj (s1, combine_fields rel lubs glbs tf1 tf2) with Mismatch -> assert (rel == glbs); Non) | Func (s1, c1, bs1, ts11, ts12), Func (s2, c2, bs2, ts21, ts22) when - s1 = s2 && c1 = c2 && eq_binds bs1 bs2 && + combine_sort rel lubs glbs s1 s2 bs1 bs2 <> None && + c1 = c2 && eq_binds bs1 bs2 && List.(length ts11 = length ts21 && length ts12 = length ts22) -> let ts = open_binds bs1 in let cs = List.map (fun t -> fst (as_con t)) ts in let opened = List.map (open_ ts) in let closed = List.map (close cs) in let rel' = if rel == lubs then glbs else lubs in + let s = Option.get (combine_sort rel lubs glbs s1 s2 bs1 bs2) in Func ( - s1, c1, bs1, + s, c1, bs1, closed (List.map2 (combine rel' lubs glbs) (opened ts11) (opened ts21)), closed (List.map2 (combine rel lubs glbs) (opened ts12) (opened ts22)) ) @@ -1647,6 +1649,17 @@ let rec combine rel lubs glbs t1 t2 = | _, _ -> if rel == lubs then Any else Non +and combine_sort rel lubs glbs s1 s2 bs1 bs2= + if s1 = s2 then Some s1 else + let both s = + if rel_sort s1 s bs1 && rel_sort s2 s bs2 then Some s + else None + in + if rel == lubs then + both (Local Flexible) + else + both (Local Stable) + and cons_if b x xs = if b then x::xs else xs and combine_fields rel lubs glbs fs1 fs2 = diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 4d7e950dfac..ca420945b4b 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -276,6 +276,7 @@ val eq_kind : ?src_fields : Field_sources.t -> kind -> kind -> bool val sub : ?src_fields : Field_sources.t -> typ -> typ -> bool val sub_explained : ?src_fields : Field_sources.t -> context -> typ -> typ -> compatibility val compatible : typ -> typ -> bool +val rel_sort : func_sort -> func_sort -> bind list -> bool exception PreEncountered val lub : ?src_fields : Field_sources.t -> typ -> typ -> typ From f3cd87204cae8a3c476d718fe15b187b8e011e8b Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Tue, 16 Sep 2025 11:10:12 +0200 Subject: [PATCH 11/22] fix test --- test/run/use-persistent-function.mo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/run/use-persistent-function.mo b/test/run/use-persistent-function.mo index 5e5d9634517..0373b00de05 100644 --- a/test/run/use-persistent-function.mo +++ b/test/run/use-persistent-function.mo @@ -2,8 +2,8 @@ type Order = { #less; #equal; #greater }; module Array { public func sort(array : [T], compare : (T, T) -> Order) : [T] { - if (compare(array[0], array[1]) == #less) { - [array[0], array[1]]; + if (compare(array[0], array[1]) == #greater) { + [array[1], array[0]]; } else { array; }; From 66b6b957123514a8fcb0d9a2e48a2fd470129f29 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Tue, 16 Sep 2025 11:27:05 +0200 Subject: [PATCH 12/22] line change --- test/fail/ok/persistent-func-type-argument-and-return.tc.ok | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fail/ok/persistent-func-type-argument-and-return.tc.ok b/test/fail/ok/persistent-func-type-argument-and-return.tc.ok index 81d632c9bc0..f1a932f5c7b 100644 --- a/test/fail/ok/persistent-func-type-argument-and-return.tc.ok +++ b/test/fail/ok/persistent-func-type-argument-and-return.tc.ok @@ -1 +1 @@ -persistent-func-type-argument-and-return.mo:6.40-6.42: type error [M0220], this function should be declared `persistent` +persistent-func-type-argument-and-return.mo:7.40-7.42: type error [M0220], this function should be declared `persistent` From 2832156aab779b06790d1839abb3c7334e86b3d3 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Tue, 16 Sep 2025 11:27:53 +0200 Subject: [PATCH 13/22] try disabling implicit func conversion from Stable to Flexible when eop flag is off --- src/mo_frontend/typing.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 333a3dafc62..1665656fe73 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1697,10 +1697,10 @@ and infer_exp'' env exp : T.typ = | _ -> () end; let sort, ve = check_shared_pat env shared_pat in - let sort = match sort, !Mo_config.Flags.enhanced_orthogonal_persistence with + (* let sort = match sort, !Mo_config.Flags.enhanced_orthogonal_persistence with | T.Local T.Stable, false -> T.Local T.Flexible (* named local functions are flexible in classical mode *) | _ -> sort - in + in *) let is_async = match typ_opt with | Some { it = AsyncT _; _ } -> true | _ -> false @@ -1769,7 +1769,7 @@ and infer_exp'' env exp : T.typ = end end; let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in - let sort = if is_flexible && sort = T.Local T.Stable then T.Local T.Flexible else sort in + (* let sort = if is_flexible && sort = T.Local T.Stable then T.Local T.Flexible else sort in *) T.Func (sort, c, T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | CallE (par_opt, exp1, inst, exp2) -> let t = infer_call env exp1 inst exp2 exp.at None in From 64789bc17338dc4c14d45b26b2fc1e19495907fb Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Tue, 16 Sep 2025 12:43:56 +0200 Subject: [PATCH 14/22] script for replacing mops-cached moc, with backups and restore --- scripts/replace-mops-moc | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100755 scripts/replace-mops-moc diff --git a/scripts/replace-mops-moc b/scripts/replace-mops-moc new file mode 100755 index 00000000000..af2ab71cbd4 --- /dev/null +++ b/scripts/replace-mops-moc @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# replace-mops-moc: Build moc via Nix and replace a mops-cached moc binary. +# Usage: ./replace-mops-moc [restore] +# - Without 'restore': builds .#release.moc, backs up existing 'moc' once as 'moc-backup' if absent, +# then installs the newly built 'moc' into the target version directory. +# - With 'restore': moves 'moc-backup' back to 'moc' (overwriting current), then prints version. +set -euo pipefail + +if [ "${1:-}" = "" ]; then + echo "Usage: $0 [restore]" >&2 + echo "Example replace: $0 0.16.1" >&2 + echo "Example restore: $0 0.16.1 restore" >&2 + exit 2 +fi + +VERSION_DIR="$1" +TARGET_DIR="${HOME}/Library/Caches/mops/moc/${VERSION_DIR}" +TARGET="${TARGET_DIR}/moc" +BACKUP="${TARGET}-backup" +MODE="${2:-}" + +# Do not create directories; assume they exist as requested. +if [ ! -d "${TARGET_DIR}" ]; then + echo "Error: Target directory does not exist: ${TARGET_DIR}" >&2 + exit 1 +fi + +if [ "${MODE}" = "restore" ]; then + echo "Restoring backup for ${TARGET}" + if [ ! -f "${BACKUP}" ]; then + echo "Error: No backup found at ${BACKUP}" >&2 + exit 1 + fi + mv -f "${BACKUP}" "${TARGET}" + chmod +x "${TARGET}" || true + echo "Restored. Version:" + "${TARGET}" --version || true + exit 0 +fi + +echo "Building moc via Nix (.#release.moc)..." +OUT_PATH="$(nix build --max-jobs 1 .#release.moc --print-out-paths)" +SRC="${OUT_PATH}/bin/moc" + +echo "Using built moc at: ${SRC}" +echo "Target directory: ${TARGET_DIR}" +echo "Target binary: ${TARGET}" + +# Step 1: Backup existing moc if no backup exists yet +if [ -f "${BACKUP}" ]; then + echo "Backup already exists at ${BACKUP}; skipping backup." +else + if [ -f "${TARGET}" ]; then + echo "Creating backup at ${BACKUP}" + mv "${TARGET}" "${BACKUP}" + else + echo "No existing moc found at ${TARGET}; nothing to back up." + fi +fi + +# Step 2: Replace moc with newly built one +echo "Installing new moc to ${TARGET}" +cp -f "${SRC}" "${TARGET}" +chmod +x "${TARGET}" + +echo "Installed. Version:" +"${TARGET}" --version || true + + From 552f8344783ec7930dda102221da3ad450307014 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Tue, 16 Sep 2025 13:02:43 +0200 Subject: [PATCH 15/22] fix draft tag to match the version + suffix --- .github/workflows/release.yml | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ddbd8ed0d53..a9d124b7c05 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,12 +6,12 @@ on: - "*" workflow_dispatch: # To test this workflow: Go to Actions -> release -> Run workflow - # Or using the CLI: gh workflow run release --ref -f version=test-draft-release + # Or using the CLI: gh workflow run release --ref -f version_suffix=test-draft-release # This creates a draft release tagged with the specified version # Remember to delete the draft release after testing! inputs: - version: - description: "Version for draft release (default: test-draft-release)" + version_suffix: + description: "Suffix for draft release tag (e.g., experimental-foo-2)" required: false default: test-draft-release type: string @@ -19,24 +19,22 @@ on: jobs: prepare: runs-on: ubuntu-latest - outputs: - version: ${{ inputs.version || github.ref_name }} steps: - name: Prepare release - run: echo "Preparing release for version ${{ inputs.version || github.ref_name }}" + run: echo "Preparing release ref=${{ github.ref_name }} suffix=${{ inputs.version_suffix }}" - name: Validate draft suffix (workflow_dispatch only) if: ${{ github.event_name == 'workflow_dispatch' }} run: | set -eu - SUFFIX="${{ inputs.version }}" + SUFFIX="${{ inputs.version_suffix }}" if [ -z "${SUFFIX:-}" ]; then - echo "Error: inputs.version (draft suffix) is empty" + echo "Error: inputs.version_suffix (draft suffix) is empty" exit 1 fi # Allow only letters, digits, and hyphens if ! printf '%s' "${SUFFIX}" | grep -Eq '^[A-Za-z0-9-]+$'; then - echo "Error: inputs.version must contain only letters, digits, and hyphens (e.g., experimental-foo-2)" + echo "Error: inputs.version_suffix must contain only letters, digits, and hyphens (e.g., experimental-foo-2)" exit 1 fi @@ -52,7 +50,7 @@ jobs: id: read_changelog uses: ./.github/actions/extract-changelog with: - version: ${{ needs.prepare.outputs.version }} + version: ${{ github.ref_name }} outputs: release_body: ${{ steps.read_changelog.outputs.release_body }} @@ -62,7 +60,7 @@ jobs: matrix: os: [ubuntu-latest, macos-13, ubuntu-24.04-arm, macos-latest] concurrency: - group: release-build-${{ matrix.os }}-${{ needs.prepare.outputs.version }} + group: release-build-${{ matrix.os }}-${{ github.ref_name }} cancel-in-progress: true runs-on: ${{ matrix.os }} steps: @@ -102,9 +100,10 @@ jobs: merge-multiple: true - name: Rewrite artifact filenames with draft suffix + id: rewrite_draft_assets if: ${{ github.event_name == 'workflow_dispatch' }} env: - DRAFT_SUFFIX: ${{ inputs.version }} + DRAFT_SUFFIX: ${{ inputs.version_suffix }} run: | set -eu echo "Applying draft suffix: ${DRAFT_SUFFIX}" @@ -128,6 +127,8 @@ jobs: [ -e "$f" ] || continue mv "$f" "${f%.tar.gz}-${DRAFT_SUFFIX}.tar.gz" done + # Expose computed draft tag as a step output + echo "tag=${version}-${DRAFT_SUFFIX}" >> "$GITHUB_OUTPUT" - name: List downloaded files run: | @@ -138,7 +139,7 @@ jobs: uses: svenstaro/upload-release-action@v2 with: repo_token: ${{ secrets.GITHUB_TOKEN }} - tag: ${{ needs.prepare.outputs.version }} + tag: ${{ github.event_name == 'workflow_dispatch' && steps.rewrite_draft_assets.outputs.tag || github.ref_name }} file: release-assets/* file_glob: true body: ${{ needs.changelog.outputs.release_body || 'Draft release created for testing purposes' }} From c4d9368a915c5a5538862db7fb9659cd48ec976d Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Tue, 16 Sep 2025 14:03:02 +0200 Subject: [PATCH 16/22] refactor --- src/mo_frontend/typing.ml | 5 ----- src/mo_types/type.ml | 45 ++++++++++++++++++--------------------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 1665656fe73..294921e9934 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1697,10 +1697,6 @@ and infer_exp'' env exp : T.typ = | _ -> () end; let sort, ve = check_shared_pat env shared_pat in - (* let sort = match sort, !Mo_config.Flags.enhanced_orthogonal_persistence with - | T.Local T.Stable, false -> T.Local T.Flexible (* named local functions are flexible in classical mode *) - | _ -> sort - in *) let is_async = match typ_opt with | Some { it = AsyncT _; _ } -> true | _ -> false @@ -1769,7 +1765,6 @@ and infer_exp'' env exp : T.typ = end end; let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in - (* let sort = if is_flexible && sort = T.Local T.Stable then T.Local T.Flexible else sort in *) T.Func (sort, c, T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | CallE (par_opt, exp1, inst, exp2) -> let t = infer_call env exp1 inst exp2 exp.at None in diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 1c691ab50d2..ac53e517ce8 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1592,21 +1592,22 @@ let rec combine rel lubs glbs t1 t2 = | Obj (s1, tf1), Obj (s2, tf2) when s1 = s2 -> (try Obj (s1, combine_fields rel lubs glbs tf1 tf2) with Mismatch -> assert (rel == glbs); Non) - | Func (s1, c1, bs1, ts11, ts12), Func (s2, c2, bs2, ts21, ts22) when - combine_sort rel lubs glbs s1 s2 bs1 bs2 <> None && - c1 = c2 && eq_binds bs1 bs2 && - List.(length ts11 = length ts21 && length ts12 = length ts22) -> - let ts = open_binds bs1 in - let cs = List.map (fun t -> fst (as_con t)) ts in - let opened = List.map (open_ ts) in - let closed = List.map (close cs) in - let rel' = if rel == lubs then glbs else lubs in - let s = Option.get (combine_sort rel lubs glbs s1 s2 bs1 bs2) in - Func ( - s, c1, bs1, - closed (List.map2 (combine rel' lubs glbs) (opened ts11) (opened ts21)), - closed (List.map2 (combine rel lubs glbs) (opened ts12) (opened ts22)) - ) + | Func (s1, c1, bs1, ts11, ts12), Func (s2, c2, bs2, ts21, ts22) -> + begin match combine_sort rel lubs glbs s1 s2 bs1 bs2 with + | Some s when c1 = c2 && eq_binds bs1 bs2 && + List.(length ts11 = length ts21 && length ts12 = length ts22) -> + let ts = open_binds bs1 in + let cs = List.map (fun t -> fst (as_con t)) ts in + let opened = List.map (open_ ts) in + let closed = List.map (close cs) in + let rel' = if rel == lubs then glbs else lubs in + Func ( + s, c1, bs1, + closed (List.map2 (combine rel' lubs glbs) (opened ts11) (opened ts21)), + closed (List.map2 (combine rel lubs glbs) (opened ts12) (opened ts22)) + ) + | _ -> if rel == lubs then Any else Non + end | Async (s1, t11, t12), Async (s2, t21, t22) when s1 == s2 && eq t11 t21 -> Async (s1, t11, combine rel lubs glbs t12 t22) | Con _, _ @@ -1649,16 +1650,12 @@ let rec combine rel lubs glbs t1 t2 = | _, _ -> if rel == lubs then Any else Non -and combine_sort rel lubs glbs s1 s2 bs1 bs2= +and combine_sort rel lubs glbs s1 s2 bs1 bs2 = if s1 = s2 then Some s1 else - let both s = - if rel_sort s1 s bs1 && rel_sort s2 s bs2 then Some s - else None - in - if rel == lubs then - both (Local Flexible) - else - both (Local Stable) + if rel == glbs then None else + let s = Local Flexible in + if rel_sort s1 s bs1 && rel_sort s2 s bs2 then Some s + else None and cons_if b x xs = if b then x::xs else xs From 76c62d280ce7028981c5070ab327e1b06cb1a089 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Tue, 16 Sep 2025 14:05:44 +0200 Subject: [PATCH 17/22] restore motoko-core branch --- flake.lock | 7 +++---- flake.nix | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index c6b156a6d51..d39bb2b6898 100644 --- a/flake.lock +++ b/flake.lock @@ -137,16 +137,15 @@ "motoko-core-src": { "flake": false, "locked": { - "lastModified": 1757337895, - "narHash": "sha256-G5BlQfm/TJ0Trk5owOGDOTxoigcf5ErgnSEDyPe20fk=", + "lastModified": 1756913868, + "narHash": "sha256-zLJShje+X/+4yM0wTwNB9Bri00SH6G3vOvyUP56KdwU=", "owner": "dfinity", "repo": "motoko-core", - "rev": "59310bfed843c072882ad48980a366fb87f19f03", + "rev": "e397d7e577491703d94a1f82dc88ff01c59c0dbd", "type": "github" }, "original": { "owner": "dfinity", - "ref": "luc/oo-data-structures", "repo": "motoko-core", "type": "github" } diff --git a/flake.nix b/flake.nix index 67843862985..0489f9d7e63 100644 --- a/flake.nix +++ b/flake.nix @@ -46,7 +46,7 @@ flake = false; }; motoko-core-src = { - url = "github:dfinity/motoko-core/luc/oo-data-structures"; + url = "github:dfinity/motoko-core"; flake = false; }; motoko-matchers-src = { From 11340ce82f77096efa5f5e01561e1c713d8eaf82 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Tue, 16 Sep 2025 14:09:54 +0200 Subject: [PATCH 18/22] tmp disable macos-13 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a9d124b7c05..8906f3afa93 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -58,7 +58,7 @@ jobs: needs: prepare strategy: matrix: - os: [ubuntu-latest, macos-13, ubuntu-24.04-arm, macos-latest] + os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest] concurrency: group: release-build-${{ matrix.os }}-${{ github.ref_name }} cancel-in-progress: true From 62131d6c4dc03790c1de280adca68b13cf5ec16c Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Tue, 16 Sep 2025 15:48:55 +0200 Subject: [PATCH 19/22] rel_func_sort ~eq and sub_func_sort --- src/mo_frontend/bi_match.ml | 2 +- src/mo_types/type.ml | 13 ++++++++----- src/mo_types/type.mli | 4 +++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index 60f2bc6a0a4..bff5f308910 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -261,7 +261,7 @@ let bi_match_typs ctx = | Tup ts1, Tup ts2 -> bi_match_list bi_match_typ rel eq inst any ts1 ts2 | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> - if rel_sort s1 s2 tbs1 && c1 = c2 then + if rel_func_sort ~eq:(rel == eq) s1 s2 tbs1 && c1 = c2 then (match bi_match_binds rel eq inst any tbs1 tbs2 with | Some (inst, ts) -> let any' = List.fold_right diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index ac53e517ce8..895ac9011d8 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1223,7 +1223,7 @@ let rec rel_typ d rel eq t1 t2 = | Tup ts1, Tup ts2 -> rel_list "tuple arguments" d rel_typ rel eq ts1 ts2 | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> - (rel_sort s1 s2 tbs1 || incompatible_func_sorts d t1 t2) && + (rel_func_sort ~eq:(rel == eq) s1 s2 tbs1 || incompatible_func_sorts d t1 t2) && (c1 = c2 || incompatible_bounds d t1 t2) && (match rel_binds d eq eq tbs1 tbs2 with | Some ts -> @@ -1238,7 +1238,10 @@ let rec rel_typ d rel eq t1 t2 = | _, _ -> incompatible_types d t1 t2 end -and rel_sort s1 s2 tbs1 = +and rel_func_sort ~eq s1 s2 tbs1 = + if eq then s1 = s2 else sub_func_sort s1 s2 tbs1 + +and sub_func_sort s1 s2 tbs1 = match s1, s2 with | Local Stable, Local Flexible -> not (List.exists (fun b -> b.sort = Type) tbs1) @@ -1593,7 +1596,7 @@ let rec combine rel lubs glbs t1 t2 = (try Obj (s1, combine_fields rel lubs glbs tf1 tf2) with Mismatch -> assert (rel == glbs); Non) | Func (s1, c1, bs1, ts11, ts12), Func (s2, c2, bs2, ts21, ts22) -> - begin match combine_sort rel lubs glbs s1 s2 bs1 bs2 with + begin match combine_func_sort rel lubs glbs s1 s2 bs1 bs2 with | Some s when c1 = c2 && eq_binds bs1 bs2 && List.(length ts11 = length ts21 && length ts12 = length ts22) -> let ts = open_binds bs1 in @@ -1650,11 +1653,11 @@ let rec combine rel lubs glbs t1 t2 = | _, _ -> if rel == lubs then Any else Non -and combine_sort rel lubs glbs s1 s2 bs1 bs2 = +and combine_func_sort rel lubs glbs s1 s2 bs1 bs2 = if s1 = s2 then Some s1 else if rel == glbs then None else let s = Local Flexible in - if rel_sort s1 s bs1 && rel_sort s2 s bs2 then Some s + if sub_func_sort s1 s bs1 && sub_func_sort s2 s bs2 then Some s else None and cons_if b x xs = if b then x::xs else xs diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index ca420945b4b..d7210c8090d 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -276,7 +276,9 @@ val eq_kind : ?src_fields : Field_sources.t -> kind -> kind -> bool val sub : ?src_fields : Field_sources.t -> typ -> typ -> bool val sub_explained : ?src_fields : Field_sources.t -> context -> typ -> typ -> compatibility val compatible : typ -> typ -> bool -val rel_sort : func_sort -> func_sort -> bind list -> bool + +val rel_func_sort : eq:bool -> func_sort -> func_sort -> bind list -> bool +val sub_func_sort : func_sort -> func_sort -> bind list -> bool exception PreEncountered val lub : ?src_fields : Field_sources.t -> typ -> typ -> typ From 5028f5ada79466fe1e18d67a81813801843f681a Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Wed, 17 Sep 2025 10:10:43 +0200 Subject: [PATCH 20/22] remove done todo --- test/fail/persistent-func-type-argument-and-return.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fail/persistent-func-type-argument-and-return.mo b/test/fail/persistent-func-type-argument-and-return.mo index e0038ac4edd..64deced5329 100644 --- a/test/fail/persistent-func-type-argument-and-return.mo +++ b/test/fail/persistent-func-type-argument-and-return.mo @@ -1,7 +1,7 @@ module { persistent func g(x : T) : persistent() -> T { persistent func h() : T { x }; - h; // TODO: non-eop should still typecheck here + h; }; // don't allow `func() {}` to typecheck as `persistent() -> ()` for now let h = g ()>(func() {}); From b31e1a43b16c56d251e2ebd58fc30f9cfd315277 Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Wed, 17 Sep 2025 10:12:38 +0200 Subject: [PATCH 21/22] revert #5491, cleaunp --- .github/workflows/release.yml | 158 +++++++----------- scripts/replace-mops-moc | 69 -------- ...-funcs-in-type-args-and-return.drun-run.ok | 2 - 3 files changed, 57 insertions(+), 172 deletions(-) delete mode 100755 scripts/replace-mops-moc delete mode 100644 test/run-drun/ok/persistent-actor-with-persistent-funcs-in-type-args-and-return.drun-run.ok diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8906f3afa93..ad56b69f5cf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,15 +3,15 @@ name: release on: push: tags: - - "*" + - '*' workflow_dispatch: # To test this workflow: Go to Actions -> release -> Run workflow - # Or using the CLI: gh workflow run release --ref -f version_suffix=test-draft-release + # Or using the CLI: gh workflow run release --ref -f version=test-draft-release # This creates a draft release tagged with the specified version # Remember to delete the draft release after testing! inputs: - version_suffix: - description: "Suffix for draft release tag (e.g., experimental-foo-2)" + version: + description: 'Version for draft release (default: test-draft-release)' required: false default: test-draft-release type: string @@ -19,38 +19,25 @@ on: jobs: prepare: runs-on: ubuntu-latest + outputs: + version: ${{ inputs.version || github.ref_name }} steps: - name: Prepare release - run: echo "Preparing release ref=${{ github.ref_name }} suffix=${{ inputs.version_suffix }}" - - - name: Validate draft suffix (workflow_dispatch only) - if: ${{ github.event_name == 'workflow_dispatch' }} - run: | - set -eu - SUFFIX="${{ inputs.version_suffix }}" - if [ -z "${SUFFIX:-}" ]; then - echo "Error: inputs.version_suffix (draft suffix) is empty" - exit 1 - fi - # Allow only letters, digits, and hyphens - if ! printf '%s' "${SUFFIX}" | grep -Eq '^[A-Za-z0-9-]+$'; then - echo "Error: inputs.version_suffix must contain only letters, digits, and hyphens (e.g., experimental-foo-2)" - exit 1 - fi + run: echo "Preparing release for version ${{ inputs.version || github.ref_name }}" # Check that the changelog is in good order and extract the changelog. changelog: runs-on: ubuntu-latest needs: prepare steps: - - uses: actions/checkout@v5 - - name: Extract changelog - # Skip this step for draft releases. Leave the release body empty. - if: ${{ github.event_name != 'workflow_dispatch' }} - id: read_changelog - uses: ./.github/actions/extract-changelog - with: - version: ${{ github.ref_name }} + - uses: actions/checkout@v5 + - name: Extract changelog + # Skip this step for draft releases. Leave the release body empty. + if: ${{ github.event_name != 'workflow_dispatch' }} + id: read_changelog + uses: ./.github/actions/extract-changelog + with: + version: ${{ needs.prepare.outputs.version }} outputs: release_body: ${{ steps.read_changelog.outputs.release_body }} @@ -58,90 +45,59 @@ jobs: needs: prepare strategy: matrix: - os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest] + os: [ ubuntu-latest, macos-13, ubuntu-24.04-arm, macos-latest ] concurrency: - group: release-build-${{ matrix.os }}-${{ github.ref_name }} + group: release-build-${{ matrix.os }}-${{ needs.prepare.outputs.version }} cancel-in-progress: true runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v5 - - uses: cachix/install-nix-action@v31 - - uses: cachix/cachix-action@v16 - with: - name: ic-hs-test - # NB: No auth token, we don't expect to push new stuff here + - uses: actions/checkout@v5 + - uses: cachix/install-nix-action@v31 + - uses: cachix/cachix-action@v16 + with: + name: ic-hs-test + # NB: No auth token, we don't expect to push new stuff here - - name: Build platform-specific release files - run: nix build --max-jobs 1 '.#"release-files-${{ matrix.os }}"' + - name: Build platform-specific release files + run: nix build --max-jobs 1 '.#"release-files-${{ matrix.os }}"' - - name: Upload Release Artifacts - uses: actions/upload-artifact@v4 - with: - name: release-files-${{ matrix.os }} - path: result/* + - name: Upload Release Artifacts + uses: actions/upload-artifact@v4 + with: + name: release-files-${{ matrix.os }} + path: result/* - - name: Test release files - run: | - uname -s -m - moc="$(nix build --max-jobs 1 .#release.moc --print-out-paths)" - "$moc/bin/moc" --version - file "$moc/bin/moc" - ldd "$moc/bin/moc" || true + - name: Test release files + run: | + uname -s -m + moc="$(nix build --max-jobs 1 .#release.moc --print-out-paths)" + "$moc/bin/moc" --version + file "$moc/bin/moc" + ldd "$moc/bin/moc" || true publish: runs-on: ubuntu-latest needs: [prepare, changelog, build] steps: - - name: Download all release artifacts - uses: actions/download-artifact@v5 - with: - path: release-assets - pattern: release-files-* - merge-multiple: true - - - name: Rewrite artifact filenames with draft suffix - id: rewrite_draft_assets - if: ${{ github.event_name == 'workflow_dispatch' }} - env: - DRAFT_SUFFIX: ${{ inputs.version_suffix }} - run: | - set -eu - echo "Applying draft suffix: ${DRAFT_SUFFIX}" - dir="release-assets" - # Extract numeric version from moc-.js - version="$(ls "$dir"/moc-*.js 2>/dev/null | sed -n 's#.*moc-\([0-9.]\+\)\.js#\1#p' | head -n1 || true)" - if [ -z "${version}" ]; then - echo "Could not determine base version from moc-*.js; skipping rename." - exit 0 - fi - echo "Detected base version: ${version}" - # Rename JS artifacts - if [ -f "$dir/moc-${version}.js" ]; then - mv "$dir/moc-${version}.js" "$dir/moc-${version}-${DRAFT_SUFFIX}.js" - fi - if [ -f "$dir/moc-interpreter-${version}.js" ]; then - mv "$dir/moc-interpreter-${version}.js" "$dir/moc-interpreter-${version}-${DRAFT_SUFFIX}.js" - fi - # Rename tarballs - for f in "$dir"/*-"${version}".tar.gz; do - [ -e "$f" ] || continue - mv "$f" "${f%.tar.gz}-${DRAFT_SUFFIX}.tar.gz" - done - # Expose computed draft tag as a step output - echo "tag=${version}-${DRAFT_SUFFIX}" >> "$GITHUB_OUTPUT" + - name: Download all release artifacts + uses: actions/download-artifact@v5 + with: + path: release-assets + pattern: release-files-* + merge-multiple: true - - name: List downloaded files - run: | - echo "Contents of release-assets directory:" - find release-assets -type f -ls || true + - name: List downloaded files + run: | + echo "Contents of release-assets directory:" + find release-assets -type f -ls || true - - name: Upload Release Assets - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - tag: ${{ github.event_name == 'workflow_dispatch' && steps.rewrite_draft_assets.outputs.tag || github.ref_name }} - file: release-assets/* - file_glob: true - body: ${{ needs.changelog.outputs.release_body || 'Draft release created for testing purposes' }} - draft: ${{ github.event_name == 'workflow_dispatch' }} - prerelease: ${{ github.event_name == 'workflow_dispatch' }} + - name: Upload Release Assets + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ needs.prepare.outputs.version }} + file: release-assets/* + file_glob: true + body: ${{ needs.changelog.outputs.release_body || 'Draft release created for testing purposes' }} + draft: ${{ github.event_name == 'workflow_dispatch' }} + prerelease: ${{ github.event_name == 'workflow_dispatch' }} diff --git a/scripts/replace-mops-moc b/scripts/replace-mops-moc deleted file mode 100755 index af2ab71cbd4..00000000000 --- a/scripts/replace-mops-moc +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env bash -# replace-mops-moc: Build moc via Nix and replace a mops-cached moc binary. -# Usage: ./replace-mops-moc [restore] -# - Without 'restore': builds .#release.moc, backs up existing 'moc' once as 'moc-backup' if absent, -# then installs the newly built 'moc' into the target version directory. -# - With 'restore': moves 'moc-backup' back to 'moc' (overwriting current), then prints version. -set -euo pipefail - -if [ "${1:-}" = "" ]; then - echo "Usage: $0 [restore]" >&2 - echo "Example replace: $0 0.16.1" >&2 - echo "Example restore: $0 0.16.1 restore" >&2 - exit 2 -fi - -VERSION_DIR="$1" -TARGET_DIR="${HOME}/Library/Caches/mops/moc/${VERSION_DIR}" -TARGET="${TARGET_DIR}/moc" -BACKUP="${TARGET}-backup" -MODE="${2:-}" - -# Do not create directories; assume they exist as requested. -if [ ! -d "${TARGET_DIR}" ]; then - echo "Error: Target directory does not exist: ${TARGET_DIR}" >&2 - exit 1 -fi - -if [ "${MODE}" = "restore" ]; then - echo "Restoring backup for ${TARGET}" - if [ ! -f "${BACKUP}" ]; then - echo "Error: No backup found at ${BACKUP}" >&2 - exit 1 - fi - mv -f "${BACKUP}" "${TARGET}" - chmod +x "${TARGET}" || true - echo "Restored. Version:" - "${TARGET}" --version || true - exit 0 -fi - -echo "Building moc via Nix (.#release.moc)..." -OUT_PATH="$(nix build --max-jobs 1 .#release.moc --print-out-paths)" -SRC="${OUT_PATH}/bin/moc" - -echo "Using built moc at: ${SRC}" -echo "Target directory: ${TARGET_DIR}" -echo "Target binary: ${TARGET}" - -# Step 1: Backup existing moc if no backup exists yet -if [ -f "${BACKUP}" ]; then - echo "Backup already exists at ${BACKUP}; skipping backup." -else - if [ -f "${TARGET}" ]; then - echo "Creating backup at ${BACKUP}" - mv "${TARGET}" "${BACKUP}" - else - echo "No existing moc found at ${TARGET}; nothing to back up." - fi -fi - -# Step 2: Replace moc with newly built one -echo "Installing new moc to ${TARGET}" -cp -f "${SRC}" "${TARGET}" -chmod +x "${TARGET}" - -echo "Installed. Version:" -"${TARGET}" --version || true - - diff --git a/test/run-drun/ok/persistent-actor-with-persistent-funcs-in-type-args-and-return.drun-run.ok b/test/run-drun/ok/persistent-actor-with-persistent-funcs-in-type-args-and-return.drun-run.ok deleted file mode 100644 index a6f776f43c6..00000000000 --- a/test/run-drun/ok/persistent-actor-with-persistent-funcs-in-type-args-and-return.drun-run.ok +++ /dev/null @@ -1,2 +0,0 @@ -ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 -ingress Completed: Reply: 0x4449444c0000 From 636b15a44cd89072ce0d36a0e263d5d623e4d45d Mon Sep 17 00:00:00 2001 From: Kamil Listopad Date: Wed, 17 Sep 2025 10:25:35 +0200 Subject: [PATCH 22/22] damn you run.sh and your extra moc args... --- ...or-with-persistent-funcs-in-type-args-and-return.drun-run.ok | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 test/run-drun/ok/persistent-actor-with-persistent-funcs-in-type-args-and-return.drun-run.ok diff --git a/test/run-drun/ok/persistent-actor-with-persistent-funcs-in-type-args-and-return.drun-run.ok b/test/run-drun/ok/persistent-actor-with-persistent-funcs-in-type-args-and-return.drun-run.ok new file mode 100644 index 00000000000..a6f776f43c6 --- /dev/null +++ b/test/run-drun/ok/persistent-actor-with-persistent-funcs-in-type-args-and-return.drun-run.ok @@ -0,0 +1,2 @@ +ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 +ingress Completed: Reply: 0x4449444c0000