From d80c9150ab611adaec20b61191f1ff486d165c1f Mon Sep 17 00:00:00 2001 From: Akosh Farkash Date: Thu, 16 Apr 2026 13:41:19 +0100 Subject: [PATCH 1/3] Update Noir dependency to 1.0.0-beta.20 --- .github/workflows/ci-noir.yaml | 4 +- Cargo.lock | 386 ++++++++++++++--------------- Cargo.toml | 12 +- src/lean/builtin.rs | 40 +-- src/lean/generator.rs | 434 +++++++++++++-------------------- 5 files changed, 376 insertions(+), 500 deletions(-) diff --git a/.github/workflows/ci-noir.yaml b/.github/workflows/ci-noir.yaml index 51693d23..ba0236f5 100644 --- a/.github/workflows/ci-noir.yaml +++ b/.github/workflows/ci-noir.yaml @@ -13,7 +13,7 @@ jobs: uses: ./.github/workflows/build-ci-image.yaml with: allow_push: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} - + run-tests: name: Test Noir needs: build-ci-image @@ -28,7 +28,7 @@ jobs: uses: actions/checkout@v6 with: repository: noir-lang/noir - ref: 74d6be658e1ad252f87943292ba09bdd4da80bd4 + ref: b4236c1957d0c26cb65d82adc9e5447b6ff1d629 path: noir - name: Ensure Test Programs Up To Date working-directory: noir/test_programs diff --git a/Cargo.lock b/Cargo.lock index ec99040e..f5674139 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,8 +4,8 @@ version = 4 [[package]] name = "acir" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acir_field", "base64", @@ -20,17 +20,16 @@ dependencies = [ "serde-big-array", "strum", "strum_macros", - "thiserror 1.0.69", + "thiserror", ] [[package]] name = "acir_field" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "ark-bn254", "ark-ff", - "ark-std", "cfg-if", "hex", "num-bigint", @@ -39,23 +38,24 @@ dependencies = [ [[package]] name = "acvm" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acir", "acvm_blackbox_solver", "brillig_vm", - "indexmap 2.13.0", + "indexmap 2.14.0", + "itertools 0.14.0", "rustc-hash", "serde", - "thiserror 1.0.69", + "thiserror", "tracing", ] [[package]] name = "acvm_blackbox_solver" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acir", "aes", @@ -67,7 +67,7 @@ dependencies = [ "log", "p256", "sha2 0.11.0-rc.5", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -116,9 +116,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -137,9 +137,9 @@ checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -353,12 +353,6 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" -[[package]] -name = "binary-merge" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597bb81c80a54b6a4381b23faba8d7774b144c94cbd1d6fe3f1329bd776554ab" - [[package]] name = "bit-set" version = "0.8.0" @@ -441,8 +435,8 @@ dependencies = [ [[package]] name = "bn254_blackbox_solver" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acir", "acvm_blackbox_solver", @@ -451,6 +445,7 @@ dependencies = [ "ark-ff", "ark-grumpkin", "hex", + "itertools 0.14.0", ] [[package]] @@ -464,23 +459,25 @@ dependencies = [ [[package]] name = "brillig" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acir_field", + "itertools 0.14.0", "serde", ] [[package]] name = "brillig_vm" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acir", "acvm_blackbox_solver", + "itertools 0.14.0", "num-bigint", "num-traits", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -536,6 +533,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.0", +] + [[package]] name = "chrono" version = "0.4.44" @@ -562,9 +570,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.60" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -572,9 +580,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.60" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -584,11 +592,11 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.117", @@ -608,11 +616,11 @@ checksum = "de0758edba32d61d1fd9f4d69491b47604b91ee2f7e6b33de7e54ca4ebe55dc3" [[package]] name = "codespan" -version = "0.11.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3362992a0d9f1dd7c3d0e89e0ab2bb540b7a95fea8cd798090e758fda2899b5e" +checksum = "583f52b0658b321b25fd6b209b6c76cf058f433071297de64e5980c3d9aad937" dependencies = [ - "codespan-reporting", + "codespan-reporting 0.13.1", "serde", ] @@ -621,6 +629,16 @@ name = "codespan-reporting" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" dependencies = [ "serde", "termcolor", @@ -1013,11 +1031,12 @@ dependencies = [ [[package]] name = "fm" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ - "codespan-reporting", + "codespan-reporting 0.11.1", "iter-extended", + "itertools 0.14.0", "serde", ] @@ -1148,15 +1167,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "heck" @@ -1366,12 +1379,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -1386,15 +1399,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "inplace-vec-builder" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf64c2edc8226891a71f127587a2861b132d2b942310843814d5001d99a1d307" -dependencies = [ - "smallvec", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -1403,8 +1407,8 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "iter-extended" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" [[package]] name = "itertools" @@ -1442,18 +1446,18 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fba77a59c4c644fd48732367624d1bcf6f409f9c9a286fbc71d2f1fc0b2ea16" +checksum = "3f3f48dc3e6b8bd21e15436c1ddd0bc22a6a54e8ec46fedd6adf3425f396ec6a" dependencies = [ "jsonrpsee-core", ] [[package]] name = "jsonrpsee-core" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693c93cbb7db25f4108ed121304b671a36002c2db67dff2ee4391a688c738547" +checksum = "316c96719901f05d1137f19ba598b5fe9c9bc39f4335f67f6be8613921946480" dependencies = [ "async-trait", "futures-util", @@ -1462,7 +1466,7 @@ dependencies = [ "pin-project", "serde", "serde_json", - "thiserror 2.0.18", + "thiserror", "tokio", "tower", "tracing", @@ -1470,14 +1474,14 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66df7256371c45621b3b7d2fb23aea923d577616b9c0e9c0b950a6ea5c2be0ca" +checksum = "bc88ff4688e43cc3fa9883a8a95c6fa27aa2e76c96e610b737b6554d650d7fd5" dependencies = [ "http", "serde", "serde_json", - "thiserror 2.0.18", + "thiserror", ] [[package]] @@ -1495,10 +1499,11 @@ dependencies = [ [[package]] name = "keccak" -version = "0.2.0-rc.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882b69cb15b1f78b51342322a97ccd16f5123d1dc8a3da981a95244f488e8692" +checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" dependencies = [ + "cfg-if", "cpufeatures 0.3.0", ] @@ -1519,17 +1524,11 @@ dependencies = [ "petgraph", "serde", "tempfile", - "thiserror 2.0.18", + "thiserror", "toml 0.9.12+spec-1.1.0", "walkdir", ] -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "leb128fmt" version = "0.1.0" @@ -1587,8 +1586,8 @@ dependencies = [ [[package]] name = "nargo" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acvm", "brillig", @@ -1606,15 +1605,15 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror 1.0.69", + "thiserror", "tracing", "walkdir", ] [[package]] name = "nargo_toml" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "dirs", "fm", @@ -1624,26 +1623,27 @@ dependencies = [ "noirc_frontend", "semver", "serde", - "thiserror 1.0.69", - "toml 0.7.8", + "thiserror", + "toml 0.8.23", "tracing", "url", ] [[package]] name = "noir_greybox_fuzzer" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acvm", "build-data", "fm", + "itertools 0.14.0", "noirc_abi", "noirc_artifacts", "num-traits", "proptest", - "rand 0.9.2", - "rand_xorshift", + "rand 0.10.1", + "rand_xorshift 0.5.0", "rayon", "sha256", "termcolor", @@ -1652,34 +1652,35 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acvm", "iter-extended", + "itertools 0.14.0", "noirc_printable_type", "num-bigint", "num-traits", "serde", "serde_json", - "thiserror 1.0.69", - "toml 0.7.8", + "thiserror", + "toml 0.8.23", ] [[package]] name = "noirc_arena" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" [[package]] name = "noirc_artifacts" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acir", "acvm", "base64", - "codespan-reporting", + "codespan-reporting 0.11.1", "flate2", "fm", "noirc_abi", @@ -1687,14 +1688,14 @@ dependencies = [ "noirc_printable_type", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror", "tracing", ] [[package]] name = "noirc_driver" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acvm", "build-data", @@ -1713,20 +1714,21 @@ dependencies = [ [[package]] name = "noirc_errors" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ - "codespan-reporting", + "codespan-reporting 0.11.1", "fm", "noirc_span", + "rangemap", "rustc-hash", "serde", ] [[package]] name = "noirc_evaluator" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -1734,8 +1736,9 @@ dependencies = [ "chrono", "fm", "im", - "indexmap 2.13.0", + "indexmap 2.14.0", "iter-extended", + "itertools 0.14.0", "noirc_artifacts", "noirc_errors", "noirc_frontend", @@ -1751,15 +1754,14 @@ dependencies = [ "serde_json", "serde_with", "smallvec", - "thiserror 1.0.69", + "thiserror", "tracing", - "vec-collections", ] [[package]] name = "noirc_frontend" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -1767,6 +1769,7 @@ dependencies = [ "fm", "im", "iter-extended", + "itertools 0.14.0", "noirc_arena", "noirc_artifacts", "noirc_errors", @@ -1782,25 +1785,26 @@ dependencies = [ "smol_str", "strum", "strum_macros", - "thiserror 1.0.69", + "thiserror", "tracing", ] [[package]] name = "noirc_printable_type" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "acvm", "iter-extended", + "itertools 0.14.0", "serde", "serde_json", ] [[package]] name = "noirc_span" -version = "1.0.0-beta.19" -source = "git+https://github.com/noir-lang/noir?rev=74d6be658e1ad252f87943292ba09bdd4da80bd4#74d6be658e1ad252f87943292ba09bdd4da80bd4" +version = "1.0.0-beta.20" +source = "git+https://github.com/noir-lang/noir?rev=b4236c1957d0c26cb65d82adc9e5447b6ff1d629#b4236c1957d0c26cb65d82adc9e5447b6ff1d629" dependencies = [ "codespan", "serde", @@ -1922,7 +1926,7 @@ checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset", "hashbrown 0.15.5", - "indexmap 2.13.0", + "indexmap 2.14.0", "serde", ] @@ -2039,9 +2043,9 @@ dependencies = [ [[package]] name = "proptest" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37566cb3fdacef14c0737f9546df7cfeadbfbc9fef10991038bf5015d0c80532" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ "bit-set", "bit-vec", @@ -2049,7 +2053,7 @@ dependencies = [ "num-traits", "rand 0.9.2", "rand_chacha 0.9.0", - "rand_xorshift", + "rand_xorshift 0.4.0", "regex-syntax", "unarray", ] @@ -2095,6 +2099,17 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.0", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -2145,6 +2160,15 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand_xorshift" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60aa6af80be32871323012e02e6e65f8a7cc7890931ae421d217ad8fe0df2ccf" +dependencies = [ + "rand_core 0.10.0", +] + [[package]] name = "rand_xoshiro" version = "0.6.0" @@ -2188,7 +2212,7 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 2.0.18", + "thiserror", ] [[package]] @@ -2512,7 +2536,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.13.0", + "indexmap 2.14.0", "schemars 0.9.0", "schemars 1.2.1", "serde_core", @@ -2633,12 +2657,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "sorted-iter" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bceb57dc07c92cdae60f5b27b3fa92ecaaa42fe36c55e22dbfb0b44893e0b1f7" - [[package]] name = "spki" version = "0.8.0-rc.4" @@ -2663,21 +2681,20 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.24.1" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" [[package]] name = "strum_macros" -version = "0.24.3" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", "quote", - "rustversion", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] @@ -2741,33 +2758,13 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - [[package]] name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.18", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "thiserror-impl", ] [[package]] @@ -2833,14 +2830,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.8" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", - "toml_edit 0.19.15", + "toml_edit 0.22.27", ] [[package]] @@ -2849,13 +2846,13 @@ version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.14.0", "serde_core", "serde_spanned 1.0.4", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 0.7.15", + "winnow", ] [[package]] @@ -2887,15 +2884,16 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.14.0", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", - "winnow 0.5.40", + "toml_write", + "winnow", ] [[package]] @@ -2904,10 +2902,10 @@ version = "0.25.4+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.14.0", "toml_datetime 1.0.0+spec-1.1.0", "toml_parser", - "winnow 0.7.15", + "winnow", ] [[package]] @@ -2916,9 +2914,15 @@ version = "1.0.9+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" dependencies = [ - "winnow 0.7.15", + "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "toml_writer" version = "1.0.6+spec-1.1.0" @@ -3038,21 +3042,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "vec-collections" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c9965c8f2ffed1dbcd16cafe18a009642f540fa22661c6cfd6309ddb02e4982" -dependencies = [ - "binary-merge", - "inplace-vec-builder", - "lazy_static", - "num-traits", - "serde", - "smallvec", - "sorted-iter", -] - [[package]] name = "version_check" version = "0.9.5" @@ -3155,7 +3144,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", - "indexmap 2.13.0", + "indexmap 2.14.0", "wasm-encoder", "wasmparser", ] @@ -3168,7 +3157,7 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags", "hashbrown 0.15.5", - "indexmap 2.13.0", + "indexmap 2.14.0", "semver", ] @@ -3271,15 +3260,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - [[package]] name = "winnow" version = "0.7.15" @@ -3305,7 +3285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" dependencies = [ "anyhow", - "heck 0.5.0", + "heck", "wit-parser", ] @@ -3316,8 +3296,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", - "heck 0.5.0", - "indexmap 2.13.0", + "heck", + "indexmap 2.14.0", "prettyplease", "syn 2.0.117", "wasm-metadata", @@ -3348,7 +3328,7 @@ checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", "bitflags", - "indexmap 2.13.0", + "indexmap 2.14.0", "log", "serde", "serde_derive", @@ -3367,7 +3347,7 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", - "indexmap 2.13.0", + "indexmap 2.14.0", "log", "semver", "serde", diff --git a/Cargo.toml b/Cargo.toml index 0e419165..d0ee7e80 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,12 +13,12 @@ license = "MIT" [dependencies] # When update noir version used in here please remember about changing the # `ci-noir` workflow and standard library to pull from the same version. -fm = { git = "https://github.com/noir-lang/noir", rev = "74d6be658e1ad252f87943292ba09bdd4da80bd4" } -nargo = { git = "https://github.com/noir-lang/noir", rev = "74d6be658e1ad252f87943292ba09bdd4da80bd4" } -nargo_toml = { git = "https://github.com/noir-lang/noir", rev = "74d6be658e1ad252f87943292ba09bdd4da80bd4" } -noirc_driver = { git = "https://github.com/noir-lang/noir", rev = "74d6be658e1ad252f87943292ba09bdd4da80bd4" } -noirc_errors = { git = "https://github.com/noir-lang/noir", rev = "74d6be658e1ad252f87943292ba09bdd4da80bd4" } -noirc_frontend = { git = "https://github.com/noir-lang/noir", rev = "74d6be658e1ad252f87943292ba09bdd4da80bd4" } +fm = { git = "https://github.com/noir-lang/noir", rev = "b4236c1957d0c26cb65d82adc9e5447b6ff1d629" } +nargo = { git = "https://github.com/noir-lang/noir", rev = "b4236c1957d0c26cb65d82adc9e5447b6ff1d629" } +nargo_toml = { git = "https://github.com/noir-lang/noir", rev = "b4236c1957d0c26cb65d82adc9e5447b6ff1d629" } +noirc_driver = { git = "https://github.com/noir-lang/noir", rev = "b4236c1957d0c26cb65d82adc9e5447b6ff1d629" } +noirc_errors = { git = "https://github.com/noir-lang/noir", rev = "b4236c1957d0c26cb65d82adc9e5447b6ff1d629" } +noirc_frontend = { git = "https://github.com/noir-lang/noir", rev = "b4236c1957d0c26cb65d82adc9e5447b6ff1d629" } # Left behind to enable easier local development when needed # fm = { path = "../noir/compiler/fm" } diff --git a/src/lean/builtin.rs b/src/lean/builtin.rs index 19a04284..252f0184 100644 --- a/src/lean/builtin.rs +++ b/src/lean/builtin.rs @@ -1,8 +1,7 @@ use noirc_frontend::{ - ast::{BinaryOpKind, IntegerBitSize, UnaryOp}, + ast::{BinaryOpKind, UnaryOp}, shared::Signedness, - Type as NoirType, - TypeBinding, + Type as NoirType, TypeBinding, }; use crate::lean::ast::{BuiltinCallRef, Call, DeclCallRef, Expression, Type}; @@ -44,8 +43,8 @@ pub fn make_ordering_const(crate_name: &str, ordering_name: &str) -> Expression Expression::Call(Call { function: Box::new(Expression::DeclCallRef(DeclCallRef { - function: format!("{crate_name}::{ordering_name}"), - generics: vec![], + function: format!("{crate_name}::{ordering_name}"), + generics: vec![], param_types: vec![], return_type: return_type.clone(), })), @@ -59,11 +58,11 @@ pub fn make_ordering_const(crate_name: &str, ordering_name: &str) -> Expression #[must_use] pub fn make_beq(left: Expression, right: Expression) -> Expression { Expression::Call(Call { - function: Box::new(Expression::BuiltinCallRef(BuiltinCallRef { - name: BEQ_NAME.to_string(), + function: Box::new(Expression::BuiltinCallRef(BuiltinCallRef { + name: BEQ_NAME.to_string(), return_type: Type::bool(), })), - params: vec![left, right], + params: vec![left, right], return_type: Type::bool(), }) } @@ -73,11 +72,11 @@ pub fn make_beq(left: Expression, right: Expression) -> Expression { #[must_use] pub fn make_bor(left: Expression, right: Expression) -> Expression { Expression::Call(Call { - function: Box::new(Expression::BuiltinCallRef(BuiltinCallRef { - name: BOR_NAME.to_string(), + function: Box::new(Expression::BuiltinCallRef(BuiltinCallRef { + name: BOR_NAME.to_string(), return_type: Type::bool(), })), - params: vec![left, right], + params: vec![left, right], return_type: Type::bool(), }) } @@ -95,17 +94,6 @@ pub enum BuiltinType { String, } -const fn integer_bit_size_to_u8(s: IntegerBitSize) -> u8 { - match s { - IntegerBitSize::One => 1, - IntegerBitSize::Eight => 8, - IntegerBitSize::Sixteen => 16, - IntegerBitSize::ThirtyTwo => 32, - IntegerBitSize::SixtyFour => 64, - IntegerBitSize::HundredTwentyEight => 128, - } -} - impl TryInto for NoirType { type Error = String; @@ -114,12 +102,8 @@ impl TryInto for NoirType { NoirType::FieldElement => Ok(BuiltinType::Field), NoirType::Bool => Ok(BuiltinType::Bool), NoirType::Unit => Ok(BuiltinType::Unit), - NoirType::Integer(Signedness::Signed, s) => { - Ok(BuiltinType::Int(integer_bit_size_to_u8(s))) - } - NoirType::Integer(Signedness::Unsigned, s) => { - Ok(BuiltinType::Uint(integer_bit_size_to_u8(s))) - } + NoirType::Integer(Signedness::Signed, s) => Ok(BuiltinType::Int(s.bit_size())), + NoirType::Integer(Signedness::Unsigned, s) => Ok(BuiltinType::Uint(s.bit_size())), NoirType::Array(..) => Ok(BuiltinType::Array), NoirType::Vector(_) => Ok(BuiltinType::Vector), NoirType::String(_) => Ok(BuiltinType::String), diff --git a/src/lean/generator.rs b/src/lean/generator.rs index f1b49005..ac806d44 100644 --- a/src/lean/generator.rs +++ b/src/lean/generator.rs @@ -15,147 +15,62 @@ use itertools::Itertools; use nargo::workspace::Workspace; use noirc_errors::Location; use noirc_frontend::{ - ast::{BinaryOpKind, FunctionKind, Ident, IntegerBitSize}, + ast::{BinaryOpKind, FunctionKind, Ident}, graph::CrateId, hir::{ + comptime::Integer as NoirInteger, def_map::{LocalModuleId, ModuleData, ModuleDefId}, type_check::generics::TraitGenerics, Context, }, hir_def::{ expr::{ - HirArrayLiteral, - HirBlockExpression, - HirCallExpression, - HirCastExpression, - HirConstrainExpression, - HirConstructorExpression, - HirExpression, - HirIdent, - HirIfExpression, - HirIndexExpression, - HirInfixExpression, - HirLambda, - HirLiteral, - HirMemberAccess, - HirPrefixExpression, + HirArrayLiteral, HirBlockExpression, HirCallExpression, HirCastExpression, + HirConstrainExpression, HirConstructorExpression, HirExpression, HirIdent, + HirIfExpression, HirIndexExpression, HirInfixExpression, HirLambda, HirLiteral, + HirMemberAccess, HirPrefixExpression, }, function::{FuncMeta, Param}, stmt::{ - HirAssignStatement, - HirForStatement, - HirLValue, - HirLetStatement, - HirPattern, + HirAssignStatement, HirForStatement, HirLValue, HirLetStatement, HirPattern, HirStatement, }, traits::{NamedType, TraitConstraint, TraitImpl}, }, node_interner::{ - DefinitionKind, - DependencyId, - ExprId, - FuncId, - GlobalId, - StmtId, - TraitId, - TraitImplId, - TypeAliasId, - TypeId, + DefinitionKind, DependencyId, ExprId, FuncId, GlobalId, StmtId, TraitId, TraitImplId, + TypeAliasId, TypeId, }, shared::Signedness, token::{FunctionAttributeKind, SecondaryAttributeKind}, - BinaryTypeOperator, - DataType, - Kind as NoirKind, - NamedGeneric, - QuotedType, - ResolvedGeneric, - Shared, - StructField, - Type as NoirType, - TypeBinding, - TypeBindings, - TypeVariable, - TypeVariableId, + BinaryTypeOperator, DataType, Kind as NoirKind, NamedGeneric, QuotedType, ResolvedGeneric, + Shared, StructField, Type as NoirType, TypeBinding, TypeBindings, TypeVariable, TypeVariableId, }; use petgraph::data::DataMap; use crate::{ constants::{ - LAMPE_STRUCT_METHOD_SEPARATOR, - NOIR_PATH_SEPARATOR, - NONE_DEPENDENCY_VERSION, - STDLIB_TOML, + LAMPE_STRUCT_METHOD_SEPARATOR, NOIR_PATH_SEPARATOR, NONE_DEPENDENCY_VERSION, STDLIB_TOML, }, file_generator::to_import_from_noir_path, lean::{ ast::{ - AssignStatement, - Block, - BuiltinCallRef, - BuiltinTag, - BuiltinTypeExpr, - Call, - Cast, - ConstGenericLiteral, - Crate, - DeclCallRef, - Deprecation, - Expression, - ForStatement, - FunctionDefinition, - GlobalCallRef, - GlobalDefinition, - IdentCallRef, - Identifier, - IfThenElse, - Kind, - LValue, - Lambda, - LetStatement, - Literal, - MemberAccess, - Module, - ModuleDefinition, - NumericLiteral, - ParamDef, - Pattern, - Statement, - StructDefinition, - StructPattern, - TraitCallRef, - TraitDefinition, - TraitImplementation, - TraitMethodDeclaration, - Type, - TypeAlias, - TypeArithOp, - TypeDefinition, - TypeExpr, - TypePattern, - WhereClause, + AssignStatement, Block, BuiltinCallRef, BuiltinTag, BuiltinTypeExpr, Call, Cast, + ConstGenericLiteral, Crate, DeclCallRef, Deprecation, Expression, ForStatement, + FunctionDefinition, GlobalCallRef, GlobalDefinition, IdentCallRef, Identifier, + IfThenElse, Kind, LValue, Lambda, LetStatement, Literal, MemberAccess, Module, + ModuleDefinition, NumericLiteral, ParamDef, Pattern, Statement, StructDefinition, + StructPattern, TraitCallRef, TraitDefinition, TraitImplementation, + TraitMethodDeclaration, Type, TypeAlias, TypeArithOp, TypeDefinition, TypeExpr, + TypePattern, WhereClause, }, builtin::{ - self, - make_bor, - make_ordering_const, - make_ordering_type, - BuiltinType, - ASSERT_BUILTIN_NAME, - MAKE_ARRAY_BUILTIN_NAME, - MAKE_EQUAL_NAME, - MAKE_GREATER_NAME, - MAKE_LESS_NAME, - MAKE_REPEATED_ARRAY_BUILTIN_NAME, - MAKE_REPEATED_SLICE_BUILTIN_NAME, - MAKE_SLICE_BUILTIN_NAME, - MAKE_STRUCT_BUILTIN_NAME, - UNIT_TYPE_NAME, + self, make_bor, make_ordering_const, make_ordering_type, BuiltinType, + ASSERT_BUILTIN_NAME, MAKE_ARRAY_BUILTIN_NAME, MAKE_EQUAL_NAME, MAKE_GREATER_NAME, + MAKE_LESS_NAME, MAKE_REPEATED_ARRAY_BUILTIN_NAME, MAKE_REPEATED_SLICE_BUILTIN_NAME, + MAKE_SLICE_BUILTIN_NAME, MAKE_STRUCT_BUILTIN_NAME, UNIT_TYPE_NAME, }, - conflicts_with_lean_keyword, - LEAN_QUOTE_END, - LEAN_QUOTE_START, + conflicts_with_lean_keyword, LEAN_QUOTE_END, LEAN_QUOTE_START, }, }; @@ -261,7 +176,7 @@ impl LeanGenerator<'_, '_, '_> { if let Some(dep_id) = g.node_weight(node_idx) { matches!( *dep_id, - DependencyId::Struct(_) | DependencyId::Alias(_) | DependencyId::Trait(_) + DependencyId::DataType(_) | DependencyId::Alias(_) | DependencyId::Trait(_) ) } else { false @@ -306,7 +221,7 @@ impl LeanGenerator<'_, '_, '_> { let def_order = dep_weights .clone() .into_iter() - .position(|item| *item == DependencyId::Struct(id)); + .position(|item| *item == DependencyId::DataType(id)); self.name_supply.reset(); let struct_def = self.generate_struct_def(id); let name = quote_lean_keywords(&struct_def.name); @@ -376,7 +291,7 @@ impl LeanGenerator<'_, '_, '_> { .collect_vec() } - /// Generates the definition of a `struct` that is describeed by the + /// Generates the definition of a `struct` that is described by the /// provided `id`. pub fn generate_struct_def(&self, id: TypeId) -> StructDefinition { let deprecation = Deprecation::from_noir( @@ -385,7 +300,7 @@ impl LeanGenerator<'_, '_, '_> { .type_attributes(&id) .iter() .find_map(|attr| match &attr.kind { - SecondaryAttributeKind::Deprecated(msg) => Some(msg.clone()), + SecondaryAttributeKind::Deprecated(_, msg) => Some(msg.clone()), _ => None, }), ); @@ -547,9 +462,13 @@ impl LeanGenerator<'_, '_, '_> { Type::immutable_reference(typ) } } - NoirType::Constant(felt, kind) => { - let felt_value = felt.to_string(); - let kind = self.expect_constant_numeric_kind(kind); + NoirType::Constant(value) => { + let felt_value = match value { + // `Integer::to_string` displays Field as hex. + NoirInteger::Field(field) => field.to_string(), + i => i.to_string(), + }; + let kind = self.expect_constant_numeric_kind(&value.numeric_kind()); Type::numeric_const(&felt_value, kind) } @@ -831,9 +750,9 @@ impl LeanGenerator<'_, '_, '_> { NoirKind::Any, ); let dummy_generic = NoirType::NamedGeneric(NamedGeneric { - type_var: dummy_tv.clone(), - name: Rc::new("LOOKUP_DUMMY".to_string()), - implicit: false, + type_var: dummy_tv.clone(), + name: Rc::new("LOOKUP_DUMMY".to_string()), + implicit: false, original_type_var_id: None, }); @@ -856,7 +775,6 @@ impl LeanGenerator<'_, '_, '_> { Box::new(NoirType::Unit), false, ), - NoirType::Integer(Signedness::Unsigned, IntegerBitSize::One), NoirType::Vector(Box::new(dummy_generic.clone())), NoirType::String(Box::new(dummy_generic.clone())), NoirType::Tuple(vec![dummy_generic; 0]), @@ -910,9 +828,9 @@ impl LeanGenerator<'_, '_, '_> { .iter() .map(|g| { NoirType::NamedGeneric(NamedGeneric { - type_var: g.type_var.clone(), - name: g.name.clone(), - implicit: false, + type_var: g.type_var.clone(), + name: g.name.clone(), + implicit: false, original_type_var_id: None, }) }) @@ -1000,7 +918,7 @@ impl LeanGenerator<'_, '_, '_> { let functions = functions.into_iter().sorted().collect_vec(); ModuleDefs { - func_defs: functions, + func_defs: functions, global_defs: globals, } } @@ -1035,7 +953,8 @@ impl LeanGenerator<'_, '_, '_> { self.context .def_interner .function_attributes(id) - .get_deprecated_note(), + .get_deprecated() + .map(|(_, msg)| msg), ); let generics = self.gather_function_generic_patterns(function_meta); @@ -1086,7 +1005,7 @@ impl LeanGenerator<'_, '_, '_> { return_type: Type, ) -> Expression { let call_identifier = Expression::BuiltinCallRef(BuiltinCallRef { - name: name.to_string(), + name: name.to_string(), return_type: return_type.clone(), }); let params = params @@ -1683,7 +1602,7 @@ impl LeanGenerator<'_, '_, '_> { let return_type = Type::tuple(&elem_types); let call_ref = Expression::BuiltinCallRef(BuiltinCallRef { - name: MAKE_STRUCT_BUILTIN_NAME.to_string(), + name: MAKE_STRUCT_BUILTIN_NAME.to_string(), return_type: return_type.clone(), }); @@ -1704,7 +1623,7 @@ impl LeanGenerator<'_, '_, '_> { let else_expr = cond.alternative.map(|e| Box::new(self.generate_expr(e))); let ite = IfThenElse { - condition: Box::new(if_cond), + condition: Box::new(if_cond), then_branch: Box::new(then_expr), else_branch: else_expr, }; @@ -1720,8 +1639,8 @@ impl LeanGenerator<'_, '_, '_> { let constraint_expr = self.generate_expr(constrain.0); let builtin_ref = Expression::builtin_call_ref(ASSERT_BUILTIN_NAME, output_type); let call = Call { - function: Box::new(builtin_ref), - params: vec![constraint_expr], + function: Box::new(builtin_ref), + params: vec![constraint_expr], return_type: output_type.clone(), }; @@ -1821,7 +1740,7 @@ impl LeanGenerator<'_, '_, '_> { let return_type = Type::data_type(&name, generic_args); let call_ref = Expression::BuiltinCallRef(BuiltinCallRef { - name: MAKE_STRUCT_BUILTIN_NAME.to_string(), + name: MAKE_STRUCT_BUILTIN_NAME.to_string(), return_type: return_type.clone(), }); @@ -1864,32 +1783,32 @@ impl LeanGenerator<'_, '_, '_> { index_expr } else { Expression::Cast(Cast { - lhs: Box::new(index_expr), + lhs: Box::new(index_expr), target: Type::integer(32, false), }) } } _ => Expression::Cast(Cast { - lhs: Box::new(index_expr), + lhs: Box::new(index_expr), target: Type::integer(32, false), }), }, _ => Expression::Cast(Cast { - lhs: Box::new(index_expr), + lhs: Box::new(index_expr), target: Type::integer(32, false), }), }, _ => panic!("Non numeric literal {lit:?} encountered as index in index expression"), }, _ => Expression::Cast(Cast { - lhs: Box::new(index_expr), + lhs: Box::new(index_expr), target: Type::integer(32, false), }), }; let call = Call { - function: Box::new(call_target), - params: vec![collection_expr, index_expr], + function: Box::new(call_target), + params: vec![collection_expr, index_expr], return_type: output_type.clone(), }; @@ -1916,8 +1835,8 @@ impl LeanGenerator<'_, '_, '_> { if let Some(builtin_name) = maybe_builtin { let builtin_target = Expression::builtin_call_ref(builtin_name.as_str(), output_type); let call = Call { - function: Box::new(builtin_target), - params: vec![lhs, rhs], + function: Box::new(builtin_target), + params: vec![lhs, rhs], return_type: output_type.clone(), }; Expression::Call(call) @@ -1972,12 +1891,12 @@ impl LeanGenerator<'_, '_, '_> { }); let negation_call_ref = Expression::BuiltinCallRef(BuiltinCallRef { - name: "bNot".to_string(), + name: "bNot".to_string(), return_type: Type::bool(), }); Expression::Call(Call { - function: Box::new(negation_call_ref), - params: vec![eq_call], + function: Box::new(negation_call_ref), + params: vec![eq_call], return_type: Type::bool(), }) } @@ -2002,11 +1921,11 @@ impl LeanGenerator<'_, '_, '_> { }); let cmp_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let cmp_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(cmp_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(cmp_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(cmp_call), }); @@ -2016,25 +1935,25 @@ impl LeanGenerator<'_, '_, '_> { ); let make_less_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_less_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(make_less_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(make_less_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(make_less_call), }); let eq_call = Expression::Call(Call { - function: Box::new(Expression::TraitCallRef(TraitCallRef { - trait_name: format!("{stdlib_name}::cmp::Eq"), - function_name: "eq".to_string(), - self_type: ordering_type.clone(), + function: Box::new(Expression::TraitCallRef(TraitCallRef { + trait_name: format!("{stdlib_name}::cmp::Eq"), + function_name: "eq".to_string(), + self_type: ordering_type.clone(), trait_generics: vec![], - fun_generics: vec![], - param_types: vec![ordering_type.clone(), ordering_type.clone()], - return_type: Type::bool(), + fun_generics: vec![], + param_types: vec![ordering_type.clone(), ordering_type.clone()], + return_type: Type::bool(), })), - params: vec![ + params: vec![ Expression::Ident(cmp_result_ident), Expression::Ident(make_less_result_ident), ], @@ -2067,11 +1986,11 @@ impl LeanGenerator<'_, '_, '_> { }); let cmp_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let cmp_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(cmp_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(cmp_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(cmp_call), }); @@ -2081,25 +2000,25 @@ impl LeanGenerator<'_, '_, '_> { ); let make_greater_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_greater_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(make_greater_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(make_greater_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(make_greater_call), }); let eq_call = Expression::Call(Call { - function: Box::new(Expression::TraitCallRef(TraitCallRef { - trait_name: format!("{stdlib_name}::cmp::Eq"), - function_name: "eq".to_string(), - self_type: ordering_type.clone(), + function: Box::new(Expression::TraitCallRef(TraitCallRef { + trait_name: format!("{stdlib_name}::cmp::Eq"), + function_name: "eq".to_string(), + self_type: ordering_type.clone(), trait_generics: vec![], - fun_generics: vec![], - param_types: vec![ordering_type.clone(), ordering_type.clone()], - return_type: Type::bool(), + fun_generics: vec![], + param_types: vec![ordering_type.clone(), ordering_type.clone()], + return_type: Type::bool(), })), - params: vec![ + params: vec![ Expression::Ident(cmp_result_ident), Expression::Ident(make_greater_result_ident), ], @@ -2133,11 +2052,11 @@ impl LeanGenerator<'_, '_, '_> { }); let cmp_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let cmp_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(cmp_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(cmp_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(cmp_call), }); @@ -2147,11 +2066,11 @@ impl LeanGenerator<'_, '_, '_> { ); let make_less_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_less_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(make_less_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(make_less_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(make_less_call), }); @@ -2161,25 +2080,25 @@ impl LeanGenerator<'_, '_, '_> { ); let make_eq_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_eq_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(make_eq_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(make_eq_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(make_eq_call), }); let eq_to_less_call = Expression::Call(Call { - function: Box::new(Expression::TraitCallRef(TraitCallRef { - trait_name: format!("{stdlib_name}::cmp::Eq"), - function_name: "eq".to_string(), - self_type: ordering_type.clone(), + function: Box::new(Expression::TraitCallRef(TraitCallRef { + trait_name: format!("{stdlib_name}::cmp::Eq"), + function_name: "eq".to_string(), + self_type: ordering_type.clone(), trait_generics: vec![], - fun_generics: vec![], - param_types: vec![ordering_type.clone(), ordering_type.clone()], - return_type: Type::bool(), + fun_generics: vec![], + param_types: vec![ordering_type.clone(), ordering_type.clone()], + return_type: Type::bool(), })), - params: vec![ + params: vec![ Expression::Ident(cmp_result_ident.clone()), Expression::Ident(make_less_result_ident), ], @@ -2187,25 +2106,25 @@ impl LeanGenerator<'_, '_, '_> { }); let eq_to_less_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_eq_to_less_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(eq_to_less_result_ident.clone()), - typ: Type::bool(), + pattern: Pattern::Identifier(eq_to_less_result_ident.clone()), + typ: Type::bool(), expression: Box::new(eq_to_less_call), }); let eq_to_eq_call = Expression::Call(Call { - function: Box::new(Expression::TraitCallRef(TraitCallRef { - trait_name: format!("{stdlib_name}::cmp::Eq"), - function_name: "eq".to_string(), - self_type: ordering_type.clone(), + function: Box::new(Expression::TraitCallRef(TraitCallRef { + trait_name: format!("{stdlib_name}::cmp::Eq"), + function_name: "eq".to_string(), + self_type: ordering_type.clone(), trait_generics: vec![], - fun_generics: vec![], - param_types: vec![ordering_type.clone(), ordering_type.clone()], - return_type: Type::bool(), + fun_generics: vec![], + param_types: vec![ordering_type.clone(), ordering_type.clone()], + return_type: Type::bool(), })), - params: vec![ + params: vec![ Expression::Ident(cmp_result_ident.clone()), Expression::Ident(make_eq_result_ident), ], @@ -2213,11 +2132,11 @@ impl LeanGenerator<'_, '_, '_> { }); let eq_to_eq_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_eq_to_eq_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(eq_to_eq_result_ident.clone()), - typ: Type::bool(), + pattern: Pattern::Identifier(eq_to_eq_result_ident.clone()), + typ: Type::bool(), expression: Box::new(eq_to_eq_call), }); @@ -2259,11 +2178,11 @@ impl LeanGenerator<'_, '_, '_> { }); let cmp_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let cmp_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(cmp_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(cmp_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(cmp_call), }); @@ -2273,11 +2192,11 @@ impl LeanGenerator<'_, '_, '_> { ); let make_greater_result_id = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_greater_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(make_greater_result_id.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(make_greater_result_id.clone()), + typ: ordering_type.clone(), expression: Box::new(make_greater_call), }); @@ -2287,25 +2206,25 @@ impl LeanGenerator<'_, '_, '_> { ); let make_eq_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_eq_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(make_eq_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(make_eq_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(make_eq_call), }); let eq_to_greater_call = Expression::Call(Call { - function: Box::new(Expression::TraitCallRef(TraitCallRef { - trait_name: format!("{stdlib_name}::cmp::Eq"), - function_name: "eq".to_string(), - self_type: ordering_type.clone(), + function: Box::new(Expression::TraitCallRef(TraitCallRef { + trait_name: format!("{stdlib_name}::cmp::Eq"), + function_name: "eq".to_string(), + self_type: ordering_type.clone(), trait_generics: vec![], - fun_generics: vec![], - param_types: vec![ordering_type.clone(), ordering_type.clone()], - return_type: Type::bool(), + fun_generics: vec![], + param_types: vec![ordering_type.clone(), ordering_type.clone()], + return_type: Type::bool(), })), - params: vec![ + params: vec![ Expression::Ident(cmp_result_ident.clone()), Expression::Ident(make_greater_result_id), ], @@ -2313,25 +2232,25 @@ impl LeanGenerator<'_, '_, '_> { }); let eq_to_greater_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_eq_to_greater_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(eq_to_greater_result_ident.clone()), - typ: Type::bool(), + pattern: Pattern::Identifier(eq_to_greater_result_ident.clone()), + typ: Type::bool(), expression: Box::new(eq_to_greater_call), }); let eq_to_eq_call = Expression::Call(Call { - function: Box::new(Expression::TraitCallRef(TraitCallRef { - trait_name: format!("{stdlib_name}::cmp::Eq"), - function_name: "eq".to_string(), - self_type: ordering_type.clone(), + function: Box::new(Expression::TraitCallRef(TraitCallRef { + trait_name: format!("{stdlib_name}::cmp::Eq"), + function_name: "eq".to_string(), + self_type: ordering_type.clone(), trait_generics: vec![], - fun_generics: vec![], - param_types: vec![ordering_type.clone(), ordering_type.clone()], - return_type: Type::bool(), + fun_generics: vec![], + param_types: vec![ordering_type.clone(), ordering_type.clone()], + return_type: Type::bool(), })), - params: vec![ + params: vec![ Expression::Ident(cmp_result_ident.clone()), Expression::Ident(make_eq_result_ident), ], @@ -2339,11 +2258,11 @@ impl LeanGenerator<'_, '_, '_> { }); let eq_to_eq_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_eq_to_eq_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(eq_to_eq_result_ident.clone()), - typ: Type::bool(), + pattern: Pattern::Identifier(eq_to_eq_result_ident.clone()), + typ: Type::bool(), expression: Box::new(eq_to_eq_call), }); @@ -2402,8 +2321,8 @@ impl LeanGenerator<'_, '_, '_> { { let builtin_target = Expression::builtin_call_ref(builtin_name.as_str(), output_type); let call = Call { - function: Box::new(builtin_target), - params: vec![rhs], + function: Box::new(builtin_target), + params: vec![rhs], return_type: output_type.clone(), }; Expression::Call(call) @@ -2435,8 +2354,8 @@ impl LeanGenerator<'_, '_, '_> { }; let call = Call { - function: Box::new(Expression::TraitCallRef(call_target)), - params: vec![rhs], + function: Box::new(Expression::TraitCallRef(call_target)), + params: vec![rhs], return_type: output_type.clone(), }; @@ -2457,11 +2376,11 @@ impl LeanGenerator<'_, '_, '_> { HirArrayLiteral::Standard(elems) => { let elems = elems.iter().map(|e| self.generate_expr(*e)).collect_vec(); let call = Call { - function: Box::new(Expression::builtin_call_ref( + function: Box::new(Expression::builtin_call_ref( MAKE_ARRAY_BUILTIN_NAME, output_type, )), - params: elems, + params: elems, return_type: output_type.clone(), }; Expression::Call(call) @@ -2471,11 +2390,11 @@ impl LeanGenerator<'_, '_, '_> { } => { let elem_expr = self.generate_expr(*repeated_element); let call = Call { - function: Box::new(Expression::builtin_call_ref( + function: Box::new(Expression::builtin_call_ref( MAKE_REPEATED_ARRAY_BUILTIN_NAME, output_type, )), - params: vec![elem_expr], + params: vec![elem_expr], return_type: output_type.clone(), }; Expression::Call(call) @@ -2485,11 +2404,11 @@ impl LeanGenerator<'_, '_, '_> { HirArrayLiteral::Standard(elems) => { let elems = elems.iter().map(|e| self.generate_expr(*e)).collect_vec(); let call = Call { - function: Box::new(Expression::builtin_call_ref( + function: Box::new(Expression::builtin_call_ref( MAKE_SLICE_BUILTIN_NAME, output_type, )), - params: elems, + params: elems, return_type: output_type.clone(), }; Expression::Call(call) @@ -2506,7 +2425,7 @@ impl LeanGenerator<'_, '_, '_> { let length_lit = match length.expr { TypeExpr::NumericConst(n) => Literal::Numeric(NumericLiteral { value: n, - typ: length.kind.into_type(), + typ: length.kind.into_type(), }), TypeExpr::TypeVariable(name) => { Literal::ConstGeneric(ConstGenericLiteral { @@ -2535,12 +2454,8 @@ impl LeanGenerator<'_, '_, '_> { } }, HirLiteral::Bool(bool) => Expression::Literal(Literal::Bool(*bool)), - HirLiteral::Integer(signed_field) => { - let value = format!( - "{}{}", - if signed_field.is_negative() { "-" } else { "" }, - signed_field.absolute_value() - ); + HirLiteral::Integer(field) => { + let value = field.to_string(); let literal = NumericLiteral { value, @@ -2558,11 +2473,8 @@ impl LeanGenerator<'_, '_, '_> { let all_vars = vec![template].into_iter().chain(vars).collect_vec(); let call = Call { - function: Box::new(Expression::builtin_call_ref( - "mkFormatString", - output_type, - )), - params: all_vars, + function: Box::new(Expression::builtin_call_ref("mkFormatString", output_type)), + params: all_vars, return_type: output_type.clone(), }; Expression::Call(call) @@ -2741,7 +2653,7 @@ impl LeanGenerator<'_, '_, '_> { let global_call = GlobalCallRef { name: global_name, - typ: global_type, + typ: global_type, }; Expression::GlobalCallRef(global_call) @@ -2751,7 +2663,7 @@ impl LeanGenerator<'_, '_, '_> { if let TypeExpr::Function(_) = &typ.expr { let ident = IdentCallRef { - name: sanitize_variable_name(&name), + name: sanitize_variable_name(&name), func_type: typ.expr, }; @@ -2759,7 +2671,7 @@ impl LeanGenerator<'_, '_, '_> { } else { let identifier = Identifier { name: sanitize_variable_name(&name), - typ: output_type.clone(), + typ: output_type.clone(), }; Expression::Ident(identifier) @@ -2890,7 +2802,7 @@ impl LeanGenerator<'_, '_, '_> { match lvalue { HirLValue::Ident(ident, typ) => LValue::Ident(Identifier { name: self.context.def_interner.definition_name(ident.id).to_string(), - typ: self.generate_lean_type_value(typ, None), + typ: self.generate_lean_type_value(typ, None), }), HirLValue::MemberAccess { object, @@ -3043,12 +2955,12 @@ impl LeanGenerator<'_, '_, '_> { .iter() .map(|t| self.substitute_bindings(t, bindings)) .collect(), - named: generics + named: generics .named .iter() .map(|t| NamedType { name: t.name.clone(), - typ: self.substitute_bindings(&t.typ, bindings), + typ: self.substitute_bindings(&t.typ, bindings), }) .collect(), }, From b9055ea2a94941aeb90307a1bfdbf06b9766f801 Mon Sep 17 00:00:00 2001 From: Akosh Farkash Date: Thu, 16 Apr 2026 16:42:15 +0100 Subject: [PATCH 2/3] Fix formatting --- src/lean/builtin.rs | 19 +- src/lean/generator.rs | 401 ++++++++++++++++++++++++++---------------- 2 files changed, 255 insertions(+), 165 deletions(-) diff --git a/src/lean/builtin.rs b/src/lean/builtin.rs index 252f0184..6b0f434c 100644 --- a/src/lean/builtin.rs +++ b/src/lean/builtin.rs @@ -1,7 +1,8 @@ use noirc_frontend::{ ast::{BinaryOpKind, UnaryOp}, shared::Signedness, - Type as NoirType, TypeBinding, + Type as NoirType, + TypeBinding, }; use crate::lean::ast::{BuiltinCallRef, Call, DeclCallRef, Expression, Type}; @@ -43,8 +44,8 @@ pub fn make_ordering_const(crate_name: &str, ordering_name: &str) -> Expression Expression::Call(Call { function: Box::new(Expression::DeclCallRef(DeclCallRef { - function: format!("{crate_name}::{ordering_name}"), - generics: vec![], + function: format!("{crate_name}::{ordering_name}"), + generics: vec![], param_types: vec![], return_type: return_type.clone(), })), @@ -58,11 +59,11 @@ pub fn make_ordering_const(crate_name: &str, ordering_name: &str) -> Expression #[must_use] pub fn make_beq(left: Expression, right: Expression) -> Expression { Expression::Call(Call { - function: Box::new(Expression::BuiltinCallRef(BuiltinCallRef { - name: BEQ_NAME.to_string(), + function: Box::new(Expression::BuiltinCallRef(BuiltinCallRef { + name: BEQ_NAME.to_string(), return_type: Type::bool(), })), - params: vec![left, right], + params: vec![left, right], return_type: Type::bool(), }) } @@ -72,11 +73,11 @@ pub fn make_beq(left: Expression, right: Expression) -> Expression { #[must_use] pub fn make_bor(left: Expression, right: Expression) -> Expression { Expression::Call(Call { - function: Box::new(Expression::BuiltinCallRef(BuiltinCallRef { - name: BOR_NAME.to_string(), + function: Box::new(Expression::BuiltinCallRef(BuiltinCallRef { + name: BOR_NAME.to_string(), return_type: Type::bool(), })), - params: vec![left, right], + params: vec![left, right], return_type: Type::bool(), }) } diff --git a/src/lean/generator.rs b/src/lean/generator.rs index ac806d44..db93e63e 100644 --- a/src/lean/generator.rs +++ b/src/lean/generator.rs @@ -25,52 +25,138 @@ use noirc_frontend::{ }, hir_def::{ expr::{ - HirArrayLiteral, HirBlockExpression, HirCallExpression, HirCastExpression, - HirConstrainExpression, HirConstructorExpression, HirExpression, HirIdent, - HirIfExpression, HirIndexExpression, HirInfixExpression, HirLambda, HirLiteral, - HirMemberAccess, HirPrefixExpression, + HirArrayLiteral, + HirBlockExpression, + HirCallExpression, + HirCastExpression, + HirConstrainExpression, + HirConstructorExpression, + HirExpression, + HirIdent, + HirIfExpression, + HirIndexExpression, + HirInfixExpression, + HirLambda, + HirLiteral, + HirMemberAccess, + HirPrefixExpression, }, function::{FuncMeta, Param}, stmt::{ - HirAssignStatement, HirForStatement, HirLValue, HirLetStatement, HirPattern, + HirAssignStatement, + HirForStatement, + HirLValue, + HirLetStatement, + HirPattern, HirStatement, }, traits::{NamedType, TraitConstraint, TraitImpl}, }, node_interner::{ - DefinitionKind, DependencyId, ExprId, FuncId, GlobalId, StmtId, TraitId, TraitImplId, - TypeAliasId, TypeId, + DefinitionKind, + DependencyId, + ExprId, + FuncId, + GlobalId, + StmtId, + TraitId, + TraitImplId, + TypeAliasId, + TypeId, }, shared::Signedness, token::{FunctionAttributeKind, SecondaryAttributeKind}, - BinaryTypeOperator, DataType, Kind as NoirKind, NamedGeneric, QuotedType, ResolvedGeneric, - Shared, StructField, Type as NoirType, TypeBinding, TypeBindings, TypeVariable, TypeVariableId, + BinaryTypeOperator, + DataType, + Kind as NoirKind, + NamedGeneric, + QuotedType, + ResolvedGeneric, + Shared, + StructField, + Type as NoirType, + TypeBinding, + TypeBindings, + TypeVariable, + TypeVariableId, }; use petgraph::data::DataMap; use crate::{ constants::{ - LAMPE_STRUCT_METHOD_SEPARATOR, NOIR_PATH_SEPARATOR, NONE_DEPENDENCY_VERSION, STDLIB_TOML, + LAMPE_STRUCT_METHOD_SEPARATOR, + NOIR_PATH_SEPARATOR, + NONE_DEPENDENCY_VERSION, + STDLIB_TOML, }, file_generator::to_import_from_noir_path, lean::{ ast::{ - AssignStatement, Block, BuiltinCallRef, BuiltinTag, BuiltinTypeExpr, Call, Cast, - ConstGenericLiteral, Crate, DeclCallRef, Deprecation, Expression, ForStatement, - FunctionDefinition, GlobalCallRef, GlobalDefinition, IdentCallRef, Identifier, - IfThenElse, Kind, LValue, Lambda, LetStatement, Literal, MemberAccess, Module, - ModuleDefinition, NumericLiteral, ParamDef, Pattern, Statement, StructDefinition, - StructPattern, TraitCallRef, TraitDefinition, TraitImplementation, - TraitMethodDeclaration, Type, TypeAlias, TypeArithOp, TypeDefinition, TypeExpr, - TypePattern, WhereClause, + AssignStatement, + Block, + BuiltinCallRef, + BuiltinTag, + BuiltinTypeExpr, + Call, + Cast, + ConstGenericLiteral, + Crate, + DeclCallRef, + Deprecation, + Expression, + ForStatement, + FunctionDefinition, + GlobalCallRef, + GlobalDefinition, + IdentCallRef, + Identifier, + IfThenElse, + Kind, + LValue, + Lambda, + LetStatement, + Literal, + MemberAccess, + Module, + ModuleDefinition, + NumericLiteral, + ParamDef, + Pattern, + Statement, + StructDefinition, + StructPattern, + TraitCallRef, + TraitDefinition, + TraitImplementation, + TraitMethodDeclaration, + Type, + TypeAlias, + TypeArithOp, + TypeDefinition, + TypeExpr, + TypePattern, + WhereClause, }, builtin::{ - self, make_bor, make_ordering_const, make_ordering_type, BuiltinType, - ASSERT_BUILTIN_NAME, MAKE_ARRAY_BUILTIN_NAME, MAKE_EQUAL_NAME, MAKE_GREATER_NAME, - MAKE_LESS_NAME, MAKE_REPEATED_ARRAY_BUILTIN_NAME, MAKE_REPEATED_SLICE_BUILTIN_NAME, - MAKE_SLICE_BUILTIN_NAME, MAKE_STRUCT_BUILTIN_NAME, UNIT_TYPE_NAME, + self, + make_bor, + make_ordering_const, + make_ordering_type, + BuiltinType, + ASSERT_BUILTIN_NAME, + MAKE_ARRAY_BUILTIN_NAME, + MAKE_EQUAL_NAME, + MAKE_GREATER_NAME, + MAKE_LESS_NAME, + MAKE_REPEATED_ARRAY_BUILTIN_NAME, + MAKE_REPEATED_SLICE_BUILTIN_NAME, + MAKE_SLICE_BUILTIN_NAME, + MAKE_STRUCT_BUILTIN_NAME, + UNIT_TYPE_NAME, }, - conflicts_with_lean_keyword, LEAN_QUOTE_END, LEAN_QUOTE_START, + conflicts_with_lean_keyword, + LEAN_QUOTE_END, + LEAN_QUOTE_START, }, }; @@ -750,9 +836,9 @@ impl LeanGenerator<'_, '_, '_> { NoirKind::Any, ); let dummy_generic = NoirType::NamedGeneric(NamedGeneric { - type_var: dummy_tv.clone(), - name: Rc::new("LOOKUP_DUMMY".to_string()), - implicit: false, + type_var: dummy_tv.clone(), + name: Rc::new("LOOKUP_DUMMY".to_string()), + implicit: false, original_type_var_id: None, }); @@ -828,9 +914,9 @@ impl LeanGenerator<'_, '_, '_> { .iter() .map(|g| { NoirType::NamedGeneric(NamedGeneric { - type_var: g.type_var.clone(), - name: g.name.clone(), - implicit: false, + type_var: g.type_var.clone(), + name: g.name.clone(), + implicit: false, original_type_var_id: None, }) }) @@ -918,7 +1004,7 @@ impl LeanGenerator<'_, '_, '_> { let functions = functions.into_iter().sorted().collect_vec(); ModuleDefs { - func_defs: functions, + func_defs: functions, global_defs: globals, } } @@ -1005,7 +1091,7 @@ impl LeanGenerator<'_, '_, '_> { return_type: Type, ) -> Expression { let call_identifier = Expression::BuiltinCallRef(BuiltinCallRef { - name: name.to_string(), + name: name.to_string(), return_type: return_type.clone(), }); let params = params @@ -1602,7 +1688,7 @@ impl LeanGenerator<'_, '_, '_> { let return_type = Type::tuple(&elem_types); let call_ref = Expression::BuiltinCallRef(BuiltinCallRef { - name: MAKE_STRUCT_BUILTIN_NAME.to_string(), + name: MAKE_STRUCT_BUILTIN_NAME.to_string(), return_type: return_type.clone(), }); @@ -1623,7 +1709,7 @@ impl LeanGenerator<'_, '_, '_> { let else_expr = cond.alternative.map(|e| Box::new(self.generate_expr(e))); let ite = IfThenElse { - condition: Box::new(if_cond), + condition: Box::new(if_cond), then_branch: Box::new(then_expr), else_branch: else_expr, }; @@ -1639,8 +1725,8 @@ impl LeanGenerator<'_, '_, '_> { let constraint_expr = self.generate_expr(constrain.0); let builtin_ref = Expression::builtin_call_ref(ASSERT_BUILTIN_NAME, output_type); let call = Call { - function: Box::new(builtin_ref), - params: vec![constraint_expr], + function: Box::new(builtin_ref), + params: vec![constraint_expr], return_type: output_type.clone(), }; @@ -1740,7 +1826,7 @@ impl LeanGenerator<'_, '_, '_> { let return_type = Type::data_type(&name, generic_args); let call_ref = Expression::BuiltinCallRef(BuiltinCallRef { - name: MAKE_STRUCT_BUILTIN_NAME.to_string(), + name: MAKE_STRUCT_BUILTIN_NAME.to_string(), return_type: return_type.clone(), }); @@ -1783,32 +1869,32 @@ impl LeanGenerator<'_, '_, '_> { index_expr } else { Expression::Cast(Cast { - lhs: Box::new(index_expr), + lhs: Box::new(index_expr), target: Type::integer(32, false), }) } } _ => Expression::Cast(Cast { - lhs: Box::new(index_expr), + lhs: Box::new(index_expr), target: Type::integer(32, false), }), }, _ => Expression::Cast(Cast { - lhs: Box::new(index_expr), + lhs: Box::new(index_expr), target: Type::integer(32, false), }), }, _ => panic!("Non numeric literal {lit:?} encountered as index in index expression"), }, _ => Expression::Cast(Cast { - lhs: Box::new(index_expr), + lhs: Box::new(index_expr), target: Type::integer(32, false), }), }; let call = Call { - function: Box::new(call_target), - params: vec![collection_expr, index_expr], + function: Box::new(call_target), + params: vec![collection_expr, index_expr], return_type: output_type.clone(), }; @@ -1835,8 +1921,8 @@ impl LeanGenerator<'_, '_, '_> { if let Some(builtin_name) = maybe_builtin { let builtin_target = Expression::builtin_call_ref(builtin_name.as_str(), output_type); let call = Call { - function: Box::new(builtin_target), - params: vec![lhs, rhs], + function: Box::new(builtin_target), + params: vec![lhs, rhs], return_type: output_type.clone(), }; Expression::Call(call) @@ -1891,12 +1977,12 @@ impl LeanGenerator<'_, '_, '_> { }); let negation_call_ref = Expression::BuiltinCallRef(BuiltinCallRef { - name: "bNot".to_string(), + name: "bNot".to_string(), return_type: Type::bool(), }); Expression::Call(Call { - function: Box::new(negation_call_ref), - params: vec![eq_call], + function: Box::new(negation_call_ref), + params: vec![eq_call], return_type: Type::bool(), }) } @@ -1921,11 +2007,11 @@ impl LeanGenerator<'_, '_, '_> { }); let cmp_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let cmp_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(cmp_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(cmp_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(cmp_call), }); @@ -1935,25 +2021,25 @@ impl LeanGenerator<'_, '_, '_> { ); let make_less_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_less_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(make_less_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(make_less_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(make_less_call), }); let eq_call = Expression::Call(Call { - function: Box::new(Expression::TraitCallRef(TraitCallRef { - trait_name: format!("{stdlib_name}::cmp::Eq"), - function_name: "eq".to_string(), - self_type: ordering_type.clone(), + function: Box::new(Expression::TraitCallRef(TraitCallRef { + trait_name: format!("{stdlib_name}::cmp::Eq"), + function_name: "eq".to_string(), + self_type: ordering_type.clone(), trait_generics: vec![], - fun_generics: vec![], - param_types: vec![ordering_type.clone(), ordering_type.clone()], - return_type: Type::bool(), + fun_generics: vec![], + param_types: vec![ordering_type.clone(), ordering_type.clone()], + return_type: Type::bool(), })), - params: vec![ + params: vec![ Expression::Ident(cmp_result_ident), Expression::Ident(make_less_result_ident), ], @@ -1986,11 +2072,11 @@ impl LeanGenerator<'_, '_, '_> { }); let cmp_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let cmp_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(cmp_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(cmp_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(cmp_call), }); @@ -2000,25 +2086,25 @@ impl LeanGenerator<'_, '_, '_> { ); let make_greater_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_greater_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(make_greater_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(make_greater_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(make_greater_call), }); let eq_call = Expression::Call(Call { - function: Box::new(Expression::TraitCallRef(TraitCallRef { - trait_name: format!("{stdlib_name}::cmp::Eq"), - function_name: "eq".to_string(), - self_type: ordering_type.clone(), + function: Box::new(Expression::TraitCallRef(TraitCallRef { + trait_name: format!("{stdlib_name}::cmp::Eq"), + function_name: "eq".to_string(), + self_type: ordering_type.clone(), trait_generics: vec![], - fun_generics: vec![], - param_types: vec![ordering_type.clone(), ordering_type.clone()], - return_type: Type::bool(), + fun_generics: vec![], + param_types: vec![ordering_type.clone(), ordering_type.clone()], + return_type: Type::bool(), })), - params: vec![ + params: vec![ Expression::Ident(cmp_result_ident), Expression::Ident(make_greater_result_ident), ], @@ -2052,11 +2138,11 @@ impl LeanGenerator<'_, '_, '_> { }); let cmp_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let cmp_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(cmp_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(cmp_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(cmp_call), }); @@ -2066,11 +2152,11 @@ impl LeanGenerator<'_, '_, '_> { ); let make_less_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_less_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(make_less_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(make_less_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(make_less_call), }); @@ -2080,25 +2166,25 @@ impl LeanGenerator<'_, '_, '_> { ); let make_eq_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_eq_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(make_eq_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(make_eq_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(make_eq_call), }); let eq_to_less_call = Expression::Call(Call { - function: Box::new(Expression::TraitCallRef(TraitCallRef { - trait_name: format!("{stdlib_name}::cmp::Eq"), - function_name: "eq".to_string(), - self_type: ordering_type.clone(), + function: Box::new(Expression::TraitCallRef(TraitCallRef { + trait_name: format!("{stdlib_name}::cmp::Eq"), + function_name: "eq".to_string(), + self_type: ordering_type.clone(), trait_generics: vec![], - fun_generics: vec![], - param_types: vec![ordering_type.clone(), ordering_type.clone()], - return_type: Type::bool(), + fun_generics: vec![], + param_types: vec![ordering_type.clone(), ordering_type.clone()], + return_type: Type::bool(), })), - params: vec![ + params: vec![ Expression::Ident(cmp_result_ident.clone()), Expression::Ident(make_less_result_ident), ], @@ -2106,25 +2192,25 @@ impl LeanGenerator<'_, '_, '_> { }); let eq_to_less_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_eq_to_less_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(eq_to_less_result_ident.clone()), - typ: Type::bool(), + pattern: Pattern::Identifier(eq_to_less_result_ident.clone()), + typ: Type::bool(), expression: Box::new(eq_to_less_call), }); let eq_to_eq_call = Expression::Call(Call { - function: Box::new(Expression::TraitCallRef(TraitCallRef { - trait_name: format!("{stdlib_name}::cmp::Eq"), - function_name: "eq".to_string(), - self_type: ordering_type.clone(), + function: Box::new(Expression::TraitCallRef(TraitCallRef { + trait_name: format!("{stdlib_name}::cmp::Eq"), + function_name: "eq".to_string(), + self_type: ordering_type.clone(), trait_generics: vec![], - fun_generics: vec![], - param_types: vec![ordering_type.clone(), ordering_type.clone()], - return_type: Type::bool(), + fun_generics: vec![], + param_types: vec![ordering_type.clone(), ordering_type.clone()], + return_type: Type::bool(), })), - params: vec![ + params: vec![ Expression::Ident(cmp_result_ident.clone()), Expression::Ident(make_eq_result_ident), ], @@ -2132,11 +2218,11 @@ impl LeanGenerator<'_, '_, '_> { }); let eq_to_eq_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_eq_to_eq_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(eq_to_eq_result_ident.clone()), - typ: Type::bool(), + pattern: Pattern::Identifier(eq_to_eq_result_ident.clone()), + typ: Type::bool(), expression: Box::new(eq_to_eq_call), }); @@ -2178,11 +2264,11 @@ impl LeanGenerator<'_, '_, '_> { }); let cmp_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let cmp_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(cmp_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(cmp_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(cmp_call), }); @@ -2192,11 +2278,11 @@ impl LeanGenerator<'_, '_, '_> { ); let make_greater_result_id = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_greater_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(make_greater_result_id.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(make_greater_result_id.clone()), + typ: ordering_type.clone(), expression: Box::new(make_greater_call), }); @@ -2206,25 +2292,25 @@ impl LeanGenerator<'_, '_, '_> { ); let make_eq_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_eq_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(make_eq_result_ident.clone()), - typ: ordering_type.clone(), + pattern: Pattern::Identifier(make_eq_result_ident.clone()), + typ: ordering_type.clone(), expression: Box::new(make_eq_call), }); let eq_to_greater_call = Expression::Call(Call { - function: Box::new(Expression::TraitCallRef(TraitCallRef { - trait_name: format!("{stdlib_name}::cmp::Eq"), - function_name: "eq".to_string(), - self_type: ordering_type.clone(), + function: Box::new(Expression::TraitCallRef(TraitCallRef { + trait_name: format!("{stdlib_name}::cmp::Eq"), + function_name: "eq".to_string(), + self_type: ordering_type.clone(), trait_generics: vec![], - fun_generics: vec![], - param_types: vec![ordering_type.clone(), ordering_type.clone()], - return_type: Type::bool(), + fun_generics: vec![], + param_types: vec![ordering_type.clone(), ordering_type.clone()], + return_type: Type::bool(), })), - params: vec![ + params: vec![ Expression::Ident(cmp_result_ident.clone()), Expression::Ident(make_greater_result_id), ], @@ -2232,25 +2318,25 @@ impl LeanGenerator<'_, '_, '_> { }); let eq_to_greater_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_eq_to_greater_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(eq_to_greater_result_ident.clone()), - typ: Type::bool(), + pattern: Pattern::Identifier(eq_to_greater_result_ident.clone()), + typ: Type::bool(), expression: Box::new(eq_to_greater_call), }); let eq_to_eq_call = Expression::Call(Call { - function: Box::new(Expression::TraitCallRef(TraitCallRef { - trait_name: format!("{stdlib_name}::cmp::Eq"), - function_name: "eq".to_string(), - self_type: ordering_type.clone(), + function: Box::new(Expression::TraitCallRef(TraitCallRef { + trait_name: format!("{stdlib_name}::cmp::Eq"), + function_name: "eq".to_string(), + self_type: ordering_type.clone(), trait_generics: vec![], - fun_generics: vec![], - param_types: vec![ordering_type.clone(), ordering_type.clone()], - return_type: Type::bool(), + fun_generics: vec![], + param_types: vec![ordering_type.clone(), ordering_type.clone()], + return_type: Type::bool(), })), - params: vec![ + params: vec![ Expression::Ident(cmp_result_ident.clone()), Expression::Ident(make_eq_result_ident), ], @@ -2258,11 +2344,11 @@ impl LeanGenerator<'_, '_, '_> { }); let eq_to_eq_result_ident = Identifier { name: self.name_supply.get_name(), - typ: ordering_type.clone(), + typ: ordering_type.clone(), }; let make_eq_to_eq_result = Statement::Let(LetStatement { - pattern: Pattern::Identifier(eq_to_eq_result_ident.clone()), - typ: Type::bool(), + pattern: Pattern::Identifier(eq_to_eq_result_ident.clone()), + typ: Type::bool(), expression: Box::new(eq_to_eq_call), }); @@ -2321,8 +2407,8 @@ impl LeanGenerator<'_, '_, '_> { { let builtin_target = Expression::builtin_call_ref(builtin_name.as_str(), output_type); let call = Call { - function: Box::new(builtin_target), - params: vec![rhs], + function: Box::new(builtin_target), + params: vec![rhs], return_type: output_type.clone(), }; Expression::Call(call) @@ -2354,8 +2440,8 @@ impl LeanGenerator<'_, '_, '_> { }; let call = Call { - function: Box::new(Expression::TraitCallRef(call_target)), - params: vec![rhs], + function: Box::new(Expression::TraitCallRef(call_target)), + params: vec![rhs], return_type: output_type.clone(), }; @@ -2376,11 +2462,11 @@ impl LeanGenerator<'_, '_, '_> { HirArrayLiteral::Standard(elems) => { let elems = elems.iter().map(|e| self.generate_expr(*e)).collect_vec(); let call = Call { - function: Box::new(Expression::builtin_call_ref( + function: Box::new(Expression::builtin_call_ref( MAKE_ARRAY_BUILTIN_NAME, output_type, )), - params: elems, + params: elems, return_type: output_type.clone(), }; Expression::Call(call) @@ -2390,11 +2476,11 @@ impl LeanGenerator<'_, '_, '_> { } => { let elem_expr = self.generate_expr(*repeated_element); let call = Call { - function: Box::new(Expression::builtin_call_ref( + function: Box::new(Expression::builtin_call_ref( MAKE_REPEATED_ARRAY_BUILTIN_NAME, output_type, )), - params: vec![elem_expr], + params: vec![elem_expr], return_type: output_type.clone(), }; Expression::Call(call) @@ -2404,11 +2490,11 @@ impl LeanGenerator<'_, '_, '_> { HirArrayLiteral::Standard(elems) => { let elems = elems.iter().map(|e| self.generate_expr(*e)).collect_vec(); let call = Call { - function: Box::new(Expression::builtin_call_ref( + function: Box::new(Expression::builtin_call_ref( MAKE_SLICE_BUILTIN_NAME, output_type, )), - params: elems, + params: elems, return_type: output_type.clone(), }; Expression::Call(call) @@ -2425,7 +2511,7 @@ impl LeanGenerator<'_, '_, '_> { let length_lit = match length.expr { TypeExpr::NumericConst(n) => Literal::Numeric(NumericLiteral { value: n, - typ: length.kind.into_type(), + typ: length.kind.into_type(), }), TypeExpr::TypeVariable(name) => { Literal::ConstGeneric(ConstGenericLiteral { @@ -2473,8 +2559,11 @@ impl LeanGenerator<'_, '_, '_> { let all_vars = vec![template].into_iter().chain(vars).collect_vec(); let call = Call { - function: Box::new(Expression::builtin_call_ref("mkFormatString", output_type)), - params: all_vars, + function: Box::new(Expression::builtin_call_ref( + "mkFormatString", + output_type, + )), + params: all_vars, return_type: output_type.clone(), }; Expression::Call(call) @@ -2653,7 +2742,7 @@ impl LeanGenerator<'_, '_, '_> { let global_call = GlobalCallRef { name: global_name, - typ: global_type, + typ: global_type, }; Expression::GlobalCallRef(global_call) @@ -2663,7 +2752,7 @@ impl LeanGenerator<'_, '_, '_> { if let TypeExpr::Function(_) = &typ.expr { let ident = IdentCallRef { - name: sanitize_variable_name(&name), + name: sanitize_variable_name(&name), func_type: typ.expr, }; @@ -2671,7 +2760,7 @@ impl LeanGenerator<'_, '_, '_> { } else { let identifier = Identifier { name: sanitize_variable_name(&name), - typ: output_type.clone(), + typ: output_type.clone(), }; Expression::Ident(identifier) @@ -2802,7 +2891,7 @@ impl LeanGenerator<'_, '_, '_> { match lvalue { HirLValue::Ident(ident, typ) => LValue::Ident(Identifier { name: self.context.def_interner.definition_name(ident.id).to_string(), - typ: self.generate_lean_type_value(typ, None), + typ: self.generate_lean_type_value(typ, None), }), HirLValue::MemberAccess { object, @@ -2955,12 +3044,12 @@ impl LeanGenerator<'_, '_, '_> { .iter() .map(|t| self.substitute_bindings(t, bindings)) .collect(), - named: generics + named: generics .named .iter() .map(|t| NamedType { name: t.name.clone(), - typ: self.substitute_bindings(&t.typ, bindings), + typ: self.substitute_bindings(&t.typ, bindings), }) .collect(), }, From 8bd03bfb05fe10e7613372e3a6eed98c91acc486 Mon Sep 17 00:00:00 2001 From: Akosh Farkash Date: Tue, 21 Apr 2026 14:36:01 +0100 Subject: [PATCH 3/3] Copy the current stdlib from Noir --- stdlib/src/aes128.nr | 2 +- stdlib/src/append.nr | 18 +- stdlib/src/array/check_shuffle.nr | 34 +-- stdlib/src/array/mod.nr | 32 +-- stdlib/src/array/quicksort.nr | 59 ++-- stdlib/src/cmp.nr | 286 ++++++++++---------- stdlib/src/collections/bounded_vec.nr | 161 +++++++++-- stdlib/src/collections/map.nr | 30 +-- stdlib/src/collections/mod.nr | 2 - stdlib/src/collections/umap.nr | 157 ++++++----- stdlib/src/collections/vec.nr | 371 -------------------------- stdlib/src/compat.nr | 1 + stdlib/src/convert.nr | 2 + stdlib/src/default.nr | 8 +- stdlib/src/ecdsa_secp256r1.nr | 16 ++ stdlib/src/embedded_curve_ops.nr | 82 +++--- stdlib/src/field/mod.nr | 138 +++++----- stdlib/src/hash/mod.nr | 66 ++--- stdlib/src/hash/poseidon2.nr | 8 +- stdlib/src/lib.nr | 14 +- stdlib/src/meta/expr.nr | 10 +- stdlib/src/meta/function_def.nr | 38 +-- stdlib/src/meta/mod.nr | 2 +- stdlib/src/meta/module.nr | 5 - stdlib/src/meta/type_def.nr | 22 +- stdlib/src/ops/arith.nr | 81 +----- stdlib/src/ops/bit.nr | 36 --- stdlib/src/option.nr | 6 +- stdlib/src/panic.nr | 3 + stdlib/src/prelude.nr | 1 - stdlib/src/primitive_docs.nr | 4 - stdlib/src/runtime.nr | 1 + stdlib/src/vector.nr | 36 +-- 33 files changed, 684 insertions(+), 1048 deletions(-) delete mode 100644 stdlib/src/collections/vec.nr diff --git a/stdlib/src/aes128.nr b/stdlib/src/aes128.nr index d7d13120..be00393f 100644 --- a/stdlib/src/aes128.nr +++ b/stdlib/src/aes128.nr @@ -1,5 +1,5 @@ // docs:start:aes128 -// Given a plaintext as an array of bytes, returns the corresponding aes128 ciphertext (CBC mode). Input padding is performed using PKCS#7, so that the output length is `input.len() + (16 - input.len() % 16)`. +/// Given a plaintext as an array of bytes, returns the corresponding aes128 ciphertext (CBC mode). Input padding is performed using PKCS#7, so that the output length is `input.len() + (16 - input.len() % 16)`. pub fn aes128_encrypt( input: [u8; N], iv: [u8; 16], diff --git a/stdlib/src/append.nr b/stdlib/src/append.nr index 3b483fc9..aa24cd10 100644 --- a/stdlib/src/append.nr +++ b/stdlib/src/append.nr @@ -1,11 +1,11 @@ -// Appends two values together, returning the result. -// -// An alternate name for this trait is `Monoid` if that is familiar. -// If not, it can be ignored. -// -// It is expected that for any implementation: -// - `T::empty().append(x) == x` -// - `x.append(T::empty()) == x` +/// Appends two values together, returning the result. +/// +/// An alternate name for this trait is `Monoid` if that is familiar. +/// If not, it can be ignored. +/// +/// It is expected that for any implementation: +/// - `T::empty().append(x) == x` +/// - `x.append(T::empty()) == x` // docs:start:append-trait pub trait Append { fn empty() -> Self; @@ -19,7 +19,7 @@ impl Append for [T] { } fn append(self, other: Self) -> Self { - // Slices have an existing append function which this will resolve to. + // Vectors have an existing append function which this will resolve to. self.append(other) } } diff --git a/stdlib/src/array/check_shuffle.nr b/stdlib/src/array/check_shuffle.nr index c3c87383..aa26c950 100644 --- a/stdlib/src/array/check_shuffle.nr +++ b/stdlib/src/array/check_shuffle.nr @@ -1,6 +1,6 @@ use crate::cmp::Eq; -unconstrained fn __get_shuffle_indices(lhs: [T; N], rhs: [T; N]) -> [u32; N] +unconstrained fn __get_shuffle_indices(lhs: &[T; N], rhs: &[T; N]) -> [u32; N] where T: Eq, { @@ -25,7 +25,7 @@ where shuffle_indices } -unconstrained fn __get_index(indices: [u32; N], idx: u32) -> u32 { +unconstrained fn __get_index(indices: &[u32; N], idx: u32) -> u32 { let mut result = 0; for i in 0..N { if (indices[i] == idx) { @@ -36,7 +36,7 @@ unconstrained fn __get_index(indices: [u32; N], idx: u32) -> u32 { result } -pub(crate) fn check_shuffle(lhs: [T; N], rhs: [T; N]) +pub(crate) fn check_shuffle(lhs: &[T; N], rhs: &[T; N]) where T: Eq, { @@ -46,7 +46,7 @@ where let shuffle_indices = __get_shuffle_indices(lhs, rhs); for i in 0..N { - let idx = __get_index(shuffle_indices, i); + let idx = __get_index(&shuffle_indices, i); assert_eq(shuffle_indices[idx], i); } for i in 0..N { @@ -77,28 +77,28 @@ mod test { fn test_shuffle() { let lhs: [Field; 5] = [0, 1, 2, 3, 4]; let rhs: [Field; 5] = [2, 0, 3, 1, 4]; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } #[test] fn test_shuffle_identity() { let lhs: [Field; 5] = [0, 1, 2, 3, 4]; let rhs: [Field; 5] = [0, 1, 2, 3, 4]; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } #[test(should_fail_with = "check_shuffle, lhs and rhs arrays do not contain equivalent values")] fn test_shuffle_fail() { let lhs: [Field; 5] = [0, 1, 2, 3, 4]; let rhs: [Field; 5] = [0, 1, 2, 3, 5]; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } #[test(should_fail_with = "check_shuffle, lhs and rhs arrays do not contain equivalent values")] fn test_shuffle_duplicates() { let lhs: [Field; 5] = [0, 1, 2, 3, 4]; let rhs: [Field; 5] = [0, 1, 2, 3, 3]; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } #[test] @@ -117,21 +117,21 @@ mod test { CompoundStruct { a: true, b: 9814, c: 0xeeffee0011001133 }, CompoundStruct { a: true, b: 5, c: 0xffffffffffffffff }, ]; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } #[test] fn test_shuffle_empty_array() { let lhs: [Field; 0] = []; let rhs: [Field; 0] = []; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } #[test] fn test_shuffle_single_element() { let lhs: [Field; 1] = [42]; let rhs: [Field; 1] = [42]; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } // arrays with duplicate values @@ -139,21 +139,21 @@ mod test { fn test_shuffle_with_duplicates() { let lhs: [Field; 4] = [1, 2, 1, 3]; let rhs: [Field; 4] = [1, 3, 1, 2]; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } #[test] fn test_shuffle_all_same_values() { let lhs: [Field; 5] = [42, 42, 42, 42, 42]; let rhs: [Field; 5] = [42, 42, 42, 42, 42]; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } #[test] fn test_shuffle_bool() { let lhs: [bool; 4] = [true, false, true, false]; let rhs: [bool; 4] = [false, true, false, true]; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } #[test] @@ -162,7 +162,7 @@ mod test { let struct2 = CompoundStruct { a: false, b: 0, c: 200 }; let lhs: [CompoundStruct; 4] = [struct1, struct2, struct1, struct2]; let rhs: [CompoundStruct; 4] = [struct2, struct1, struct2, struct1]; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } #[test(should_fail_with = "check_shuffle, lhs and rhs arrays do not contain equivalent values")] @@ -173,7 +173,7 @@ mod test { CompoundStruct { a: true, b: 42, c: 100 }, CompoundStruct { a: false, b: 1, c: 200 }, // Different b field ]; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } // test with negative field values @@ -181,6 +181,6 @@ mod test { fn test_shuffle_negative_values() { let lhs: [Field; 4] = [-1, -2, -3, -4]; let rhs: [Field; 4] = [-4, -3, -2, -1]; - check_shuffle(lhs, rhs); + check_shuffle(&lhs, &rhs); } } diff --git a/stdlib/src/array/mod.nr b/stdlib/src/array/mod.nr index 53379fd0..5acb2c49 100644 --- a/stdlib/src/array/mod.nr +++ b/stdlib/src/array/mod.nr @@ -54,7 +54,7 @@ impl [T; N] { /// let b = a.map(|a| a * 2); /// assert_eq(b, [2, 4, 6]); /// ``` - pub fn map(self, f: fn[Env](T) -> U) -> [U; N] { + pub fn map(&self, f: fn[Env](T) -> U) -> [U; N] { let uninitialized = crate::mem::zeroed(); let mut ret = [uninitialized; N]; @@ -75,7 +75,7 @@ impl [T; N] { /// let b = a.mapi(|i, a| i + a * 2); /// assert_eq(b, [2, 5, 8]); /// ``` - pub fn mapi(self, f: fn[Env](u32, T) -> U) -> [U; N] { + pub fn mapi(&self, f: fn[Env](u32, T) -> U) -> [U; N] { let uninitialized = crate::mem::zeroed(); let mut ret = [uninitialized; N]; @@ -100,7 +100,7 @@ impl [T; N] { /// }); /// assert_eq(a, b); /// ``` - pub fn for_each(self, f: fn[Env](T) -> ()) { + pub fn for_each(&self, f: fn[Env](T) -> ()) { for i in 0..self.len() { f(self[i]); } @@ -118,7 +118,7 @@ impl [T; N] { /// }); /// assert_eq(a, b); /// ``` - pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) { + pub fn for_eachi(&self, f: fn[Env](u32, T) -> ()) { for i in 0..self.len() { f(i, self[i]); } @@ -142,7 +142,7 @@ impl [T; N] { /// /// assert_eq(a3.fold(10, f), 10 - 1 - 2 - 3); /// ``` - pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U { + pub fn fold(&self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U { for elem in self { accumulator = f(accumulator, elem); } @@ -162,7 +162,7 @@ impl [T; N] { /// assert(reduced == 10); /// } /// ``` - pub fn reduce(self, f: fn[Env](T, T) -> T) -> T { + pub fn reduce(&self, f: fn[Env](T, T) -> T) -> T { let mut accumulator = self[0]; for i in 1..self.len() { accumulator = f(accumulator, self[i]); @@ -181,7 +181,7 @@ impl [T; N] { /// assert(all); /// } /// ``` - pub fn all(self, predicate: fn[Env](T) -> bool) -> bool { + pub fn all(&self, predicate: fn[Env](T) -> bool) -> bool { let mut ret = true; for elem in self { ret &= predicate(elem); @@ -200,7 +200,7 @@ impl [T; N] { /// assert(any); /// } /// ``` - pub fn any(self, predicate: fn[Env](T) -> bool) -> bool { + pub fn any(&self, predicate: fn[Env](T) -> bool) -> bool { let mut ret = false; for elem in self { ret |= predicate(elem); @@ -220,7 +220,7 @@ impl [T; N] { /// assert(concatenated_arr == [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]); /// } /// ``` - pub fn concat(self, array2: [T; M]) -> [T; N + M] { + pub fn concat(&self, array2: [T; M]) -> [T; N + M] { let mut result = [crate::mem::zeroed(); N + M]; for i in 0..N { result[i] = self[i]; @@ -250,7 +250,7 @@ where /// assert(sorted == [32, 42]); /// } /// ``` - pub fn sort(self) -> Self { + pub fn sort(&self) -> Self { self.sort_via(|a, b| a <= b) } } @@ -277,7 +277,7 @@ where /// assert(sorted_descending == [32, 42]); // does not verify /// } /// ``` - pub fn sort_via(self, ordering: fn[Env](T, T) -> bool) -> Self { + pub fn sort_via(&self, ordering: fn[Env](T, T) -> bool) -> Self { // Safety: `sorted` array is checked to be: // a. a permutation of `input`'s elements // b. satisfying the predicate `ordering` @@ -290,7 +290,7 @@ where "Array has not been sorted correctly according to `ordering`.", ); } - check_shuffle::check_shuffle(self, sorted); + check_shuffle::check_shuffle(self, &sorted); } sorted } @@ -345,7 +345,7 @@ mod test { #[test] fn test_sort() { - let mut arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1]; + let arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1]; let sorted = arr.sort(); @@ -355,7 +355,7 @@ mod test { #[test] fn test_sort_100_values() { - let mut arr: [u32; 100] = [ + let arr: [u32; 100] = [ 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2, 54, 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41, 19, 98, 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21, @@ -383,7 +383,7 @@ mod test { #[test] fn test_sort_via() { - let mut arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1]; + let arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1]; let sorted = arr.sort_via(sort_u32); @@ -393,7 +393,7 @@ mod test { #[test] fn test_sort_via_100_values() { - let mut arr: [u32; 100] = [ + let arr: [u32; 100] = [ 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2, 54, 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41, 19, 98, 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21, diff --git a/stdlib/src/array/quicksort.nr b/stdlib/src/array/quicksort.nr index 22f83500..8cf233e4 100644 --- a/stdlib/src/array/quicksort.nr +++ b/stdlib/src/array/quicksort.nr @@ -34,6 +34,7 @@ unconstrained fn quicksort_loop( break; } + // TODO: This causes an unnecessary clone on `stack` let (new_stack, (new_low, new_high)) = stack.pop_back(); stack = new_stack; @@ -50,10 +51,10 @@ unconstrained fn quicksort_loop( } pub unconstrained fn quicksort( - arr: [T; N], + arr: &[T; N], sortfn: unconstrained fn[Env](T, T) -> bool, ) -> [T; N] { - let mut arr: [T; N] = arr; + let mut arr: [T; N] = *arr; if arr.len() > 1 { quicksort_loop(&mut arr, 0, arr.len() - 1, sortfn); } @@ -83,7 +84,7 @@ mod test { fn test_empty_array() { let arr: [u32; 0] = []; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, arr); } @@ -91,7 +92,7 @@ mod test { fn test_single_element() { let arr: [u32; 1] = [42]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, arr); } @@ -99,7 +100,7 @@ mod test { fn test_two_elements_ascending() { let arr: [u32; 2] = [2, 1]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [1, 2]); } @@ -107,7 +108,7 @@ mod test { fn test_two_elements_descending() { let arr: [u32; 2] = [1, 2]; // Safety: test - let result = unsafe { quicksort(arr, descending) }; + let result = unsafe { quicksort(&arr, descending) }; assert_eq(result, [2, 1]); } @@ -115,7 +116,7 @@ mod test { fn test_already_sorted_ascending() { let arr: [u32; 5] = [1, 2, 3, 4, 5]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [1, 2, 3, 4, 5]); } @@ -127,7 +128,7 @@ mod test { } arr[0] = 2; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; arr[0] = 1; arr[1] = 2; assert_eq(result, arr); @@ -137,7 +138,7 @@ mod test { fn test_already_sorted_descending() { let arr: [u32; 5] = [5, 4, 3, 2, 1]; // Safety: test - let result = unsafe { quicksort(arr, descending) }; + let result = unsafe { quicksort(&arr, descending) }; assert_eq(result, [5, 4, 3, 2, 1]); } @@ -145,7 +146,7 @@ mod test { fn test_reverse_sorted_ascending() { let arr: [u32; 5] = [5, 4, 3, 2, 1]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [1, 2, 3, 4, 5]); } @@ -153,7 +154,7 @@ mod test { fn test_reverse_sorted_descending() { let arr: [u32; 5] = [1, 2, 3, 4, 5]; // Safety: test - let result = unsafe { quicksort(arr, descending) }; + let result = unsafe { quicksort(&arr, descending) }; assert_eq(result, [5, 4, 3, 2, 1]); } @@ -161,7 +162,7 @@ mod test { fn test_random_array_ascending() { let arr: [u32; 8] = [3, 1, 4, 1, 5, 9, 2, 6]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [1, 1, 2, 3, 4, 5, 6, 9]); } @@ -169,7 +170,7 @@ mod test { fn test_random_array_descending() { let arr: [u32; 8] = [3, 1, 4, 1, 5, 9, 2, 6]; // Safety: test - let result = unsafe { quicksort(arr, descending) }; + let result = unsafe { quicksort(&arr, descending) }; assert_eq(result, [9, 6, 5, 4, 3, 2, 1, 1]); } @@ -177,7 +178,7 @@ mod test { fn test_duplicate_elements() { let arr: [u32; 11] = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]); } @@ -185,7 +186,7 @@ mod test { fn test_all_same_elements() { let arr: [u32; 5] = [42, 42, 42, 42, 42]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [42, 42, 42, 42, 42]); } @@ -193,7 +194,7 @@ mod test { fn test_large_array() { let arr: [u32; 10] = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); } @@ -201,7 +202,7 @@ mod test { fn test_negative_numbers() { let arr: [i32; 8] = [-3, 1, -4, 1, -5, 9, -2, 6]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [-5, -4, -3, -2, 1, 1, 6, 9]); } @@ -209,7 +210,7 @@ mod test { fn test_zero_values() { let arr: [u32; 6] = [0, 1, 0, 2, 0, 3]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [0, 0, 0, 1, 2, 3]); } @@ -217,7 +218,7 @@ mod test { fn test_edge_case_near_sorted() { let arr: [u32; 8] = [1, 2, 3, 5, 4, 6, 7, 8]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [1, 2, 3, 4, 5, 6, 7, 8]); } @@ -225,7 +226,7 @@ mod test { fn test_edge_case_near_reverse_sorted() { let arr: [u32; 8] = [8, 7, 6, 4, 5, 3, 2, 1]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [1, 2, 3, 4, 5, 6, 7, 8]); } @@ -241,7 +242,7 @@ mod test { let arr: [i32; 8] = [-3, 1, -4, 1, -5, 9, -2, 6]; // Safety: test - let result = unsafe { quicksort(arr, abs_compare) }; + let result = unsafe { quicksort(&arr, abs_compare) }; assert_eq(result, [1, 1, -2, -3, -4, -5, 6, 9]); } @@ -250,7 +251,7 @@ mod test { // sort by absolute value let arr: [i32; 11] = [-3, 1, -4, 1, -5, 5, -5, 5, 9, -2, 6]; // Safety: test - let result = unsafe { quicksort(arr, abs_compare) }; + let result = unsafe { quicksort(&arr, abs_compare) }; assert_eq(result, [1, 1, -2, -3, -4, -5, 5, -5, 5, 6, 9]); } @@ -258,7 +259,7 @@ mod test { fn test_maximum_values() { let arr: [u32; 4] = [2 ^ 32 - 1, 1, 0, 2 ^ 32 - 2]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [0, 1, 2 ^ 32 - 2, 2 ^ 32 - 1]); } @@ -266,7 +267,7 @@ mod test { fn test_alternating_pattern() { let arr: [u32; 9] = [1, 9, 2, 8, 3, 7, 4, 6, 5]; // Safety: test - let result = unsafe { quicksort(arr, ascending) }; + let result = unsafe { quicksort(&arr, ascending) }; assert_eq(result, [1, 2, 3, 4, 5, 6, 7, 8, 9]); } @@ -274,11 +275,11 @@ mod test { fn test_multiple_sorts_same_array() { let arr: [u32; 8] = [3, 1, 4, 1, 5, 9, 2, 6]; // Safety: test - let result1 = unsafe { quicksort(arr, ascending) }; + let result1 = unsafe { quicksort(&arr, ascending) }; // Safety: test - let result2 = unsafe { quicksort(arr, ascending) }; + let result2 = unsafe { quicksort(&arr, ascending) }; // Safety: test - let result3 = unsafe { quicksort(arr, ascending) }; + let result3 = unsafe { quicksort(&arr, ascending) }; assert_eq(result1, result2); assert_eq(result2, result3); @@ -289,11 +290,11 @@ mod test { fn test_descending_then_ascending() { let arr: [u32; 8] = [3, 1, 4, 1, 5, 9, 2, 6]; // Safety: test - let desc_result = unsafe { quicksort(arr, descending) }; + let desc_result = unsafe { quicksort(&arr, descending) }; assert_eq(desc_result, [9, 6, 5, 4, 3, 2, 1, 1]); // Safety: test - let asc_result: [u32; 8] = unsafe { quicksort(desc_result, ascending) }; + let asc_result: [u32; 8] = unsafe { quicksort(&desc_result, ascending) }; assert_eq(asc_result, [1, 1, 2, 3, 4, 5, 6, 9]); } } diff --git a/stdlib/src/cmp.nr b/stdlib/src/cmp.nr index fd45030c..efd7f38c 100644 --- a/stdlib/src/cmp.nr +++ b/stdlib/src/cmp.nr @@ -1,5 +1,7 @@ +use crate::meta::ctstring::AsCtString; use crate::meta::derive_via; +/// Compare two values for equality #[derive_via(derive_eq)] // docs:start:eq-trait pub trait Eq { @@ -60,12 +62,6 @@ impl Eq for u8 { self == other } } -impl Eq for u1 { - fn eq(self, other: u1) -> bool { - self == other - } -} - impl Eq for i8 { fn eq(self, other: i8) -> bool { self == other @@ -134,53 +130,77 @@ impl Eq for str { } } -impl Eq for (A, B) -where - A: Eq, - B: Eq, -{ +comptime fn make_tuple_eq_body(n: u32) -> Quoted { + let mut body = f"self.0.eq(other.0)".as_ctstring(); + for i in 1u32..n { + body = body.append_fmtstr(f" & self.{i}.eq(other.{i})"); + } + f"{body}".quoted_contents() +} + +impl Eq for (A, B) { fn eq(self, other: (A, B)) -> bool { - self.0.eq(other.0) & self.1.eq(other.1) + make_tuple_eq_body!(2u32) } } -impl Eq for (A, B, C) -where - A: Eq, - B: Eq, - C: Eq, -{ +impl Eq for (A, B, C) { fn eq(self, other: (A, B, C)) -> bool { - self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) + make_tuple_eq_body!(3u32) } } -impl Eq for (A, B, C, D) -where - A: Eq, - B: Eq, - C: Eq, - D: Eq, -{ +impl Eq for (A, B, C, D) { fn eq(self, other: (A, B, C, D)) -> bool { - self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) + make_tuple_eq_body!(4u32) } } -impl Eq for (A, B, C, D, E) -where - A: Eq, - B: Eq, - C: Eq, - D: Eq, - E: Eq, -{ +impl Eq for (A, B, C, D, E) { fn eq(self, other: (A, B, C, D, E)) -> bool { - self.0.eq(other.0) - & self.1.eq(other.1) - & self.2.eq(other.2) - & self.3.eq(other.3) - & self.4.eq(other.4) + make_tuple_eq_body!(5u32) + } +} + +impl Eq for (A, B, C, D, E, F) { + fn eq(self, other: (A, B, C, D, E, F)) -> bool { + make_tuple_eq_body!(6u32) + } +} + +impl Eq for (A, B, C, D, E, F, G) { + fn eq(self, other: (A, B, C, D, E, F, G)) -> bool { + make_tuple_eq_body!(7u32) + } +} + +impl Eq for (A, B, C, D, E, F, G, H) { + fn eq(self, other: (A, B, C, D, E, F, G, H)) -> bool { + make_tuple_eq_body!(8u32) + } +} + +impl Eq for (A, B, C, D, E, F, G, H, I) { + fn eq(self, other: (A, B, C, D, E, F, G, H, I)) -> bool { + make_tuple_eq_body!(9u32) + } +} + +impl Eq for (A, B, C, D, E, F, G, H, I, J) { + fn eq(self, other: (A, B, C, D, E, F, G, H, I, J)) -> bool { + make_tuple_eq_body!(10u32) + } +} + +impl Eq for (A, B, C, D, E, F, G, H, I, J, K) { + fn eq(self, other: (A, B, C, D, E, F, G, H, I, J, K)) -> bool { + make_tuple_eq_body!(11u32) + } +} + +impl Eq for (A, B, C, D, E, F, G, H, I, J, K, L) { + fn eq(self, other: (A, B, C, D, E, F, G, H, I, J, K, L)) -> bool { + make_tuple_eq_body!(12u32) } } @@ -192,6 +212,8 @@ impl Eq for Ordering { // Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct // that has 3 public functions for constructing the struct. +/// A value with three states: `Ordering::less()`, `Ordering::equal()` or `Ordering::greater()`. +/// Most often used to encode the result of a comparison operation. pub struct Ordering { result: Field, } @@ -213,6 +235,8 @@ impl Ordering { } } +/// Compare one object to another, returning whether it is less-than, equal-to, +/// or greater-than the other object. #[derive_via(derive_ord)] // docs:start:ord-trait pub trait Ord { @@ -416,112 +440,102 @@ where } } -impl Ord for (A, B) -where - A: Ord, - B: Ord, -{ - fn cmp(self, other: (A, B)) -> Ordering { - let result = self.0.cmp(other.0); +comptime fn make_tuple_ord_body(n: u32) -> Quoted { + let last = n - 1u32; + let mut body = if last == 1 { + f"let result = self.0.cmp(other.0);".as_ctstring() + } else { + f"let mut result = self.0.cmp(other.0);".as_ctstring() + }; + for i in 1u32..last { + body = body.append_fmtstr( + f" if result == Ordering::equal() {{ result = self.{i}.cmp(other.{i}); }}", + ); + } + body = body.append_fmtstr( + f" if result != Ordering::equal() {{ result }} else {{ self.{last}.cmp(other.{last}) }}", + ); + f"{body}".quoted_contents() +} - if result != Ordering::equal() { - result - } else { - self.1.cmp(other.1) - } +impl Ord for (A, B) { + fn cmp(self, other: (A, B)) -> Ordering { + make_tuple_ord_body!(2u32) } } -impl Ord for (A, B, C) -where - A: Ord, - B: Ord, - C: Ord, -{ +impl Ord for (A, B, C) { fn cmp(self, other: (A, B, C)) -> Ordering { - let mut result = self.0.cmp(other.0); - - if result == Ordering::equal() { - result = self.1.cmp(other.1); - } - - if result == Ordering::equal() { - result = self.2.cmp(other.2); - } - - result + make_tuple_ord_body!(3u32) } } -impl Ord for (A, B, C, D) -where - A: Ord, - B: Ord, - C: Ord, - D: Ord, -{ +impl Ord for (A, B, C, D) { fn cmp(self, other: (A, B, C, D)) -> Ordering { - let mut result = self.0.cmp(other.0); - - if result == Ordering::equal() { - result = self.1.cmp(other.1); - } - - if result == Ordering::equal() { - result = self.2.cmp(other.2); - } + make_tuple_ord_body!(4u32) + } +} - if result == Ordering::equal() { - result = self.3.cmp(other.3); - } +impl Ord for (A, B, C, D, E) { + fn cmp(self, other: (A, B, C, D, E)) -> Ordering { + make_tuple_ord_body!(5u32) + } +} - result +impl Ord for (A, B, C, D, E, F) { + fn cmp(self, other: (A, B, C, D, E, F)) -> Ordering { + make_tuple_ord_body!(6u32) } } -impl Ord for (A, B, C, D, E) -where - A: Ord, - B: Ord, - C: Ord, - D: Ord, - E: Ord, -{ - fn cmp(self, other: (A, B, C, D, E)) -> Ordering { - let mut result = self.0.cmp(other.0); +impl Ord for (A, B, C, D, E, F, G) { + fn cmp(self, other: (A, B, C, D, E, F, G)) -> Ordering { + make_tuple_ord_body!(7u32) + } +} - if result == Ordering::equal() { - result = self.1.cmp(other.1); - } +impl Ord for (A, B, C, D, E, F, G, H) { + fn cmp(self, other: (A, B, C, D, E, F, G, H)) -> Ordering { + make_tuple_ord_body!(8u32) + } +} - if result == Ordering::equal() { - result = self.2.cmp(other.2); - } +impl Ord for (A, B, C, D, E, F, G, H, I) { + fn cmp(self, other: (A, B, C, D, E, F, G, H, I)) -> Ordering { + make_tuple_ord_body!(9u32) + } +} - if result == Ordering::equal() { - result = self.3.cmp(other.3); - } +impl Ord for (A, B, C, D, E, F, G, H, I, J) { + fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J)) -> Ordering { + make_tuple_ord_body!(10u32) + } +} - if result == Ordering::equal() { - result = self.4.cmp(other.4); - } +impl Ord for (A, B, C, D, E, F, G, H, I, J, K) { + fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J, K)) -> Ordering { + make_tuple_ord_body!(11u32) + } +} - result +impl Ord for (A, B, C, D, E, F, G, H, I, J, K, L) { + fn cmp(self, other: (A, B, C, D, E, F, G, H, I, J, K, L)) -> Ordering { + make_tuple_ord_body!(12u32) } } -// Compares and returns the maximum of two values. -// -// Returns the second argument if the comparison determines them to be equal. -// -// # Examples -// -// ``` -// use std::cmp; -// -// assert_eq(cmp::max(1, 2), 2); -// assert_eq(cmp::max(2, 2), 2); -// ``` +/// Compares and returns the maximum of two values. +/// +/// Returns the second argument if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// use std::cmp; +/// +/// assert_eq(cmp::max(1, 2), 2); +/// assert_eq(cmp::max(2, 2), 2); +/// ``` pub fn max(v1: T, v2: T) -> T where T: Ord, @@ -533,18 +547,18 @@ where } } -// Compares and returns the minimum of two values. -// -// Returns the first argument if the comparison determines them to be equal. -// -// # Examples -// -// ``` -// use std::cmp; -// -// assert_eq(cmp::min(1, 2), 1); -// assert_eq(cmp::min(2, 2), 2); -// ``` +/// Compares and returns the minimum of two values. +/// +/// Returns the first argument if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// use std::cmp; +/// +/// assert_eq(cmp::min(1, 2), 1); +/// assert_eq(cmp::min(2, 2), 2); +/// ``` pub fn min(v1: T, v2: T) -> T where T: Ord, diff --git a/stdlib/src/collections/bounded_vec.nr b/stdlib/src/collections/bounded_vec.nr index 3726480c..aceb66ee 100644 --- a/stdlib/src/collections/bounded_vec.nr +++ b/stdlib/src/collections/bounded_vec.nr @@ -83,7 +83,7 @@ impl BoundedVec { /// assert(first != last); /// } /// ``` - pub fn get(self, index: u32) -> T { + pub fn get(&self, index: u32) -> T { assert(index < self.len, "Attempted to read past end of BoundedVec"); self.get_unchecked(index) } @@ -107,7 +107,7 @@ impl BoundedVec { /// first + second + third /// } /// ``` - pub fn get_unchecked(self, index: u32) -> T { + pub fn get_unchecked(&self, index: u32) -> T { self.storage[index] } @@ -209,7 +209,7 @@ impl BoundedVec { /// let _ = v.pop(); /// assert(v.len() == 2); /// ``` - pub fn len(self) -> u32 { + pub fn len(&self) -> u32 { self.len } @@ -225,7 +225,7 @@ impl BoundedVec { /// v.push(10); /// assert(v.max_len() == 5); /// ``` - pub fn max_len(_self: BoundedVec) -> u32 { + pub fn max_len(_self: &BoundedVec) -> u32 { MaxLen } @@ -324,9 +324,40 @@ impl BoundedVec { self.storage[self.len + i] = vec.get_unchecked(i); } } else { - for i in 0..Len { - if i < append_len { - self.storage[self.len + i] = vec.get_unchecked(i); + // The source vector can be longer than the destination, or vice versa; + // regardless we will only ever be able to read or write whichever is + // the shorter max length of the two. We asserted that the actual content fits, + // but the capacity of the source vector could be higher. + let max = crate::cmp::min(Len, MaxLen); + + // Save the last item in case we have to do a fixup on an already full array. + let last = if MaxLen > 0 { + self.storage[MaxLen - 1] + } else { + crate::mem::zeroed() + }; + + for src in 0..max { + // Since we are iterating to the static capacity of the arrays, + // the destination could be out of bounds. If that's the case, + // overwrite the last item, which we'll fixup in the end. + // NB using cmp::min resulted in more opcodes here. + let mut dst = self.len + src; + if dst >= MaxLen { dst = MaxLen - 1; }; + // Assigning the source or zeroed to avoid having to merge arrays in SSA. + self.storage[dst] = if src < append_len { + vec.get_unchecked(src) + } else { + last + } + } + + // Fixup the last item if we have to. + if MaxLen > 0 { + self.storage[MaxLen - 1] = if (self.len + append_len == MaxLen) & (append_len > 0) { + vec.get_unchecked(append_len - 1) + } else { + last } } } @@ -419,7 +450,7 @@ impl BoundedVec { /// let expected = BoundedVec::from_array([2, 4, 6, 8]); /// assert_eq(result, expected); /// ``` - pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec { + pub fn map(&self, f: fn[Env](T) -> U) -> BoundedVec { let mut ret = BoundedVec::new(); ret.len = self.len(); @@ -429,8 +460,10 @@ impl BoundedVec { } } else { for i in 0..MaxLen { - if i < self.len() { - ret.storage[i] = f(self.get_unchecked(i)); + ret.storage[i] = if i < self.len() { + f(self.get_unchecked(i)) + } else { + crate::mem::zeroed() } } } @@ -450,7 +483,7 @@ impl BoundedVec { /// let expected = BoundedVec::from_array([2, 5, 8, 11]); /// assert_eq(result, expected); /// ``` - pub fn mapi(self, f: fn[Env](u32, T) -> U) -> BoundedVec { + pub fn mapi(&self, f: fn[Env](u32, T) -> U) -> BoundedVec { let mut ret = BoundedVec::new(); ret.len = self.len(); @@ -460,8 +493,10 @@ impl BoundedVec { } } else { for i in 0..MaxLen { - if i < self.len() { - ret.storage[i] = f(i, self.get_unchecked(i)); + ret.storage[i] = if i < self.len() { + f(i, self.get_unchecked(i)) + } else { + crate::mem::zeroed() } } } @@ -481,7 +516,7 @@ impl BoundedVec { /// let expected = BoundedVec::from_array([2, 4, 6, 8]); /// assert_eq(result, expected); /// ``` - pub fn for_each(self, f: fn[Env](T) -> ()) { + pub fn for_each(&self, f: fn[Env](T) -> ()) { if is_unconstrained() { for i in 0..self.len() { f(self.get_unchecked(i)); @@ -507,7 +542,7 @@ impl BoundedVec { /// let expected = BoundedVec::from_array([2, 5, 8, 11]); /// assert_eq(result, expected); /// ``` - pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) { + pub fn for_eachi(&self, f: fn[Env](u32, T) -> ()) { if is_unconstrained() { for i in 0..self.len() { f(i, self.get_unchecked(i)); @@ -1095,8 +1130,8 @@ mod bounded_vec_tests { #[test] fn empty_equality() { - let mut bounded_vec1: BoundedVec = BoundedVec::new(); - let mut bounded_vec2: BoundedVec = BoundedVec::new(); + let bounded_vec1: BoundedVec = BoundedVec::new(); + let bounded_vec2: BoundedVec = BoundedVec::new(); assert_eq(bounded_vec1, bounded_vec2); } @@ -1238,19 +1273,109 @@ mod bounded_vec_tests { #[test] fn extend_from_bounded_vec() { + // The source deliberately has a higher capacity, + // to make sure we are not trying to assign out-of-bounds. let mut vec1: BoundedVec = BoundedVec::new(); - let mut vec2: BoundedVec = BoundedVec::new(); + let mut vec2: BoundedVec = BoundedVec::new(); + + vec1.push(1); + vec2.push(2); + vec2.push(3); + + vec1.extend_from_bounded_vec(vec2); + + assert_eq(vec1.len(), 3); + assert_eq(vec1.get(0), 1); + assert_eq(vec1.get(1), 2); + assert_eq(vec1.get(2), 3); + } + + #[test] + fn extend_from_bounded_vec_limit() { + // Capacity and contents chosen so the last item must be assigned to. + let mut vec1: BoundedVec = BoundedVec::new(); + let mut vec2: BoundedVec = BoundedVec::new(); vec1.push(1); vec2.push(2); + + vec1.extend_from_bounded_vec(vec2); + + assert_eq(vec1.len(), 2); + assert_eq(vec1.get(0), 1); + assert_eq(vec1.get(1), 2); + } + + #[test] + fn extend_from_bounded_vec_full_and_empty() { + // Capacity and contents chosen so the last item must be assigned to. + let mut vec1: BoundedVec = BoundedVec::new(); + let vec2: BoundedVec = BoundedVec::new(); + + vec1.push(1); + vec1.push(2); + + vec1.extend_from_bounded_vec(vec2); + + assert_eq(vec1.len(), 2); + assert_eq(vec1.get(0), 1); + assert_eq(vec1.get(1), 2); + } + + #[test] + fn extend_from_bounded_vec_zero_len() { + let mut vec1: BoundedVec = BoundedVec::new(); + let vec2: BoundedVec = BoundedVec::new(); + + vec1.extend_from_bounded_vec(vec2); + + assert_eq(vec1.len(), 0); + } + + #[test] + fn extend_from_bounded_vec_last_zeroed() { + let mut vec1: BoundedVec = BoundedVec::new(); + let mut vec2: BoundedVec = BoundedVec::new(); + + vec1.push(1); + vec1.push(2); vec2.push(3); vec1.extend_from_bounded_vec(vec2); assert_eq(vec1.len(), 3); + assert_eq(vec1.get_unchecked(3), 0); + } + + #[test] + fn extend_from_bounded_vec_empty_self() { + // self.len == 0 with Len > MaxLen: the loop doesn't reach + // the last storage slot, so the fixup must write it. + let mut vec1: BoundedVec = BoundedVec::new(); + let vec2: BoundedVec = BoundedVec::from_array([1, 2, 3]); + + vec1.extend_from_bounded_vec(vec2); + + assert_eq(vec1.len(), 3); + assert_eq(vec1.get(0), 1); + assert_eq(vec1.get(1), 2); + assert_eq(vec1.get(2), 3); + } + + #[test] + fn extend_from_bounded_vec_equal_capacity() { + // Len == MaxLen, fills to capacity. + let mut vec1: BoundedVec = BoundedVec::new(); + vec1.push(1); + let vec2: BoundedVec = BoundedVec::from_array([2, 3, 4]); + + vec1.extend_from_bounded_vec(vec2); + + assert_eq(vec1.len(), 4); assert_eq(vec1.get(0), 1); assert_eq(vec1.get(1), 2); assert_eq(vec1.get(2), 3); + assert_eq(vec1.get(3), 4); } #[test(should_fail_with = "extend_from_array out of bounds")] diff --git a/stdlib/src/collections/map.nr b/stdlib/src/collections/map.nr index f5c570af..c6c48790 100644 --- a/stdlib/src/collections/map.nr +++ b/stdlib/src/collections/map.nr @@ -64,11 +64,11 @@ impl Default for Slot { } impl Slot { - fn is_valid(self) -> bool { + fn is_valid(&self) -> bool { !self._is_deleted & self._is_present } - fn is_available(self) -> bool { + fn is_available(&self) -> bool { self._is_deleted | !self._is_present } @@ -142,7 +142,7 @@ impl HashMap { /// } /// ``` // docs:start:contains_key - pub fn contains_key(self, key: K) -> bool + pub fn contains_key(&self, key: K) -> bool where K: Hash + Eq, B: BuildHasher, @@ -165,7 +165,7 @@ impl HashMap { /// assert(map.is_empty()); /// ``` // docs:start:is_empty - pub fn is_empty(self) -> bool { + pub fn is_empty(&self) -> bool { // docs:end:is_empty self._len == 0 } @@ -189,7 +189,7 @@ impl HashMap { /// } /// ``` // docs:start:entries - pub fn entries(self) -> BoundedVec<(K, V), N> { + pub fn entries(&self) -> BoundedVec<(K, V), N> { // docs:end:entries let mut entries = BoundedVec::new(); @@ -227,7 +227,7 @@ impl HashMap { /// } /// ``` // docs:start:keys - pub fn keys(self) -> BoundedVec { + pub fn keys(&self) -> BoundedVec { // docs:end:keys let mut keys = BoundedVec::new(); @@ -263,7 +263,7 @@ impl HashMap { /// } /// ``` // docs:start:values - pub fn values(self) -> BoundedVec { + pub fn values(&self) -> BoundedVec { // docs:end:values let mut values = BoundedVec::new(); @@ -305,7 +305,7 @@ impl HashMap { B: BuildHasher, { // docs:end:iter_mut - let mut entries = self.entries(); + let entries = self.entries(); let mut new_map = HashMap::with_hasher(self._build_hasher); for i in 0..N { @@ -343,7 +343,7 @@ impl HashMap { B: BuildHasher, { // docs:end:iter_keys_mut - let mut entries = self.entries(); + let entries = self.entries(); let mut new_map = HashMap::with_hasher(self._build_hasher); for i in 0..N { @@ -424,7 +424,7 @@ impl HashMap { /// assert(map.len() == 2); /// ``` // docs:start:len - pub fn len(self) -> u32 { + pub fn len(&self) -> u32 { // docs:end:len self._len } @@ -446,7 +446,7 @@ impl HashMap { /// assert(empty_map.capacity() == 42); /// ``` // docs:start:capacity - pub fn capacity(_self: Self) -> u32 { + pub fn capacity(_self: &Self) -> u32 { // docs:end:capacity N } @@ -465,7 +465,7 @@ impl HashMap { /// } /// ``` // docs:start:get - pub fn get(self, key: K) -> Option + pub fn get(&self, key: K) -> Option where K: Eq + Hash, B: BuildHasher, @@ -587,14 +587,14 @@ impl HashMap { } // Apply HashMap's hasher onto key to obtain pre-hash for probing. - fn hash(self, key: K) -> u32 + fn hash(&self, key: K) -> u32 where K: Hash, B: BuildHasher, { let mut hasher = self._build_hasher.build_hasher(); key.hash(&mut hasher); - hasher.finish() as u32 + hasher.finish_ref() as u32 } // Probing scheme: quadratic function. @@ -613,7 +613,7 @@ impl HashMap { // we conduct cross-multiplication instead. // n / m >= MAX_LOAD_FACTOR_NUMERATOR / MAX_LOAD_FACTOR_DENOMINATOR // n * MAX_LOAD_FACTOR_DENOMINATOR >= m * MAX_LOAD_FACTOR_NUMERATOR - fn assert_load_factor(self) { + fn assert_load_factor(&self) { let lhs = self._len * MAX_LOAD_FACTOR_DENOMINATOR; let rhs = self._table.len() * MAX_LOAD_FACTOR_NUMERATOR; let exceeded = lhs >= rhs; diff --git a/stdlib/src/collections/mod.nr b/stdlib/src/collections/mod.nr index d11e9f2f..a5a15e87 100644 --- a/stdlib/src/collections/mod.nr +++ b/stdlib/src/collections/mod.nr @@ -1,4 +1,2 @@ -pub mod vec; pub mod bounded_vec; -pub mod map; pub mod umap; diff --git a/stdlib/src/collections/umap.nr b/stdlib/src/collections/umap.nr index 4db0d1d1..2319c888 100644 --- a/stdlib/src/collections/umap.nr +++ b/stdlib/src/collections/umap.nr @@ -45,14 +45,10 @@ impl Default for Slot { } impl Slot { - fn is_valid(self) -> bool { + fn is_valid(&self) -> bool { !self._is_deleted & self._is_present } - fn is_available(self) -> bool { - self._is_deleted | !self._is_present - } - fn set(&mut self, key: K, value: V) { self._key = key; self._value = value; @@ -72,7 +68,7 @@ impl Slot { // that if we have went that far without finding desired, // it is very unlikely to be after - performance will be heavily degraded. impl UHashMap { - // Creates a new instance of UHashMap with specified BuildHasher. + /// Creates a new instance of UHashMap with specified BuildHasher. // docs:start:with_hasher pub fn with_hasher(_build_hasher: B) -> Self where @@ -88,7 +84,6 @@ impl UHashMap { where B: BuildHasher, { - // docs:end:with_hasher let mut _table = [].as_vector(); for _ in 0..capacity { _table = _table.push_back(Slot::default()); @@ -97,7 +92,7 @@ impl UHashMap { Self { _table, _len, _build_hasher } } - // Clears the map, removing all key-value entries. + /// Clears the map, removing all key-value entries. // docs:start:clear pub fn clear(&mut self) { // docs:end:clear @@ -105,9 +100,9 @@ impl UHashMap { self._len = 0; } - // Returns true if the map contains a value for the specified key. + /// Returns true if the map contains a value for the specified key. // docs:start:contains_key - pub fn contains_key(self, key: K) -> bool + pub fn contains_key(&self, key: K) -> bool where K: Hash + Eq, B: BuildHasher, @@ -117,21 +112,21 @@ impl UHashMap { unsafe { self.get(key) }.is_some() } - // Returns true if the map contains no elements. + /// Returns true if the map contains no elements. // docs:start:is_empty - pub fn is_empty(self) -> bool { + pub fn is_empty(&self) -> bool { // docs:end:is_empty self._len == 0 } - // Returns a BoundedVec of all valid entries in this UHashMap. - // The length of the returned vector will always match the length of this UHashMap. + /// Returns a vector of all valid entries in this UHashMap. + /// The length of the returned vector will always match the length of this UHashMap. // docs:start:entries - pub fn entries(self) -> [(K, V)] { + pub fn entries(&self) -> [(K, V)] { // docs:end:entries let mut entries = [].as_vector(); - for slot in self._table { + for slot in &self._table { if slot.is_valid() { // SAFETY: slot.is_valid() should ensure there is a valid key-value pairing here entries = entries.push_back((slot._key, slot._value)); @@ -147,14 +142,14 @@ impl UHashMap { entries } - // Returns a BoundedVec containing all the keys within this UHashMap. - // The length of the returned vector will always match the length of this UHashMap. + /// Returns a vector containing all the keys within this UHashMap. + /// The length of the returned vector will always match the length of this UHashMap. // docs:start:keys - pub fn keys(self) -> [K] { + pub fn keys(&self) -> [K] { // docs:end:keys let mut keys = [].as_vector(); - for slot in self._table { + for slot in &self._table { if slot.is_valid() { keys = keys.push_back(slot._key); } @@ -169,14 +164,14 @@ impl UHashMap { keys } - // Returns a BoundedVec containing all the values within this UHashMap. - // The length of the returned vector will always match the length of this UHashMap. + /// Returns a vector containing all the values within this UHashMap. + /// The length of the returned vector will always match the length of this UHashMap. // docs:start:values - pub fn values(self) -> [V] { + pub fn values(&self) -> [V] { // docs:end:values let mut values = [].as_vector(); - for slot in self._table { + for slot in &self._table { if slot.is_valid() { values = values.push_back(slot._value); } @@ -191,7 +186,7 @@ impl UHashMap { values } - // For each key-value entry applies mutator function. + /// For each key-value entry applies mutator function. // docs:start:iter_mut pub unconstrained fn iter_mut(&mut self, f: fn(K, V) -> (K, V)) where @@ -199,7 +194,7 @@ impl UHashMap { B: BuildHasher, { // docs:end:iter_mut - let mut entries = self.entries(); + let entries = self.entries(); let mut new_map = UHashMap::with_hasher(self._build_hasher); for entry in entries { @@ -207,11 +202,11 @@ impl UHashMap { new_map.insert(key, value); } - self._table = new_map._table; self._len = new_map._len; + self._table = new_map._table; } - // For each key applies mutator function. + /// For each key applies mutator function. // docs:start:iter_keys_mut pub unconstrained fn iter_keys_mut(&mut self, f: fn(K) -> K) where @@ -219,7 +214,7 @@ impl UHashMap { B: BuildHasher, { // docs:end:iter_keys_mut - let mut entries = self.entries(); + let entries = self.entries(); let mut new_map = UHashMap::with_hasher(self._build_hasher); for entry in entries { @@ -227,11 +222,13 @@ impl UHashMap { new_map.insert(key, value); } - self._table = new_map._table; self._len = new_map._len; + // The ownership pass being unsophisticated means we avoid a clone if we + // set the table after the len instead of before + self._table = new_map._table; } - // For each value applies mutator function. + /// For each value applies mutator function. // docs:start:iter_values_mut pub fn iter_values_mut(&mut self, f: fn(V) -> V) { // docs:end:iter_values_mut @@ -244,7 +241,7 @@ impl UHashMap { } } - // Retains only the elements specified by the predicate. + /// Retains only the elements specified by the predicate. // docs:start:retain pub fn retain(&mut self, f: fn(K, V) -> bool) { // docs:end:retain @@ -260,23 +257,23 @@ impl UHashMap { } } - // Amount of active key-value entries. + /// Amount of active key-value entries. // docs:start:len - pub fn len(self) -> u32 { + pub fn len(&self) -> u32 { // docs:end:len self._len } - // Get the current capacity of the inner table. + /// Get the current capacity of the inner table. // docs:start:capacity - pub fn capacity(self: Self) -> u32 { + pub fn capacity(&self) -> u32 { // docs:end:capacity self._table.len() } - // Get the value by key. If it does not exist, returns none(). + /// Get the value by key. If it does not exist, returns none(). // docs:start:get - pub unconstrained fn get(self, key: K) -> Option + pub unconstrained fn get(&self, key: K) -> Option where K: Eq + Hash, B: BuildHasher, @@ -302,7 +299,7 @@ impl UHashMap { result } - // Insert key-value entry. In case key was already present, value is overridden. + /// Insert key-value entry. In case key was already present, value is overridden. // docs:start:insert pub unconstrained fn insert(&mut self, key: K, value: V) where @@ -313,28 +310,44 @@ impl UHashMap { self.try_resize(); let hash = self.hash(key); + let mut insert_index: u32 = 0; + let mut increment_length = false; + let mut found_deleted_candidate = false; for attempt in 0..self._table.len() { - let index = self.linear_probe(hash, attempt as u32); - let mut slot = self._table[index]; - let mut insert = false; + let index = self.linear_probe(hash, attempt); + let slot = self._table[index]; - // Either marked as deleted or has unset key-value. - if slot.is_available() { - insert = true; - self._len += 1; - } else { + if slot.is_valid() { if slot._key == key { - insert = true; + // Key exists: update in place without changing length. + insert_index = index; + break; } - } - - if insert { - slot.set(key, value); - self._table[index] = slot; + } else if slot._is_deleted { + // Deleted slot: remember as candidate but keep probing for existing key. + if !found_deleted_candidate { + insert_index = index; + found_deleted_candidate = true; + } + } else { + // Empty slot: key cannot exist beyond this point. + // Insert at a deleted slot, if we found one previously, or at the current slot. + if !found_deleted_candidate { + insert_index = index; + } + increment_length = true; break; } } + + let mut s = self._table[insert_index]; + s.set(key, value); + self._table[insert_index] = s; + + if increment_length { + self._len += 1; + } } unconstrained fn try_resize(&mut self) @@ -353,7 +366,7 @@ impl UHashMap { } } - // Removes a key-value entry. If key is not present, UHashMap remains unchanged. + /// Removes a key-value entry. If key is not present, UHashMap remains unchanged. // docs:start:remove pub unconstrained fn remove(&mut self, key: K) where @@ -379,22 +392,20 @@ impl UHashMap { } } - // Apply UHashMap's hasher onto key to obtain pre-hash for probing. - fn hash(self, key: K) -> u32 + /// Apply UHashMap's hasher onto key to obtain pre-hash for probing. + fn hash(&self, key: K) -> u32 where K: Hash, B: BuildHasher, { let mut hasher = self._build_hasher.build_hasher(); key.hash(&mut hasher); - hasher.finish() as u32 + hasher.finish_ref() as u32 } - // Probing scheme: quadratic function. - // We use 0.5 constant near variadic attempt and attempt^2 monomials. - // This ensures good uniformity of distribution for table sizes - // equal to prime numbers or powers of two. - fn linear_probe(self: Self, hash: u32, attempt: u32) -> u32 { + /// Probing scheme: linear probing. + /// Each attempt increments the index by one, wrapping around the table. + fn linear_probe(&self, hash: u32, attempt: u32) -> u32 { (hash + attempt) % self._table.len() } } @@ -447,3 +458,25 @@ where UHashMap::with_hasher(B::default()) } } + +mod test { + use crate::hash::BuildHasherDefault; + use crate::hash::poseidon2::Poseidon2Hasher; + use super::UHashMap; + + #[test] + unconstrained fn test_no_duplicate_keys_after_deletion_and_insertion() { + // The capacity and keys used here, with the Poseidon2Hasher, have the keys 5 and 8 end up in slot 0. + let mut map = UHashMap::>::with_hasher_and_capacity( + BuildHasherDefault:: {}, + 8, + ); + map.insert(5, 5); + map.insert(8, 8); + map.remove(5); + map.insert(8, 9); + + assert_eq(map.entries(), @[(8, 9)]); + assert_eq(map.keys(), @[8]); + } +} diff --git a/stdlib/src/collections/vec.nr b/stdlib/src/collections/vec.nr deleted file mode 100644 index 6ce134fa..00000000 --- a/stdlib/src/collections/vec.nr +++ /dev/null @@ -1,371 +0,0 @@ -pub struct Vec { - pub(crate) vector: [T], -} -// A mutable vector type implemented as a wrapper around immutable vectors. -// A separate type is technically not needed but helps differentiate which operations are mutable. -impl Vec { - #[deprecated("std::collections::vec::Vec is deprecated, use the built-in vector type instead")] - pub fn new() -> Self { - Self { vector: [].as_vector() } - } - - // Create a Vec containing each element from the given vector. - // Mutations to the resulting Vec will not affect the original vector. - #[deprecated("std::collections::vec::Vec is deprecated, use the built-in vector type instead")] - pub fn from_vector(vector: [T]) -> Self { - Self { vector } - } - - /// Get an element from the vector at the given index. - /// Panics if the given index - /// points beyond the end of the vector. - #[deprecated("std::collections::vec::Vec is deprecated, use the built-in vector type instead")] - pub fn get(self, index: u32) -> T { - self.vector[index] - } - - /// Write an element to the vector at the given index. - /// Panics if the given index points beyond the end of the vector (`self.len()`). - #[deprecated("std::collections::vec::Vec is deprecated, use the built-in vector type instead")] - pub fn set(&mut self, index: u32, value: T) { - self.vector[index] = value; - } - - /// Push a new element to the end of the vector, returning a - /// new vector with a length one greater than the - /// original unmodified vector. - #[deprecated("std::collections::vec::Vec is deprecated, use the built-in vector type instead")] - pub fn push(&mut self, elem: T) { - self.vector = self.vector.push_back(elem); - } - - /// Pop an element from the end of the given vector, returning - /// a new vector with a length of one less than the given vector, - /// as well as the popped element. - /// Panics if the given vector's length is zero. - #[deprecated("std::collections::vec::Vec is deprecated, use the built-in vector type instead")] - pub fn pop(&mut self) -> T { - let (popped_vector, last_elem) = self.vector.pop_back(); - self.vector = popped_vector; - last_elem - } - - /// Insert an element at a specified index, shifting all elements - /// after it to the right - #[deprecated("std::collections::vec::Vec is deprecated, use the built-in vector type instead")] - pub fn insert(&mut self, index: u32, elem: T) { - self.vector = self.vector.insert(index, elem); - } - - /// Remove an element at a specified index, shifting all elements - /// after it to the left, returning the removed element - #[deprecated("std::collections::vec::Vec is deprecated, use the built-in vector type instead")] - pub fn remove(&mut self, index: u32) -> T { - let (new_vector, elem) = self.vector.remove(index); - self.vector = new_vector; - elem - } - - /// Returns the number of elements in the vector - #[deprecated("std::collections::vec::Vec is deprecated, use the built-in vector type instead")] - pub fn len(self) -> u32 { - self.vector.len() - } -} - -mod vec_tests { - mod new { - use crate::collections::vec::Vec; - - #[test] - fn creates_empty_vector() { - let vec: Vec = Vec::new(); - assert_eq(vec.len(), 0); - } - } - - mod from_vector { - use crate::collections::vec::Vec; - - #[test] - fn creates_vector_with_elements() { - let vector = [1, 2, 3, 4, 5].as_vector(); - let vec = Vec::from_vector(vector); - assert_eq(vec.len(), 5); - assert_eq(vec.vector, vector); - } - } - - mod get { - use crate::collections::vec::Vec; - - #[test] - fn retrieves_elements_correctly() { - let vec = Vec { vector: [10, 20, 30, 40, 50].as_vector() }; - - assert_eq(vec.get(0), 10); - assert_eq(vec.get(1), 20); - assert_eq(vec.get(2), 30); - assert_eq(vec.get(3), 40); - assert_eq(vec.get(4), 50); - } - - #[test(should_fail_with = "Index out of bounds")] - fn panics_on_out_of_bounds() { - let vec = Vec { vector: [1, 2, 3].as_vector() }; - let _ = vec.get(3); - } - } - - mod set { - use crate::collections::vec::Vec; - - #[test] - fn updates_values_properly() { - let mut vec = Vec { vector: [0, 0, 0, 0, 0].as_vector() }; - - vec.set(0, 42); - assert_eq(vec.vector, [42, 0, 0, 0, 0].as_vector()); - - vec.set(1, 43); - assert_eq(vec.vector, [42, 43, 0, 0, 0].as_vector()); - - vec.set(2, 44); - assert_eq(vec.vector, [42, 43, 44, 0, 0].as_vector()); - - vec.set(1, 10); - assert_eq(vec.vector, [42, 10, 44, 0, 0].as_vector()); - - vec.set(0, 0); - assert_eq(vec.vector, [0, 10, 44, 0, 0].as_vector()); - } - - #[test(should_fail_with = "Index out of bounds")] - fn panics_when_writing_elements_past_end_of_vec() { - let mut vec = Vec::new(); - vec.set(0, 42); - - let _ = vec.get(0); - } - } - - mod push { - use crate::collections::vec::Vec; - - #[test] - fn adds_element_to_end() { - let mut vec = Vec { vector: [1, 2, 3].as_vector() }; - let original_len = vec.len(); - - vec.push(4); - - assert_eq(vec.len(), original_len + 1); - assert_eq(vec.get(3), 4); - } - - #[test] - fn on_empty_vector() { - let mut vec = Vec::new(); - vec.push(42); - - assert_eq(vec.len(), 1); - assert_eq(vec.get(0), 42); - } - } - - mod pop { - use crate::collections::vec::Vec; - - #[test] - fn removes_last_element() { - let mut vec = Vec { vector: [1, 2, 3, 4, 5].as_vector() }; - let original_len = vec.len(); - - let popped = vec.pop(); - - assert_eq(popped, 5); - assert_eq(vec.len(), original_len - 1); - assert_eq(vec.get(3), 4); - } - - #[test(should_fail_with = "Index out of bounds")] - fn on_empty_vector_panics() { - let mut vec: Vec = Vec::new(); - let _ = vec.pop(); - } - } - - mod insert { - use crate::collections::vec::Vec; - - #[test] - fn at_beginning() { - let mut vec = Vec { vector: [1, 2, 3].as_vector() }; - vec.insert(0, 0); - - assert_eq(vec.len(), 4); - assert_eq(vec.get(0), 0); - assert_eq(vec.get(1), 1); - assert_eq(vec.get(2), 2); - assert_eq(vec.get(3), 3); - } - - #[test] - fn at_middle() { - let mut vec = Vec { vector: [1, 2, 4, 5].as_vector() }; - vec.insert(2, 3); - - assert_eq(vec.len(), 5); - assert_eq(vec.get(0), 1); - assert_eq(vec.get(1), 2); - assert_eq(vec.get(2), 3); - assert_eq(vec.get(3), 4); - assert_eq(vec.get(4), 5); - } - - #[test] - fn at_end() { - let mut vec = Vec { vector: [1, 2, 3].as_vector() }; - vec.insert(3, 4); - - assert_eq(vec.len(), 4); - assert_eq(vec.get(0), 1); - assert_eq(vec.get(1), 2); - assert_eq(vec.get(2), 3); - assert_eq(vec.get(3), 4); - } - - #[test(should_fail_with = "Index out of bounds")] - fn beyond_length_panics() { - let mut vec = Vec { vector: [1, 2, 3].as_vector() }; - vec.insert(4, 5); - } - } - - mod remove { - use crate::collections::vec::Vec; - - #[test] - fn from_beginning() { - let mut vec = Vec { vector: [0, 1, 2, 3, 4].as_vector() }; - let removed = vec.remove(0); - - assert_eq(removed, 0); - assert_eq(vec.len(), 4); - assert_eq(vec.get(0), 1); - assert_eq(vec.get(1), 2); - assert_eq(vec.get(2), 3); - assert_eq(vec.get(3), 4); - } - - #[test] - fn from_middle() { - let mut vec = Vec { vector: [1, 2, 3, 4, 5].as_vector() }; - let removed = vec.remove(2); - - assert_eq(removed, 3); - assert_eq(vec.len(), 4); - assert_eq(vec.get(0), 1); - assert_eq(vec.get(1), 2); - assert_eq(vec.get(2), 4); - assert_eq(vec.get(3), 5); - } - - #[test] - fn from_end() { - let mut vec = Vec { vector: [1, 2, 3, 4, 5].as_vector() }; - let removed = vec.remove(4); - - assert_eq(removed, 5); - assert_eq(vec.len(), 4); - assert_eq(vec.get(0), 1); - assert_eq(vec.get(1), 2); - assert_eq(vec.get(2), 3); - assert_eq(vec.get(3), 4); - } - - #[test(should_fail_with = "Index out of bounds")] - fn beyond_length_panics() { - let mut vec = Vec { vector: [1, 2, 3].as_vector() }; - let _ = vec.remove(3); - } - } - - mod len { - use crate::collections::vec::Vec; - - #[test] - fn returns_correct_length() { - let empty_vec: Vec = Vec::new(); - assert_eq(empty_vec.len(), 0); - - let single_vec = Vec { vector: [42].as_vector() }; - assert_eq(single_vec.len(), 1); - - let multi_vec = Vec { vector: [1, 2, 3, 4, 5].as_vector() }; - assert_eq(multi_vec.len(), 5); - } - } - - mod vec_integration { - use crate::collections::vec::Vec; - - #[test] - fn multiple_operations_chain_correctly() { - let mut vec = Vec::new(); - - // push several elements - vec.push(1); - vec.push(2); - vec.push(3); - assert_eq(vec.len(), 3); - assert_eq(vec.get(0), 1); - assert_eq(vec.get(1), 2); - assert_eq(vec.get(2), 3); - - // insert in middle - vec.insert(1, 10); - assert_eq(vec.len(), 4); - assert_eq(vec.get(0), 1); - assert_eq(vec.get(1), 10); - assert_eq(vec.get(2), 2); - assert_eq(vec.get(3), 3); - - // set elements - vec.set(0, 100); - vec.set(2, 200); - assert_eq(vec.get(0), 100); - assert_eq(vec.get(2), 200); - - // remove element - let removed = vec.remove(1); - assert_eq(removed, 10); - assert_eq(vec.len(), 3); - assert_eq(vec.get(0), 100); - assert_eq(vec.get(1), 200); - assert_eq(vec.get(2), 3); - - // pop element - let popped = vec.pop(); - assert_eq(popped, 3); - assert_eq(vec.len(), 2); - } - - #[test] - fn vector_with_custom_types() { - let mut vec = Vec { vector: [true, false, true].as_vector() }; - - assert_eq(vec.len(), 3); - assert_eq(vec.get(0), true); - assert_eq(vec.get(1), false); - assert_eq(vec.get(2), true); - - vec.set(1, true); - assert_eq(vec.get(1), true); - - vec.push(false); - assert_eq(vec.len(), 4); - assert_eq(vec.get(3), false); - } - } -} diff --git a/stdlib/src/compat.nr b/stdlib/src/compat.nr index 216f948f..4c651430 100644 --- a/stdlib/src/compat.nr +++ b/stdlib/src/compat.nr @@ -4,6 +4,7 @@ comptime global BN254_MODULUS_BE_BYTES: [u8] = [ ] .as_vector(); +/// True if the current field is bn254 pub fn is_bn254() -> bool { comptime { // We can't use the `Eq` trait here due to limitations on calling non-comptime functions diff --git a/stdlib/src/convert.nr b/stdlib/src/convert.nr index b89e9482..b6f13a65 100644 --- a/stdlib/src/convert.nr +++ b/stdlib/src/convert.nr @@ -1,3 +1,4 @@ +/// Create a new `Self` value from the given `T` value // docs:start:from-trait pub trait From { fn from(input: T) -> Self; @@ -10,6 +11,7 @@ impl From for T { } } +/// Convert a `Self` value into a `T` value // docs:start:into-trait pub trait Into { fn into(self) -> T; diff --git a/stdlib/src/default.nr b/stdlib/src/default.nr index 021606a7..44a61ac9 100644 --- a/stdlib/src/default.nr +++ b/stdlib/src/default.nr @@ -1,5 +1,8 @@ use crate::meta::derive_via; +/// Return an implementation-defined default value for the given type. +/// This is most often a zeroed value or an empty container, but there +/// are no actual restrictions on what an implementation could return. #[derive_via(derive_default)] // docs:start:default-trait pub trait Default { @@ -21,11 +24,6 @@ impl Default for Field { } } -impl Default for u1 { - fn default() -> u1 { - 0 - } -} impl Default for u8 { fn default() -> u8 { 0 diff --git a/stdlib/src/ecdsa_secp256r1.nr b/stdlib/src/ecdsa_secp256r1.nr index 1661b896..e0cb005e 100644 --- a/stdlib/src/ecdsa_secp256r1.nr +++ b/stdlib/src/ecdsa_secp256r1.nr @@ -1,4 +1,20 @@ +/// Verifier for ECDSA Secp256r1 signatures. // docs:start:ecdsa_secp256r1 +/// Verifies a ECDSA signature over the secp256r1 curve. +/// - inputs: +/// - x coordinate of public key as 32 bytes +/// - y coordinate of public key as 32 bytes +/// - the signature, as a 64 bytes array +/// The signature internally will be represented as `(r, s)`, +/// where `r` and `s` are fixed-sized big endian scalar values. +/// As the `secp256r1` has a 256-bit modulus, we have a 64 byte signature +/// while `r` and `s` will both be 32 bytes. +/// We expect `s` to be normalized. This means given the curve's order, +/// `s` should be less than or equal to `order / 2`. +/// This is done to prevent malleability. +/// For more context regarding malleability you can reference BIP 0062. +/// - the hash of the message, as a vector of bytes +/// - output: false for failure and true for success pub fn verify_signature( public_key_x: [u8; 32], public_key_y: [u8; 32], diff --git a/stdlib/src/embedded_curve_ops.nr b/stdlib/src/embedded_curve_ops.nr index 55a769c1..515ab32b 100644 --- a/stdlib/src/embedded_curve_ops.nr +++ b/stdlib/src/embedded_curve_ops.nr @@ -4,11 +4,10 @@ use crate::ops::arith::{Add, Neg, Sub}; /// A point on the embedded elliptic curve /// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field. -/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false. +/// x and y denotes the Weierstrass coordinates of the point. pub struct EmbeddedCurvePoint { pub x: Field, pub y: Field, - pub is_infinite: bool, } impl EmbeddedCurvePoint { @@ -20,7 +19,7 @@ impl EmbeddedCurvePoint { /// Returns the null element of the curve; 'the point at infinity' pub fn point_at_infinity() -> EmbeddedCurvePoint { - EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true } + EmbeddedCurvePoint { x: 0, y: 0 } } /// Returns the curve's generator point. @@ -29,9 +28,13 @@ impl EmbeddedCurvePoint { EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16) - is_infinite: false, } } + + /// True if this point is the point at infinity + pub fn is_infinite(self) -> bool { + (self.x == 0) & (self.y == 0) + } } impl Add for EmbeddedCurvePoint { @@ -52,15 +55,14 @@ impl Neg for EmbeddedCurvePoint { /// Negates a point P, i.e returns -P, by negating the y coordinate. /// If the point is at infinity, then the result is also at infinity. fn neg(self) -> EmbeddedCurvePoint { - EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite } + EmbeddedCurvePoint { x: self.x, y: -self.y } } } impl Eq for EmbeddedCurvePoint { /// Checks whether two points are equal fn eq(self: Self, b: EmbeddedCurvePoint) -> bool { - (self.is_infinite & b.is_infinite) - | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y)) + (self.x == b.x) & (self.y == b.y) } } @@ -69,12 +71,8 @@ impl Hash for EmbeddedCurvePoint { where H: crate::hash::Hasher, { - if self.is_infinite { - self.is_infinite.hash(state); - } else { - self.x.hash(state); - self.y.hash(state); - } + self.x.hash(state); + self.y.hash(state); } } @@ -87,17 +85,19 @@ pub struct EmbeddedCurveScalar { } impl EmbeddedCurveScalar { + /// Create a new scalar using the provided (lo, hi) pair pub fn new(lo: Field, hi: Field) -> Self { EmbeddedCurveScalar { lo, hi } } + /// Create a scalar from the given bn254 field value #[field(bn254)] pub fn from_field(scalar: Field) -> EmbeddedCurveScalar { let (a, b) = crate::field::bn254::decompose(scalar); EmbeddedCurveScalar { lo: a, hi: b } } - //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value + /// Take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value #[field(bn254)] pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar { let mut v = 1; @@ -129,16 +129,15 @@ impl Hash for EmbeddedCurveScalar { } } -// Computes a multi scalar multiplication over the embedded curve. -// For bn254, We have Grumpkin and Baby JubJub. -// For bls12-381, we have JubJub and Bandersnatch. -// -// The embedded curve being used is decided by the -// underlying proof system. -// -// IMPORTANT: Prefer `multi_scalar_mul()` over repeated `embedded_curve_add()` -// for adding multiple points. This is significantly more efficient. -// For adding exactly 2 points, use `embedded_curve_add()` directly. +/// Computes a multi scalar multiplication over the embedded curve. +/// For bn254, We have Grumpkin. +/// +/// The embedded curve being used is decided by the +/// underlying proof system. +/// +/// IMPORTANT: Prefer `multi_scalar_mul()` over repeated `embedded_curve_add()` +/// for adding multiple points. This is significantly more efficient. +/// For adding exactly 2 points, use `embedded_curve_add()` directly. // docs:start:multi_scalar_mul pub fn multi_scalar_mul( points: [EmbeddedCurvePoint; N], @@ -149,13 +148,6 @@ pub fn multi_scalar_mul( multi_scalar_mul_array_return(points, scalars, true)[0] } -#[foreign(multi_scalar_mul)] -pub(crate) fn multi_scalar_mul_array_return( - points: [EmbeddedCurvePoint; N], - scalars: [EmbeddedCurveScalar; N], - predicate: bool, -) -> [EmbeddedCurvePoint; 1] {} - // docs:start:fixed_base_scalar_mul pub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint // docs:end:fixed_base_scalar_mul @@ -163,6 +155,13 @@ pub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar]) } +#[foreign(multi_scalar_mul)] +pub(crate) fn multi_scalar_mul_array_return( + points: [EmbeddedCurvePoint; N], + scalars: [EmbeddedCurveScalar; N], + predicate: bool, +) -> [EmbeddedCurvePoint; 1] {} + /// Elliptic curve addition /// IMPORTANT: this function is expected to perform a full addition in order to handle all corner cases: /// - points on the curve @@ -175,18 +174,7 @@ pub fn embedded_curve_add( point2: EmbeddedCurvePoint, ) -> EmbeddedCurvePoint { // docs:end:embedded_curve_add - if crate::runtime::is_unconstrained() { - // avoid calling the black box function for trivial cases - if point1.is_infinite { - point2 - } else if point2.is_infinite { - point1 - } else { - embedded_curve_add_inner(point1, point2) - } - } else { - embedded_curve_add_inner(point1, point2) - } + embedded_curve_add_array_return(point1, point2, true)[0] } #[foreign(embedded_curve_add)] @@ -195,11 +183,3 @@ fn embedded_curve_add_array_return( _point2: EmbeddedCurvePoint, _predicate: bool, ) -> [EmbeddedCurvePoint; 1] {} - -/// EC addition wrapper for the foreign function -fn embedded_curve_add_inner( - point1: EmbeddedCurvePoint, - point2: EmbeddedCurvePoint, -) -> EmbeddedCurvePoint { - embedded_curve_add_array_return(point1, point2, true)[0] -} diff --git a/stdlib/src/field/mod.nr b/stdlib/src/field/mod.nr index abf1d7e9..b7fe6dff 100644 --- a/stdlib/src/field/mod.nr +++ b/stdlib/src/field/mod.nr @@ -17,7 +17,7 @@ impl Field { __assert_max_bit_size(self, BIT_SIZE); } - /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array. + /// Decomposes `self` into its little endian bit decomposition as a `[bool; N]` array. /// This array will be zero padded should not all bits be necessary to represent `self`. /// /// # Failures @@ -27,7 +27,7 @@ impl Field { /// # Safety /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus. // docs:start:to_le_bits - pub fn to_le_bits(self: Self) -> [u1; N] { + pub fn to_le_bits(self: Self) -> [bool; N] { // docs:end:to_le_bits let bits = __to_le_bits(self); @@ -39,7 +39,7 @@ impl Field { for i in 0..N { if !ok { if (bits[N - 1 - i] != p[N - 1 - i]) { - assert(p[N - 1 - i] == 1); + assert(p[N - 1 - i]); ok = true; } } @@ -49,7 +49,7 @@ impl Field { bits } - /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array. + /// Decomposes `self` into its big endian bit decomposition as a `[bool; N]` array. /// This array will be zero padded should not all bits be necessary to represent `self`. /// /// # Failures @@ -59,7 +59,7 @@ impl Field { /// # Safety /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus. // docs:start:to_be_bits - pub fn to_be_bits(self: Self) -> [u1; N] { + pub fn to_be_bits(self: Self) -> [bool; N] { // docs:end:to_be_bits let bits = __to_be_bits(self); @@ -71,7 +71,7 @@ impl Field { for i in 0..N { if !ok { if (bits[i] != p[i]) { - assert(p[i] == 1); + assert(p[i]); ok = true; } } @@ -180,7 +180,7 @@ impl Field { // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits pub fn pow_32(self, exponent: Field) -> Field { let mut r: Field = 1; - let b: [u1; 32] = exponent.to_le_bits(); + let b: [bool; 32] = exponent.to_le_bits(); for i in 1..33 { r *= r; @@ -189,9 +189,9 @@ impl Field { r } - // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x `elem` {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. - pub fn sgn0(self) -> u1 { - self as u1 + // Parity of (prime) Field element, i.e. sgn0(x mod p) = false if x `elem` {0, ..., p-1} is even, otherwise sgn0(x mod p) = true. + pub fn sgn0(self) -> bool { + (self as u8) % 2 == 1 } pub fn lt(self, another: Field) -> bool { @@ -244,7 +244,7 @@ fn __to_le_radix(value: Field, radix: u32) -> [u8; N] {} #[builtin(to_be_radix)] fn __to_be_radix(value: Field, radix: u32) -> [u8; N] {} -/// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array. +/// Decomposes `self` into its little endian bit decomposition as a `[bool; N]` array. /// This array will be zero padded should not all bits be necessary to represent `self`. /// /// # Failures @@ -256,9 +256,9 @@ fn __to_be_radix(value: Field, radix: u32) -> [u8; N] {} /// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will /// wrap around due to overflow when verifying the decomposition. #[builtin(to_le_bits)] -fn __to_le_bits(value: Field) -> [u1; N] {} +fn __to_le_bits(value: Field) -> [bool; N] {} -/// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array. +/// Decomposes `self` into its big endian bit decomposition as a `[bool; N]` array. /// This array will be zero padded should not all bits be necessary to represent `self`. /// /// # Failures @@ -270,16 +270,16 @@ fn __to_le_bits(value: Field) -> [u1; N] {} /// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will /// wrap around due to overflow when verifying the decomposition. #[builtin(to_be_bits)] -fn __to_be_bits(value: Field) -> [u1; N] {} +fn __to_be_bits(value: Field) -> [bool; N] {} #[builtin(modulus_num_bits)] pub comptime fn modulus_num_bits() -> u64 {} #[builtin(modulus_be_bits)] -pub comptime fn modulus_be_bits() -> [u1] {} +pub comptime fn modulus_be_bits() -> [bool] {} #[builtin(modulus_le_bits)] -pub comptime fn modulus_le_bits() -> [u1] {} +pub comptime fn modulus_le_bits() -> [bool] {} #[builtin(modulus_be_bytes)] pub comptime fn modulus_be_bytes() -> [u8] {} @@ -347,8 +347,8 @@ mod tests { // docs:start:to_be_bits_example fn test_to_be_bits() { let field = 2; - let bits: [u1; 8] = field.to_be_bits(); - assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]); + let bits: [bool; 8] = field.to_be_bits(); + assert_eq(bits, [false, false, false, false, false, false, true, false]); } // docs:end:to_be_bits_example @@ -356,8 +356,8 @@ mod tests { // docs:start:to_le_bits_example fn test_to_le_bits() { let field = 2; - let bits: [u1; 8] = field.to_le_bits(); - assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]); + let bits: [bool; 8] = field.to_le_bits(); + assert_eq(bits, [false, true, false, false, false, false, false, false]); } // docs:end:to_le_bits_example @@ -492,8 +492,8 @@ mod tests { unconstrained fn test_large_field_values_unconstrained() { let large_field = 0xffffffffffffffff; - let bits: [u1; 64] = large_field.to_le_bits(); - assert_eq(bits[0], 1); + let bits: [bool; 64] = large_field.to_le_bits(); + assert_eq(bits[0], true); let bytes: [u8; 8] = large_field.to_le_bytes(); assert_eq(Field::from_le_bytes::<8>(bytes), large_field); @@ -506,8 +506,8 @@ mod tests { fn test_large_field_values() { let large_val = 0xffffffffffffffff; - let bits: [u1; 64] = large_val.to_le_bits(); - assert_eq(bits[0], 1); + let bits: [bool; 64] = large_val.to_le_bits(); + assert_eq(bits[0], true); let bytes: [u8; 8] = large_val.to_le_bytes(); assert_eq(Field::from_le_bytes::<8>(bytes), large_val); @@ -518,18 +518,18 @@ mod tests { #[test] fn test_decomposition_edge_cases() { - let zero_bits: [u1; 8] = 0.to_le_bits(); - assert_eq(zero_bits, [0; 8]); + let zero_bits: [bool; 8] = 0.to_le_bits(); + assert_eq(zero_bits, [false; 8]); let zero_bytes: [u8; 8] = 0.to_le_bytes(); assert_eq(zero_bytes, [0; 8]); - let one_bits: [u1; 8] = 1.to_le_bits(); - let expected: [u1; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; + let one_bits: [bool; 8] = 1.to_le_bits(); + let expected: [bool; 8] = [true, false, false, false, false, false, false, false]; assert_eq(one_bits, expected); - let pow2_bits: [u1; 8] = 4.to_le_bits(); - let expected: [u1; 8] = [0, 0, 1, 0, 0, 0, 0, 0]; + let pow2_bits: [bool; 8] = 4.to_le_bits(); + let expected: [bool; 8] = [false, false, true, false, false, false, false, false]; assert_eq(pow2_bits, expected); } @@ -550,22 +550,22 @@ mod tests { #[test] fn test_sgn0() { - assert_eq(0.sgn0(), 0); - assert_eq(2.sgn0(), 0); - assert_eq(4.sgn0(), 0); - assert_eq(100.sgn0(), 0); + assert_eq(0.sgn0(), false); + assert_eq(2.sgn0(), false); + assert_eq(4.sgn0(), false); + assert_eq(100.sgn0(), false); - assert_eq(1.sgn0(), 1); - assert_eq(3.sgn0(), 1); - assert_eq(5.sgn0(), 1); - assert_eq(101.sgn0(), 1); + assert_eq(1.sgn0(), true); + assert_eq(3.sgn0(), true); + assert_eq(5.sgn0(), true); + assert_eq(101.sgn0(), true); } #[test(should_fail_with = "Field failed to decompose into specified 8 limbs")] fn test_bit_decomposition_overflow() { // 8 bits can't represent large field values let large_val = 0x1000000000000000; - let _: [u1; 8] = large_val.to_le_bits(); + let _: [bool; 8] = large_val.to_le_bits(); } #[test(should_fail_with = "Field failed to decompose into specified 4 limbs")] @@ -659,7 +659,7 @@ mod tests { /// Convert a little endian bit array to a field element. /// If the provided bit array overflows the field modulus then the Field will silently wrap around. - fn from_le_bits(bits: [u1; N]) -> Field { + fn from_le_bits(bits: [bool; N]) -> Field { static_assert( N <= modulus_le_bits().len(), "N must be less than or equal to modulus_le_bits().len()", @@ -676,7 +676,7 @@ mod tests { /// Convert a big endian bit array to a field element. /// If the provided bit array overflows the field modulus then the Field will silently wrap around. - fn from_be_bits(bits: [u1; N]) -> Field { + fn from_be_bits(bits: [bool; N]) -> Field { let mut v = 1; let mut result = 0; @@ -691,40 +691,40 @@ mod tests { fn test_to_from_be_bits_bn254_edge_cases() { if crate::compat::is_bn254() { // checking that decrementing this bit produces the expected 254 BE bits for (modulus - 1) - let mut p_minus_1_bits: [u1; 254] = modulus_be_bits().as_array(); - assert(p_minus_1_bits[254 - 1] > 0); - p_minus_1_bits[254 - 1] -= 1; + let mut p_minus_1_bits: [bool; 254] = modulus_be_bits().as_array(); + assert(p_minus_1_bits[254 - 1]); + p_minus_1_bits[254 - 1] = false; let p_minus_1 = from_be_bits::<254>(p_minus_1_bits); assert_eq(p_minus_1 + 1, 0); // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits - let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_be_bits(); + let p_minus_1_converted_bits: [bool; 254] = p_minus_1.to_be_bits(); assert_eq(p_minus_1_converted_bits, p_minus_1_bits); // checking that incrementing this bit produces 254 BE bits for (modulus + 4) - let mut p_plus_4_bits: [u1; 254] = modulus_be_bits().as_array(); - assert(p_plus_4_bits[254 - 3] < 1); - p_plus_4_bits[254 - 3] += 1; + let mut p_plus_4_bits: [bool; 254] = modulus_be_bits().as_array(); + assert(!p_plus_4_bits[254 - 3]); + p_plus_4_bits[254 - 3] = true; let p_plus_4 = from_be_bits::<254>(p_plus_4_bits); assert_eq(p_plus_4, 4); // checking that converting p_plus_4 to 254 BE bits produces the same // bit set to 1 as p_plus_4_bits and otherwise zeroes - let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_be_bits(); - assert_eq(p_plus_4_converted_bits[254 - 3], 1); - p_plus_4_converted_bits[254 - 3] = 0; - assert_eq(p_plus_4_converted_bits, [0; 254]); + let mut p_plus_4_converted_bits: [bool; 254] = p_plus_4.to_be_bits(); + assert(p_plus_4_converted_bits[254 - 3]); + p_plus_4_converted_bits[254 - 3] = false; + assert_eq(p_plus_4_converted_bits, [false; 254]); // checking that Field::from_be_bits::<254> on the Field modulus produces 0 assert_eq(modulus_be_bits().len(), 254); let p = from_be_bits::<254>(modulus_be_bits().as_array()); assert_eq(p, 0); - // checking that converting 0 to 254 BE bytes produces 254 zeroes - let p_bits: [u1; 254] = 0.to_be_bits(); - assert_eq(p_bits, [0; 254]); + // checking that converting 0 to 254 BE bits produces 254 false values + let p_bits: [bool; 254] = 0.to_be_bits(); + assert_eq(p_bits, [false; 254]); } } @@ -732,40 +732,40 @@ mod tests { fn test_to_from_le_bits_bn254_edge_cases() { if crate::compat::is_bn254() { // checking that decrementing this bit produces the expected 254 LE bits for (modulus - 1) - let mut p_minus_1_bits: [u1; 254] = modulus_le_bits().as_array(); - assert(p_minus_1_bits[0] > 0); - p_minus_1_bits[0] -= 1; + let mut p_minus_1_bits: [bool; 254] = modulus_le_bits().as_array(); + assert(p_minus_1_bits[0]); + p_minus_1_bits[0] = false; let p_minus_1 = from_le_bits::<254>(p_minus_1_bits); assert_eq(p_minus_1 + 1, 0); // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits - let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_le_bits(); + let p_minus_1_converted_bits: [bool; 254] = p_minus_1.to_le_bits(); assert_eq(p_minus_1_converted_bits, p_minus_1_bits); // checking that incrementing this bit produces 254 LE bits for (modulus + 4) - let mut p_plus_4_bits: [u1; 254] = modulus_le_bits().as_array(); - assert(p_plus_4_bits[2] < 1); - p_plus_4_bits[2] += 1; + let mut p_plus_4_bits: [bool; 254] = modulus_le_bits().as_array(); + assert(!p_plus_4_bits[2]); + p_plus_4_bits[2] = true; let p_plus_4 = from_le_bits::<254>(p_plus_4_bits); assert_eq(p_plus_4, 4); // checking that converting p_plus_4 to 254 LE bits produces the same // bit set to 1 as p_plus_4_bits and otherwise zeroes - let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_le_bits(); - assert_eq(p_plus_4_converted_bits[2], 1); - p_plus_4_converted_bits[2] = 0; - assert_eq(p_plus_4_converted_bits, [0; 254]); + let mut p_plus_4_converted_bits: [bool; 254] = p_plus_4.to_le_bits(); + assert(p_plus_4_converted_bits[2]); + p_plus_4_converted_bits[2] = false; + assert_eq(p_plus_4_converted_bits, [false; 254]); // checking that Field::from_le_bits::<254> on the Field modulus produces 0 assert_eq(modulus_le_bits().len(), 254); let p = from_le_bits::<254>(modulus_le_bits().as_array()); assert_eq(p, 0); - // checking that converting 0 to 254 LE bytes produces 254 zeroes - let p_bits: [u1; 254] = 0.to_le_bits(); - assert_eq(p_bits, [0; 254]); + // checking that converting 0 to 254 LE bits produces 254 false values + let p_bits: [bool; 254] = 0.to_le_bits(); + assert_eq(p_bits, [false; 254]); } } } diff --git a/stdlib/src/hash/mod.nr b/stdlib/src/hash/mod.nr index 64368739..91976a6b 100644 --- a/stdlib/src/hash/mod.nr +++ b/stdlib/src/hash/mod.nr @@ -6,6 +6,10 @@ use crate::embedded_curve_ops::{ EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return, }; use crate::meta::derive_via; +use crate::static_assert; + +/// The size of the state accepted by the backend in `poseidon2_permutation`. +global POSEIDON2_CONFIG_STATE_SIZE: u32 = poseidon2_config_state_size(); #[foreign(sha256_compression)] // docs:start:sha256_compression @@ -61,8 +65,7 @@ pub fn pedersen_commitment_with_separator( ) -> EmbeddedCurvePoint { let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N]; for i in 0..N { - // we use the unsafe version because the multi_scalar_mul will constrain the scalars. - points[i] = from_field_unsafe(input[i]); + points[i] = EmbeddedCurveScalar::from_field(input[i]); } let generators = derive_generators("DEFAULT_DOMAIN_SEPARATOR".as_bytes(), separator); multi_scalar_mul(generators, points) @@ -85,7 +88,7 @@ pub fn pedersen_hash_with_separator(input: [Field; N], separator: u3 derive_generators("DEFAULT_DOMAIN_SEPARATOR".as_bytes(), separator); for i in 0..N { - scalars[i] = from_field_unsafe(input[i]); + scalars[i] = EmbeddedCurveScalar::from_field(input[i]); generators[i] = domain_generators[i]; } scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field }; @@ -114,35 +117,20 @@ fn __derive_generators( starting_index: u32, ) -> [EmbeddedCurvePoint; N] {} -#[field(bn254)] -// Decompose the input 'bn254 scalar' into two 128 bits limbs. -// It is called 'unsafe' because it does not assert the limbs are 128 bits -// Assuming the limbs are 128 bits: -// Assert the decomposition does not overflow the field size. -fn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar { - // Safety: xlo and xhi decomposition is checked below - let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) }; - // Check that the decomposition is correct - assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi); - // Check that the decomposition does not overflow the field size - let (a, b) = if xhi == crate::field::bn254::PHI { - (xlo, crate::field::bn254::PLO) - } else { - (xhi, crate::field::bn254::PHI) - }; - crate::field::bn254::assert_lt(a, b); - - EmbeddedCurveScalar { lo: xlo, hi: xhi } -} - -pub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] { - assert_eq(input.len(), state_len); +pub fn poseidon2_permutation(input: [Field; N]) -> [Field; N] { + static_assert( + N == POSEIDON2_CONFIG_STATE_SIZE, + f"the input length must equal the state size in the Poseidon2 config; expected {POSEIDON2_CONFIG_STATE_SIZE}, got {N}", + ); poseidon2_permutation_internal(input) } #[foreign(poseidon2_permutation)] fn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {} +#[foreign(poseidon2_config_state_size)] +comptime fn poseidon2_config_state_size() -> u32 {} + // Generic hashing support. // Partially ported and impacted by rust. @@ -175,6 +163,13 @@ comptime fn derive_hash(s: TypeDefinition) -> Quoted { pub trait Hasher { fn finish(self) -> Field; + /// Returns the hash value without consuming the hasher. + /// Override this for more efficient implementations that avoid copying. + /// TODO: deprecate finish() and replace it + fn finish_ref(&self) -> Field { + (*self).finish() + } + fn write(&mut self, input: Field); } @@ -216,15 +211,6 @@ impl Hash for Field { } } -impl Hash for u1 { - fn hash(self, state: &mut H) - where - H: Hasher, - { - H::write(state, self as Field); - } -} - impl Hash for u8 { fn hash(self, state: &mut H) where @@ -433,7 +419,6 @@ fn assert_pedersen() { EmbeddedCurvePoint { x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402, y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126, - is_infinite: false, }, ); @@ -446,7 +431,6 @@ fn assert_pedersen() { EmbeddedCurvePoint { x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753, y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778, - is_infinite: false, }, ); assert_eq( @@ -458,7 +442,6 @@ fn assert_pedersen() { EmbeddedCurvePoint { x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85, y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1, - is_infinite: false, }, ); assert_eq( @@ -470,7 +453,6 @@ fn assert_pedersen() { EmbeddedCurvePoint { x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9, y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014, - is_infinite: false, }, ); assert_eq( @@ -482,7 +464,6 @@ fn assert_pedersen() { EmbeddedCurvePoint { x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29, y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7, - is_infinite: false, }, ); assert_eq( @@ -494,7 +475,6 @@ fn assert_pedersen() { EmbeddedCurvePoint { x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697, y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb, - is_infinite: false, }, ); assert_eq( @@ -506,7 +486,6 @@ fn assert_pedersen() { EmbeddedCurvePoint { x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939, y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc, - is_infinite: false, }, ); assert_eq( @@ -518,7 +497,6 @@ fn assert_pedersen() { EmbeddedCurvePoint { x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443, y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77, - is_infinite: false, }, ); assert_eq( @@ -530,7 +508,6 @@ fn assert_pedersen() { EmbeddedCurvePoint { x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d, y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2, - is_infinite: false, }, ); assert_eq( @@ -542,7 +519,6 @@ fn assert_pedersen() { EmbeddedCurvePoint { x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c, y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245, - is_infinite: false, }, ); } diff --git a/stdlib/src/hash/poseidon2.nr b/stdlib/src/hash/poseidon2.nr index 559236c2..c790be36 100644 --- a/stdlib/src/hash/poseidon2.nr +++ b/stdlib/src/hash/poseidon2.nr @@ -1,7 +1,7 @@ use crate::default::Default; use crate::hash::Hasher; -comptime global RATE: u32 = 3; +global RATE: u32 = 3; pub(crate) struct Poseidon2 { cache: [Field; 3], @@ -32,7 +32,7 @@ impl Poseidon2 { self.state[i] += self.cache[i]; } } - self.state = crate::hash::poseidon2_permutation_internal(self.state); + self.state = crate::hash::poseidon2_permutation(self.state); } fn absorb(&mut self, input: Field) { @@ -89,6 +89,10 @@ pub(crate) struct Poseidon2Hasher { impl Hasher for Poseidon2Hasher { fn finish(self) -> Field { + self.finish_ref() + } + + fn finish_ref(&self) -> Field { let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64) let mut sponge = Poseidon2::new(iv); for i in 0..self._state.len() { diff --git a/stdlib/src/lib.nr b/stdlib/src/lib.nr index 817462bd..97ab1cfd 100644 --- a/stdlib/src/lib.nr +++ b/stdlib/src/lib.nr @@ -34,6 +34,7 @@ unconstrained fn print_unconstrained(with_newline: bool, input: T) { print_oracle(with_newline, input); } +/// Print the given input to stdout followed by a newline pub fn println(input: T) { // Safety: a print statement cannot be constrained unsafe { @@ -41,6 +42,7 @@ pub fn println(input: T) { } } +/// Print the given input to stdout pub fn print(input: T) { // Safety: a print statement cannot be constrained unsafe { @@ -98,15 +100,19 @@ fn verify_proof_internal( proof_type: u32, ) {} -// Asserts that the given value is known at compile-time. -// Useful for debugging for-loop bounds. +/// Asserts that the given value is known at compile-time. +/// Useful for debugging for-loop bounds. #[builtin(assert_constant)] pub fn assert_constant(x: T) {} -// Asserts that the given value is both true and known at compile-time. -// The message can be a string, a format string, or any value, as long as it is known at compile-time +/// Asserts that the given value is both true and known at compile-time. +/// The message can be a string, a format string, or any value, as long as it is known at compile-time #[builtin(static_assert)] pub fn static_assert(predicate: bool, message: T) {} +/// Force a field value to be a witness instead of a constant in the compiled output. +/// This is often only useful for debugging compiler optimizations. +/// +/// This has no effect in unconstrained or comptime code. #[builtin(as_witness)] pub fn as_witness(x: Field) {} diff --git a/stdlib/src/meta/expr.nr b/stdlib/src/meta/expr.nr index 14917100..891f4388 100644 --- a/stdlib/src/meta/expr.nr +++ b/stdlib/src/meta/expr.nr @@ -108,11 +108,13 @@ impl Expr { pub comptime fn as_index(self) -> Option<(Expr, Expr)> {} // docs:end:as_index - /// If this expression is an integer literal, return the integer as a field - /// as well as whether the integer is negative (true) or not (false). + /// If this expression is an integer literal, return the integer as a field. + /// Note that negative integers of signed integer types will be encoded + /// as the equivalent negative field value such that e.g. `-1i8` will + /// return the `-1` field value rather than the two's complement encoding of `255`. #[builtin(expr_as_integer)] // docs:start:as_integer - pub comptime fn as_integer(self) -> Option<(Field, bool)> {} + pub comptime fn as_integer(self) -> Option {} // docs:end:as_integer /// If this expression is a lambda, returns the parameters, return type and body. @@ -667,7 +669,7 @@ comptime fn new_unary_op(op: UnaryOp, rhs: Expr) -> Expr { comptime fn new_unsafe(exprs: [Expr]) -> Expr { let exprs = join_expressions(exprs, quote { ; }); - quote { + quote { // Safety: generated by macro unsafe { $exprs } } diff --git a/stdlib/src/meta/function_def.nr b/stdlib/src/meta/function_def.nr index 9930b00d..bd2ec577 100644 --- a/stdlib/src/meta/function_def.nr +++ b/stdlib/src/meta/function_def.nr @@ -1,9 +1,4 @@ impl FunctionDefinition { - #[builtin(function_def_add_attribute)] - // docs:start:add_attribute - pub comptime fn add_attribute(self, attribute: str) {} - // docs:end:add_attribute - #[builtin(function_def_as_typed_expr)] // docs:start:as_typed_expr pub comptime fn as_typed_expr(self) -> TypedExpr {} @@ -14,6 +9,11 @@ impl FunctionDefinition { pub comptime fn body(self) -> Expr {} // docs:end:body + #[builtin(function_def_disable)] + // docs:start:disable + pub comptime fn disable(self, error_message: CtString) {} + // docs:end:disable + #[builtin(function_def_has_named_attribute)] // docs:start:has_named_attribute pub comptime fn has_named_attribute(self, name: str) -> bool {} @@ -44,34 +44,6 @@ impl FunctionDefinition { pub comptime fn return_type(self) -> Type {} // docs:end:return_type - #[builtin(function_def_set_body)] - // docs:start:set_body - pub comptime fn set_body(self, body: Expr) {} - // docs:end:set_body - - #[builtin(function_def_set_parameters)] - // docs:start:set_parameters - pub comptime fn set_parameters(self, parameters: [(Quoted, Type)]) {} - // docs:end:set_parameters - - #[builtin(function_def_set_return_type)] - // docs:start:set_return_type - pub comptime fn set_return_type(self, return_type: Type) {} - // docs:end:set_return_type - - #[builtin(function_def_set_return_public)] - // docs:start:set_return_public - pub comptime fn set_return_public(self, public: bool) {} - // docs:end:set_return_public - - #[builtin(function_def_set_return_data)] - pub comptime fn set_return_data(self) {} - - #[builtin(function_def_set_unconstrained)] - // docs:start:set_unconstrained - pub comptime fn set_unconstrained(self, value: bool) {} - // docs:end:set_unconstrained - #[builtin(function_def_visibility)] // docs:start:visibility pub comptime fn visibility(self) -> Quoted {} diff --git a/stdlib/src/meta/mod.nr b/stdlib/src/meta/mod.nr index 05e7d2a2..bafc7da5 100644 --- a/stdlib/src/meta/mod.nr +++ b/stdlib/src/meta/mod.nr @@ -38,7 +38,7 @@ use crate::hash::poseidon2::Poseidon2Hasher; // A derive function is one that given a type definition can // create us a quoted trait impl from it. -pub type DeriveFunction = fn(TypeDefinition) -> Quoted; +pub comptime type DeriveFunction = fn(TypeDefinition) -> Quoted; // We'll keep a global HANDLERS map to keep track of the derive handler for each trait comptime mut global HANDLERS: UHashMap> = diff --git a/stdlib/src/meta/module.nr b/stdlib/src/meta/module.nr index b25d13f1..07bab881 100644 --- a/stdlib/src/meta/module.nr +++ b/stdlib/src/meta/module.nr @@ -1,11 +1,6 @@ use crate::option::Option; impl Module { - #[builtin(module_add_item)] - // docs:start:add_item - pub comptime fn add_item(self, item: Quoted) {} - // docs:end:add_item - #[builtin(module_has_named_attribute)] // docs:start:has_named_attribute pub comptime fn has_named_attribute(self, name: str) -> bool {} diff --git a/stdlib/src/meta/type_def.nr b/stdlib/src/meta/type_def.nr index 7f4faa5f..716221ea 100644 --- a/stdlib/src/meta/type_def.nr +++ b/stdlib/src/meta/type_def.nr @@ -1,15 +1,10 @@ use crate::option::Option; impl TypeDefinition { - #[builtin(type_def_add_attribute)] - // docs:start:add_attribute - pub comptime fn add_attribute(self, attribute: str) {} - // docs:end:add_attribute - - #[builtin(type_def_add_generic)] - // docs:start:add_generic - pub comptime fn add_generic(self, generic_name: str) -> Type {} - // docs:end:add_generic + #[builtin(type_def_add_abi)] + // docs:start:add_abi + pub comptime fn add_abi(self, abi_argument: CtString) {} + // docs:end:add_abi /// Return a syntactic version of this type definition as a type. /// For example, `type Foo { ... })` would return `Foo` when called with this method. @@ -67,15 +62,6 @@ impl TypeDefinition { // docs:start:name pub comptime fn name(self) -> Quoted {} // docs:end:name - - /// Sets the fields of this type to the given fields vector. - /// All existing fields of the type will be overridden with the given fields. - /// Each element of the fields vector corresponds to the name and type of a field. - /// Each name is expected to be a single identifier. - #[builtin(type_def_set_fields)] - // docs:start:set_fields - pub comptime fn set_fields(self, new_fields: [(Quoted, Type, Quoted)]) {} - // docs:end:set_fields } impl crate::hash::Hash for TypeDefinition { diff --git a/stdlib/src/ops/arith.nr b/stdlib/src/ops/arith.nr index 9a32f8bf..875200ab 100644 --- a/stdlib/src/ops/arith.nr +++ b/stdlib/src/ops/arith.nr @@ -37,12 +37,6 @@ impl Add for u8 { self + other } } -impl Add for u1 { - fn add(self, other: u1) -> u1 { - self + other - } -} - impl Add for i8 { fn add(self, other: i8) -> i8 { self + other @@ -101,12 +95,6 @@ impl Sub for u8 { self - other } } -impl Sub for u1 { - fn sub(self, other: u1) -> u1 { - self - other - } -} - impl Sub for i8 { fn sub(self, other: i8) -> i8 { self - other @@ -165,12 +153,6 @@ impl Mul for u8 { self * other } } -impl Mul for u1 { - fn mul(self, other: u1) -> u1 { - self * other - } -} - impl Mul for i8 { fn mul(self, other: i8) -> i8 { self * other @@ -229,12 +211,6 @@ impl Div for u8 { self / other } } -impl Div for u1 { - fn div(self, other: u1) -> u1 { - self / other - } -} - impl Div for i8 { fn div(self, other: i8) -> i8 { self / other @@ -287,12 +263,6 @@ impl Rem for u8 { self % other } } -impl Rem for u1 { - fn rem(self, other: u1) -> u1 { - self % other - } -} - impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other @@ -355,12 +325,6 @@ pub trait WrappingAdd { } // docs:end:wrapping-add-trait -impl WrappingAdd for u1 { - fn wrapping_add(self: u1, y: u1) -> u1 { - self ^ y - } -} - impl WrappingAdd for u8 { fn wrapping_add(self: u8, y: u8) -> u8 { wrapping_add_hlp(self, y) @@ -430,12 +394,6 @@ pub trait WrappingSub { } // docs:start:wrapping-sub-trait -impl WrappingSub for u1 { - fn wrapping_sub(self: u1, y: u1) -> u1 { - self ^ y - } -} - impl WrappingSub for u8 { fn wrapping_sub(self: u8, y: u8) -> u8 { wrapping_sub_hlp(self, y) as u8 @@ -502,12 +460,6 @@ pub trait WrappingMul { } // docs:start:wrapping-mul-trait -impl WrappingMul for u1 { - fn wrapping_mul(self: u1, y: u1) -> u1 { - self & y - } -} - impl WrappingMul for u8 { fn wrapping_mul(self: u8, y: u8) -> u8 { wrapping_mul_hlp(self, y) @@ -653,8 +605,8 @@ mod tests { assert_eq(10u8.div(3u8), 3u8); assert_eq(15.div(3), 5); - // rem - assert_eq(17.rem(5), 2); + // rem (Field doesn't implement Rem) + assert_eq(17u64.rem(5u64), 2u64); assert_eq(10u8.rem(3u8), 1u8); // neg @@ -674,10 +626,10 @@ mod tests { assert_eq(42.div(42), 1); assert_eq(1.div(1), 1); - // test remainder - assert_eq(42.rem(42), 0); - assert_eq(0.rem(42), 0); - assert_eq(1.rem(42), 1); + // test remainder (Field doesn't implement Rem) + assert_eq(42u32.rem(42u32), 0u32); + assert_eq(0u16.rem(42u16), 0u16); + assert_eq(1u64.rem(42u64), 1u64); } #[test(should_fail)] @@ -869,27 +821,6 @@ mod tests { assert_eq(neg_two.wrapping_mul(two), neg_four); } - #[test] - fn test_u1_behavior() { - // u1 wrapping add is XOR - assert_eq(0u1.wrapping_add(0u1), 0u1); - assert_eq(0u1.wrapping_add(1u1), 1u1); - assert_eq(1u1.wrapping_add(0u1), 1u1); - assert_eq(1u1.wrapping_add(1u1), 0u1); - - // u1 wrapping sub is XOR - assert_eq(0u1.wrapping_sub(0u1), 0u1); - assert_eq(0u1.wrapping_sub(1u1), 1u1); - assert_eq(1u1.wrapping_sub(0u1), 1u1); - assert_eq(1u1.wrapping_sub(1u1), 0u1); - - // u1 wrapping mul is AND - assert_eq(0u1.wrapping_mul(0u1), 0u1); - assert_eq(0u1.wrapping_mul(1u1), 0u1); - assert_eq(1u1.wrapping_mul(0u1), 0u1); - assert_eq(1u1.wrapping_mul(1u1), 1u1); - } - // test wrapping operations is the same as the regular operations #[test] fn test_wrapping_vs_regular() { diff --git a/stdlib/src/ops/bit.nr b/stdlib/src/ops/bit.nr index d242a375..6ec0421b 100644 --- a/stdlib/src/ops/bit.nr +++ b/stdlib/src/ops/bit.nr @@ -36,12 +36,6 @@ impl Not for u8 { !self } } -impl Not for u1 { - fn not(self) -> u1 { - !self - } -} - impl Not for i8 { fn not(self) -> i8 { !self @@ -101,12 +95,6 @@ impl BitOr for u8 { self | other } } -impl BitOr for u1 { - fn bitor(self, other: u1) -> u1 { - self | other - } -} - impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other @@ -165,12 +153,6 @@ impl BitAnd for u8 { self & other } } -impl BitAnd for u1 { - fn bitand(self, other: u1) -> u1 { - self & other - } -} - impl BitAnd for i8 { fn bitand(self, other: i8) -> i8 { self & other @@ -229,12 +211,6 @@ impl BitXor for u8 { self ^ other } } -impl BitXor for u1 { - fn bitxor(self, other: u1) -> u1 { - self ^ other - } -} - impl BitXor for i8 { fn bitxor(self, other: i8) -> i8 { self ^ other @@ -287,12 +263,6 @@ impl Shl for u8 { self << other } } -impl Shl for u1 { - fn shl(self, other: u1) -> u1 { - self << other - } -} - impl Shl for i8 { fn shl(self, other: i8) -> i8 { self << other @@ -345,12 +315,6 @@ impl Shr for u8 { self >> other } } -impl Shr for u1 { - fn shr(self, other: u1) -> u1 { - self >> other - } -} - impl Shr for i8 { fn shr(self, other: i8) -> i8 { self >> other diff --git a/stdlib/src/option.nr b/stdlib/src/option.nr index 0a62e412..164538cf 100644 --- a/stdlib/src/option.nr +++ b/stdlib/src/option.nr @@ -2,6 +2,8 @@ use crate::cmp::{Eq, Ord, Ordering}; use crate::default::Default; use crate::hash::{Hash, Hasher}; +/// Represents a value of type T or its absence. +/// Use `Option::some(value)` to construct a value or `Option::none()` to record the absence of one. pub struct Option { _is_some: bool, _value: T, @@ -19,12 +21,12 @@ impl Option { } /// True if this Option is None - pub fn is_none(self) -> bool { + pub fn is_none(&self) -> bool { !self._is_some } /// True if this Option is Some - pub fn is_some(self) -> bool { + pub fn is_some(&self) -> bool { self._is_some } diff --git a/stdlib/src/panic.nr b/stdlib/src/panic.nr index 46cbb7f8..4c26e774 100644 --- a/stdlib/src/panic.nr +++ b/stdlib/src/panic.nr @@ -1,3 +1,6 @@ +/// Halt the program at runtime with the given error message. +/// +/// The provided error message must be either a `str` or a `fmtstr`. pub fn panic(message: T) -> U where T: StringLike, diff --git a/stdlib/src/prelude.nr b/stdlib/src/prelude.nr index 7aa60456..cc868cd1 100644 --- a/stdlib/src/prelude.nr +++ b/stdlib/src/prelude.nr @@ -1,7 +1,6 @@ pub use crate::{assert_constant, print, println}; pub use crate::cmp::{Eq, Ord}; pub use crate::collections::bounded_vec::BoundedVec; -pub use crate::collections::vec::Vec; pub use crate::convert::{From, Into}; pub use crate::default::Default; pub use crate::meta::{derive, derive_via}; diff --git a/stdlib/src/primitive_docs.nr b/stdlib/src/primitive_docs.nr index 92f87588..7c20afdb 100644 --- a/stdlib/src/primitive_docs.nr +++ b/stdlib/src/primitive_docs.nr @@ -14,10 +14,6 @@ mod primitive_array {} #['nargo_doc_primitive bool] mod primitive_bool {} -/// The 1-bit unsigned integer type. -#['nargo_doc_primitive u1] -mod primitive_u1 {} - /// The 8-bit unsigned integer type. #['nargo_doc_primitive u8] mod primitive_u8 {} diff --git a/stdlib/src/runtime.nr b/stdlib/src/runtime.nr index c075107c..1215797c 100644 --- a/stdlib/src/runtime.nr +++ b/stdlib/src/runtime.nr @@ -1,2 +1,3 @@ +/// True if executed in an unconstrained or comptime context, false otherwise. #[builtin(is_unconstrained)] pub fn is_unconstrained() -> bool {} diff --git a/stdlib/src/vector.nr b/stdlib/src/vector.nr index 64ffed89..2923c5b7 100644 --- a/stdlib/src/vector.nr +++ b/stdlib/src/vector.nr @@ -47,6 +47,8 @@ impl [T] { self } + /// Converts this vector into an array of length N. + /// Panics if the length of this vector is not N. pub fn as_array(self) -> [T; N] { assert(self.len() == N); @@ -57,8 +59,8 @@ impl [T] { array } - // Apply a function to each element of the vector, returning a new vector - // containing the mapped elements. + /// Apply a function to each element of the vector, returning a new vector + /// containing the mapped elements. pub fn map(self, f: fn[Env](T) -> U) -> [U] { let mut ret = [].as_vector(); for elem in self { @@ -67,8 +69,8 @@ impl [T] { ret } - // Apply a function to each element of the vector with its index, returning a - // new vector containing the mapped elements. + /// Apply a function to each element of the vector with its index, returning a + /// new vector containing the mapped elements. pub fn mapi(self, f: fn[Env](u32, T) -> U) -> [U] { let mut ret = [].as_vector(); let mut index = 0; @@ -79,14 +81,14 @@ impl [T] { ret } - // Apply a function to each element of the vector + /// Apply a function to each element of the vector pub fn for_each(self, f: fn[Env](T) -> ()) { for elem in self { f(elem); } } - // Apply a function to each element of the vector with its index + /// Apply a function to each element of the vector with its index pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) { let mut index = 0; for elem in self { @@ -95,9 +97,9 @@ impl [T] { } } - // Apply a function to each element of the vector and an accumulator value, - // returning the final accumulated value. This function is also sometimes - // called `foldl`, `fold_left`, `reduce`, or `inject`. + /// Apply a function to each element of the vector and an accumulator value, + /// returning the final accumulated value. This function is also sometimes + /// called `foldl`, `fold_left`, `reduce`, or `inject`. pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U { for elem in self { accumulator = f(accumulator, elem); @@ -105,9 +107,9 @@ impl [T] { accumulator } - // Apply a function to each element of the vector and an accumulator value, - // returning the final accumulated value. Unlike fold, reduce uses the first - // element of the given vector as its starting accumulator value. + /// Apply a function to each element of the vector and an accumulator value, + /// returning the final accumulated value. Unlike fold, reduce uses the first + /// element of the given vector as its starting accumulator value. pub fn reduce(self, f: fn[Env](T, T) -> T) -> T { let mut accumulator = self[0]; for i in 1..self.len() { @@ -116,8 +118,8 @@ impl [T] { accumulator } - // Returns a new vector containing only elements for which the given predicate - // returns true. + /// Returns a new vector containing only elements for which the given predicate + /// returns true. pub fn filter(self, predicate: fn[Env](T) -> bool) -> Self { let mut ret = [].as_vector(); for elem in self { @@ -128,7 +130,7 @@ impl [T] { ret } - // Flatten each element in the vector into one value, separated by `separator`. + /// Flatten each element in the vector into one value, separated by `separator`. pub fn join(self, separator: T) -> T where T: Append, @@ -146,7 +148,7 @@ impl [T] { ret } - // Returns true if all elements in the vector satisfy the predicate + /// Returns true if all elements in the vector satisfy the predicate pub fn all(self, predicate: fn[Env](T) -> bool) -> bool { let mut ret = true; for elem in self { @@ -155,7 +157,7 @@ impl [T] { ret } - // Returns true if any element in the vector satisfies the predicate + /// Returns true if any element in the vector satisfies the predicate pub fn any(self, predicate: fn[Env](T) -> bool) -> bool { let mut ret = false; for elem in self {