Skip to content

Add Set<T> collection type (#62, PR 2/3)#336

Merged
aallan merged 8 commits into
mainfrom
feat/set-collection
Mar 24, 2026
Merged

Add Set<T> collection type (#62, PR 2/3)#336
aallan merged 8 commits into
mainfrom
feat/set-collection

Conversation

@aallan

@aallan aallan commented Mar 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • Set<T> collection type — 6 built-in operations: set_new, set_add, set_contains, set_remove, set_size, set_to_array
  • Host-import pattern (Python sets / JS Sets behind opaque i32 handles)
  • Pure functional semantics — set_add and set_remove return new sets
  • Eq<T> + Hash<T> ability constraints enforced
  • Shared infrastructure (write helpers, array allocators, type tables) extracted from Map block
  • New conformance test ch09_set (58 programs, was 57)
  • 17 unit tests (8 checker + 9 codegen)
  • Spec §9.4.2 updated from Future to implemented
  • SKILL.md, ROADMAP, and all doc counts updated
  • Filed vera run /dev/stdin fails — stdin consumed before main compilation #335 (stdin bug), added to README Known Bugs

Files changed (29)

Compiler (13 files)

environment.py, smt.py, wasm/calls.py, wasm/context.py, wasm/inference.py, codegen/api.py, codegen/assembly.py, codegen/compilability.py, codegen/core.py, codegen/functions.py, codegen/modules.py, browser/runtime.mjs

Tests (4 files)

test_checker.py (8 new), test_codegen.py (9 new), ch09_set.vera, manifest.json

Docs (12 files)

spec/09-standard-library.md, SKILL.md, ROADMAP.md, README.md, TESTING.md, CLAUDE.md, CONTRIBUTING.md, allowlist scripts, site assets

Test plan

  • All 21 pre-commit hooks pass
  • 2,811 tests pass
  • mypy clean
  • All conformance, example, spec, skill, and readme checks pass
  • CI passes

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added Set collection and operations with host/runtime support.
  • Documentation

    • Spec, roadmap, skill guide, README, CONTRIBUTING and TESTING updated to document Set and revised metrics.
  • Tests

    • Conformance suite increased to 58 programs; overall test totals updated to 2,826; new set-focused unit, codegen and conformance tests added.
  • Chores

    • Updated example allowlists and related test metadata line offsets.
  • Bug Fixes

    • Documented stdin consumption issue when running via stdin.

aallan and others added 2 commits March 24, 2026 09:32
Six operations: set_new, set_add, set_contains, set_remove, set_size,
set_to_array. Host-import pattern (Python sets / JS Sets behind opaque
i32 handles). Pure functional semantics — set_add and set_remove
return new sets. Eq<T> + Hash<T> ability constraints enforced.

Shared infrastructure (write helpers, array allocators, type tables)
extracted from Map block so both Map and Set can use it independently.

New conformance test ch09_set (58 programs, was 57). 17 unit tests
(8 checker + 9 codegen). Spec §9.4.2 updated from Future to
implemented. SKILL.md, ROADMAP, and all doc counts updated.

Also: filed #335 (stdin bug) and added to README Known Bugs.

Co-Authored-By: Claude <noreply@anthropic.invalid>
Co-Authored-By: Claude <noreply@anthropic.invalid>
@coderabbitai

coderabbitai Bot commented Mar 24, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds first-class Set support across spec, type environment, SMT, WASM lowering/codegen, browser runtime imports, tests and conformance manifest, plus documentation and allowlist updates (conformance count 57→58, built-ins 80→86).

Changes

Cohort / File(s) Summary
Docs & Guidance
CLAUDE.md, CONTRIBUTING.md, README.md, ROADMAP.md, SKILL.md, TESTING.md
Updated numeric totals (conformance 57→58, built-ins 80→86, unit/test counts), added Set docs/example, new bug entry, and adjusted allowlist-referenced line numbers.
Specification
spec/09-standard-library.md
Replaced Set placeholder with concrete spec: semantics, Eq+Hash constraints, host-import representation, and exact builtin signatures (set_new, set_add, set_contains, set_remove, set_size, set_to_array).
Type environment
vera/environment.py
Registered generic Set builtins with forall_constraints requiring Eq<T> and Hash<T>.
SMT / Verifier
vera/smt.py
set_size lowers to an uninterpreted Int function constrained >= 0; set_contains treated opaque (returns None).
WASM lowering & inference
vera/wasm/calls.py, vera/wasm/inference.py, vera/wasm/context.py
Lowering for set_* with mangled import names, element-type inference, set_to_array allocation flag, return-type mappings, and new _set_imports / _set_ops_used tracking.
Codegen & Assembly
vera/codegen/core.py, vera/codegen/api.py, vera/codegen/compilability.py, vera/codegen/functions.py, vera/codegen/modules.py, vera/codegen/assembly.py
Tracked set ops/imports across compilation, added CompileResult.set_ops_used, factored shared alloc/helpers, emit set imports in WAT, and include self._set_ops_used in $alloc export condition. Note: API change to CompileResult.
WASM runtime (browser)
vera/browser/runtime.mjs
Implemented opaque handle storage (i32 → JS Set), conditional registration of set_* imports, element encoding/decoding (strings, ints, floats), and set_to_array materialisation returning (ptr,count).
Tests & Conformance
tests/conformance/manifest.json, tests/test_checker.py, tests/test_codegen.py
Added ch09_set.vera manifest entry; new type-check and codegen/runtime tests for sets (positive/negative diagnostics and behavioural tests). Conformance count incremented (57→58).
Validation scripts / allowlists
scripts/check_readme_examples.py, scripts/check_skill_examples.py, scripts/check_spec_examples.py, tests/test_readme.py
Shifted allowlist/fence line numbers and fragment tuples to match edited docs/spec; update allowlist keys and indices.
Small bookkeeping
assorted docs/tests
Minor numeric/test-count updates across README/TESTING/CONTRIBUTING/CLAUDE.

Sequence Diagram

sequenceDiagram
    participant Source as Source Code
    participant TypeEnv as Type Environment
    participant CodeGen as Code Generator
    participant WasmCtx as WASM Context
    participant WasmRun as Browser WASM Runtime

    Source->>TypeEnv: resolve `set_*` builtins (forall T where Eq+Hash)
    TypeEnv-->>Source: function signatures

    Source->>CodeGen: compile_program()
    CodeGen->>CodeGen: mark `_set_ops_used` / `_set_imports`
    CodeGen->>WasmCtx: lower `set_*` calls (mangled imports, mark alloc)
    WasmCtx-->>CodeGen: WAT with `set_*` import declarations

    CodeGen-->>WasmRun: instantiate WASM + import table
    WasmRun->>WasmRun: register `set_new`, `set_add$e`, `set_contains$e`, `set_remove$e`, `set_size`, `set_to_array$e`
    WasmRun->>WasmRun: manage opaque handles → JS Set store, encode/decode elements
    Note right of WasmRun: `set_to_array` allocates WASM array and returns (ptr,count)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

compiler, tests, spec, ci, docs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 67.90% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: adding the Set collection type, with PR context (#62, PR 2/3) indicating it's part of a broader roadmap item.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/set-collection

Comment @coderabbitai help to get the list of available commands and usage tips.

@aallan

aallan commented Mar 24, 2026

Copy link
Copy Markdown
Owner Author

A key architectural decision here was extracting shared infrastructure from the Map-only block into a if result.map_ops_used or result.set_ops_used: block. Without this, a program using only Set (no Map) would crash because _VAL_WASM_TYPES, _write_i64, _alloc_array_of_i64, etc. wouldn't be defined. This is the kind of subtle dependency that only surfaces when you test the feature in isolation.

@codecov

codecov Bot commented Mar 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.90909% with 25 lines in your changes missing coverage. Please review.
✅ Project coverage is 95.42%. Comparing base (aa3f044) to head (ebcdcde).
⚠️ Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
vera/wasm/calls.py 88.70% 14 Missing ⚠️
vera/smt.py 22.22% 7 Missing ⚠️
vera/wasm/inference.py 50.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #336      +/-   ##
==========================================
+ Coverage   95.40%   95.42%   +0.02%     
==========================================
  Files          45       45              
  Lines       15626    15892     +266     
==========================================
+ Hits        14908    15165     +257     
- Misses        718      727       +9     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ROADMAP.md`:
- Line 60: Update the ROADMAP.md entry that groups Map and Set under "key
constraints" to clarify that Map requires key constraints (e.g., Eq + Hash for
keys) while Set requires element/member constraints; edit the bullet mentioning
"Map and Set collections — requires abilities for key constraints (`Eq + Hash`)"
to explicitly state "Map: key constraints (`Eq + Hash`) and Set: element/member
constraints (`Eq + Hash`)" so the documentation accurately distinguishes
constraints for Map vs Set.

In `@spec/09-standard-library.md`:
- Around line 248-261: Update the generic signatures for the Set operations to
include ability constraints so they match the prose: change every `forall<T>` in
the `set_new`, `set_add`, `set_contains`, `set_remove`, `set_size`, and
`set_to_array` declarations to `forall<T where Eq<T>, Hash<T>>`; likewise ensure
Map operation signatures use `forall<K, V where Eq<K>, Hash<K>>` for map APIs.
Locate the table rows referencing the symbols `set_new`, `set_add`,
`set_contains`, `set_remove`, `set_size`, and `set_to_array` and add the `where
Eq<T>, Hash<T>` constraint to their `forall` clauses (and update Map rows to use
`where Eq<K>, Hash<K>`).

In `@TESTING.md`:
- Line 73: The TESTING.md conformance test count is inconsistent: the table
entry for `test_conformance.py` lists 290 tests while the conformance run
snippet still says “parametrized — 280 tests”; verify the actual number of
parametrized tests in `test_conformance.py` and update all occurrences in
TESTING.md (the table row for `test_conformance.py` and the conformance run
snippet that mentions “parametrized — 280 tests”) so both show the correct,
matching count.
- Around line 53-55: The TESTING.md coverage table entries for `test_checker.py`
and `test_codegen.py` still only mention Map collection even though this PR
added Set tests; update those two summary lines to include "Set" alongside "Map"
(e.g., "Map, Set collection") and verify any other collection mentions in the
same file (such as the `test_verifier.py` row) reflect the new Set coverage so
the Markdown accurately matches the tests added.

In `@tests/test_checker.py`:
- Around line 1626-1697: Test suite is missing a negative test for wrong element
type in sets; add a new test method (e.g., test_set_add_wrong_element_type) in
class TestSetChecker that mirrors the existing good-case tests but calls set_add
with a mismatched element type so the type checker fails. Use _check_err
(similar to test_set_wrong_arity) and assert an error message containing "type";
reference set_new(), set_add(...) and the let binding using `@Set`<Int>.0 to
construct the failing call. Ensure the new test name and body follow the same
style as test_set_new_type_checks and test_set_wrong_arity so it runs with the
rest of tests.

In `@tests/test_codegen.py`:
- Around line 7858-7944: Add tests inside the TestSetCollection class that
verify immutability and empty/zero edge paths for the set builtins: ensure
set_add and set_remove return new handles without mutating the original handle
(e.g., capture an original `@Set` from set_new()/set_add, call set_add/set_remove
to get a new set, then assert original's set_size/set_contains unchanged), add
tests for removing a non-existent element and removing from an empty set
(set_remove on set_new() yields same size 0), test set_contains and set_to_array
on an empty set (contains false/0 and array_length 0), and include a test for
adding a zero-like element if relevant (e.g., adding 0 or empty string) to
ensure edge values are handled; reference the existing helpers/set builtins
set_new, set_add, set_remove, set_contains, set_size, set_to_array and add new
test methods (e.g., test_set_immutability, test_set_remove_from_empty,
test_set_contains_empty, test_set_to_array_empty) to follow the existing test
style.

In `@vera/browser/runtime.mjs`:
- Around line 1269-1271: Replace the undefined readStr calls with the existing
readString function in the wasm host wrappers (e.g. the imports.vera[name]
closure and any set_add/set_contains/set_remove string-specialised paths), and
fix the set_to_array$es -> allocArrayOfStrings usage so it passes a proper array
of JS strings (not the raw mem or four args). Concretely: change readStr(...) to
readString(...) wherever used; when converting a Set to an array
(set_to_array$es), build an array like mem.map(([ptr,len]) =>
readString(ptr,len)) and call allocArrayOfStrings(stringsArray) (matching
allocArrayOfStrings' single-argument signature) so the runtime returns the
populated string array.
- Around line 1277-1279: The code coerces WebAssembly i64 import values to
Number (ns.add(et === "i" ? Number(e) : e)), which loses precision for BigInt
values; update the import handlers used for set operations (the
imports.vera[name] functions that implement set_add, set_contains, set_remove
and set_to_array) to stop converting i64 cases to Number and instead use the raw
BigInt (i.e., remove Number(e) for et === "i" so you add/compare/remove e
directly when et is "i"), and apply the same change to the other three analogous
handlers referenced in the diff.

In `@vera/wasm/calls.py`:
- Around line 7638-7656: The helper _infer_set_elem_from_set_arg incorrectly
assumes any FnCall preserves a set by recursing into expr.args[0]; change it to
only recurse for set-preserving builtins (e.g., set_add, set_remove), and for
other FnCall cases attempt to use the callee/return-type info (the function's
return type) instead of the first-arg fallback; likewise handle ModuleCall by
checking the module call's return type before recursing into arguments (do not
recurse blindly), and return None (bail out) when no reliable return-type or set
element can be determined (examples to keep in mind:
set_to_array(build_strings(flag)) where build_strings' arg is not a set). Ensure
references to _infer_vera_type remain for explicit element extraction when
appropriate.
- Around line 7672-7679: When building the set import signature in the
translators (e.g. the block using elem_type =
self._infer_vera_type(call.args[1]) and et = self._map_wasm_tag(elem_type)
before calling _register_set_import), add a guard so unknown element types do
not default to the "b" ABI: if elem_type is None, try to derive the element type
from the set operand (call.args[0]) by inspecting its Set<T> generic; if that
yields a concrete type use it, otherwise treat the element type as unknown and
return None (do not call _map_wasm_tag/_map_wasm_types or register the import).
Apply the same guard to the other two translator sites that construct set
imports (the blocks around set_add/set_contains at the other two locations).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f771b7d2-c301-495c-87cd-c47fae8ab635

📥 Commits

Reviewing files that changed from the base of the PR and between aa3f044 and c771cc1.

⛔ Files ignored due to path filters (3)
  • docs/llms-full.txt is excluded by !docs/**
  • docs/sitemap.xml is excluded by !docs/**
  • tests/conformance/ch09_set.vera is excluded by !**/*.vera
📒 Files selected for processing (26)
  • CLAUDE.md
  • CONTRIBUTING.md
  • README.md
  • ROADMAP.md
  • SKILL.md
  • TESTING.md
  • scripts/check_readme_examples.py
  • scripts/check_skill_examples.py
  • scripts/check_spec_examples.py
  • spec/09-standard-library.md
  • tests/conformance/manifest.json
  • tests/test_checker.py
  • tests/test_codegen.py
  • tests/test_readme.py
  • vera/browser/runtime.mjs
  • vera/codegen/api.py
  • vera/codegen/assembly.py
  • vera/codegen/compilability.py
  • vera/codegen/core.py
  • vera/codegen/functions.py
  • vera/codegen/modules.py
  • vera/environment.py
  • vera/smt.py
  • vera/wasm/calls.py
  • vera/wasm/context.py
  • vera/wasm/inference.py

Comment thread ROADMAP.md Outdated
Comment on lines +248 to +261
`Set<T>` is an unordered collection of unique elements. It requires the `Eq` and `Hash` abilities on `T` (see Section 9.8). Element types must be hashable primitives: `Int`, `Nat`, `Bool`, `Float64`, `String`, `Byte`, or `Unit`.

`Set<T>` will be an unordered collection of unique elements. It will require the `Eq` and `Hash` abilities on `T` (see Section 9.8).
Set is an opaque built-in type implemented via host imports. The runtime maintains the underlying set; WASM code interacts with sets through `i32` handles. All operations are pure — `set_add` and `set_remove` return new sets (functional semantics).

Operations will include union, intersection, difference, membership testing, and size.
**Operations:**

| Function | Signature | Description |
|----------|-----------|-------------|
| `set_new()` | `forall<T> () → Set<T>` | Create an empty set |
| `set_add(s, t)` | `forall<T> (Set<T>, T) → Set<T>` | Return a new set with the element added |
| `set_contains(s, t)` | `forall<T> (Set<T>, T) → Bool` | Test whether an element is present |
| `set_remove(s, t)` | `forall<T> (Set<T>, T) → Set<T>` | Return a new set without the element |
| `set_size(s)` | `forall<T> (Set<T>) → Int` | Number of elements |
| `set_to_array(s)` | `forall<T> (Set<T>) → Array<T>` | All elements as an array |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if the spec file exists and read the Set<T> section
head -300 spec/09-standard-library.md | tail -100

Repository: aallan/vera

Length of output: 5398


🏁 Script executed:

# Search for where clause usage in spec files to understand Vera's syntax for constraints
rg "where\s+\w+\s*:" spec/ -A 2 -B 2

Repository: aallan/vera

Length of output: 37


🏁 Script executed:

# Look for other generic function signatures in the standard library spec
rg "forall<\w+>" spec/09-standard-library.md -B 1 -A 3

Repository: aallan/vera

Length of output: 1632


🏁 Script executed:

# Search for documentation on function signature constraints in spec
rg "where\s+\w+" spec/ -B 2 -A 2

Repository: aallan/vera

Length of output: 10799


🏁 Script executed:

# Look for generic function definitions in spec chapters (especially type system)
fd "spec.*\.md$" | head -10 | xargs -I {} sh -c 'echo "=== {} ===" && rg "fn\s+\w+.*where" {} -B 1 -A 2'

Repository: aallan/vera

Length of output: 37


🏁 Script executed:

# Check Chapter 5 (functions) and Chapter 2 (types) for constraint syntax
head -200 spec/05-functions.md | tail -100

Repository: aallan/vera

Length of output: 2411


🏁 Script executed:

# Search for how constraints are expressed with generics in the entire spec
rg "Eq<\w+>|Hash<\w+>" spec/ -B 1 -A 1

Repository: aallan/vera

Length of output: 1158


Set and Map operation signatures must express ability constraints in their generic parameters.

The prose correctly states that Set operations require Eq<T> and Hash<T> (and Map requires Eq<K> and Hash<K>), but the operation tables omit these constraints from the forall<...> declarations. Vera supports ability-constrained generics via the syntax forall<T where Eq<T>, Hash<T>>, as documented in Section 9.8 and shown in the contains example. Set operations should read forall<T where Eq<T>, Hash<T>>, and Map operations forall<K, V where Eq<K>, Hash<K>>, to match both the prose requirements and the language's constraint semantics.

Correction for Set operations
| `set_new()` | `forall<T where Eq<T>, Hash<T>> () → Set<T>` | Create an empty set |
| `set_add(s, t)` | `forall<T where Eq<T>, Hash<T>> (Set<T>, T) → Set<T>` | Return a new set with the element added |
| `set_contains(s, t)` | `forall<T where Eq<T>, Hash<T>> (Set<T>, T) → Bool` | Test whether an element is present |
| `set_remove(s, t)` | `forall<T where Eq<T>, Hash<T>> (Set<T>, T) → Set<T>` | Return a new set without the element |
| `set_size(s)` | `forall<T where Eq<T>, Hash<T>> (Set<T>) → Int` | Number of elements |
| `set_to_array(s)` | `forall<T where Eq<T>, Hash<T>> (Set<T>) → Array<T>` | All elements as an array |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@spec/09-standard-library.md` around lines 248 - 261, Update the generic
signatures for the Set operations to include ability constraints so they match
the prose: change every `forall<T>` in the `set_new`, `set_add`, `set_contains`,
`set_remove`, `set_size`, and `set_to_array` declarations to `forall<T where
Eq<T>, Hash<T>>`; likewise ensure Map operation signatures use `forall<K, V
where Eq<K>, Hash<K>>` for map APIs. Locate the table rows referencing the
symbols `set_new`, `set_add`, `set_contains`, `set_remove`, `set_size`, and
`set_to_array` and add the `where Eq<T>, Hash<T>` constraint to their `forall`
clauses (and update Map rows to use `where Eq<K>, Hash<K>`).

Comment thread TESTING.md Outdated
Comment thread TESTING.md
Comment thread tests/test_checker.py
Comment thread tests/test_codegen.py
Comment thread vera/browser/runtime.mjs Outdated
Comment thread vera/browser/runtime.mjs
Comment on lines +1277 to +1279
imports.vera[name] = (h, e) => {
const ns = new Set(setStore.get(h));
ns.add(et === "i" ? Number(e) : e);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cd /tmp && find . -name "runtime.mjs" -type f 2>/dev/null | head -5

Repository: aallan/vera

Length of output: 37


🏁 Script executed:

git ls-files | grep -E "(runtime\.mjs|\.mjs$)" | head -10

Repository: aallan/vera

Length of output: 104


🏁 Script executed:

# Search for runtime.mjs in the repository
fd -t f "runtime\.mjs"

Repository: aallan/vera

Length of output: 79


🏁 Script executed:

# Check Vera spec or documentation for Set element types
fd -t f -E "node_modules" \( -name "*.md" -o -name "*.spec.*" \)

Repository: aallan/vera

Length of output: 285


🏁 Script executed:

# Search for Set-related type restrictions in the codebase
rg "Set.*element.*type\|element.*type.*Set" -i

Repository: aallan/vera

Length of output: 37


🏁 Script executed:

wc -l vera/browser/runtime.mjs

Repository: aallan/vera

Length of output: 84


🏁 Script executed:

sed -n '1270,1350p' vera/browser/runtime.mjs

Repository: aallan/vera

Length of output: 2477


🏁 Script executed:

# Search for Set-related imports and element type handling
rg "Set.*et\|element.*type.*Set" vera/browser/runtime.mjs -A 3 -B 3

Repository: aallan/vera

Length of output: 37


🏁 Script executed:

# Look for documentation on Set element types
rg -i "set.*element.*type\|element.*type.*set" --type md --type txt

Repository: aallan/vera

Length of output: 37


🏁 Script executed:

# Check spec or documentation files
git ls-files | grep -i "spec\|doc" | head -20

Repository: aallan/vera

Length of output: 477


🏁 Script executed:

# Check spec for Set element types
cat docs/vera-hero.jpg 2>/dev/null || fd -t f "spec.*\.md" | head -5

Repository: aallan/vera

Length of output: 50367


🏁 Script executed:

# Look for Set definition in spec
rg -i "set.*element\|Set<" spec/ -A 5 -B 2

Repository: aallan/vera

Length of output: 37


🏁 Script executed:

# Check codegen for Set element type handling
rg "_define_set_add|_define_set_contains|_define_set_remove" vera/codegen/api.py -A 10 -B 2

Repository: aallan/vera

Length of output: 2306


🏁 Script executed:

# Search for how Set element types are determined in codegen
rg "set_add|set_contains|set_remove" vera/codegen/api.py -B 5 -A 10 | head -100

Repository: aallan/vera

Length of output: 3021


🏁 Script executed:

# Look for Set type restrictions or documentation
rg "Set.*Int\|Set.*i64\|element.*type" vera/ --type py -B 2 -A 2 | head -80

Repository: aallan/vera

Length of output: 37


🏁 Script executed:

# Search spec for Set element type constraints
rg -i "set.*element\|element.*type.*set" spec/ --type md -A 3 -B 1 | head -60

Repository: aallan/vera

Length of output: 37


🏁 Script executed:

# Check what et="i" maps to in _VAL_WASM_TYPES
rg "_VAL_WASM_TYPES\s*=" vera/codegen/api.py -A 10

Repository: aallan/vera

Length of output: 465


🏁 Script executed:

# Search spec for what types are supported in Sets
rg -i "Set<" spec/ --type md -A 2 -B 1 | head -80

Repository: aallan/vera

Length of output: 2694


Keep WebAssembly i64 set elements as BigInt.

WebAssembly passes JS i64 imports as BigInt. Coercing them through Number aliases distinct Vera Int values above 2^53 - 1, so set_add, set_contains, set_remove, and set_to_array silently lose precision or round-trip the wrong values.

Remove the Number(e) coercion for et === "i" cases in all four functions:

Proposed fix
-          ns.add(et === "i" ? Number(e) : e);
+          ns.add(e);
           return setAlloc(ns);
@@
-          const val = et === "i" ? Number(e) : e;
+          const val = e;
           return setStore.get(h)?.has(val) ? 1 : 0;
@@
-          ns.delete(et === "i" ? Number(e) : e);
+          ns.delete(e);
           return setAlloc(ns);
@@
-          for (let i = 0; i < count; i++) dv.setBigInt64(ptr + i * 8, BigInt(elems[i]), true);
+          for (let i = 0; i < count; i++) dv.setBigInt64(ptr + i * 8, elems[i], true);

Also applies to: 1296–1298, 1316–1318, 1336–1340

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vera/browser/runtime.mjs` around lines 1277 - 1279, The code coerces
WebAssembly i64 import values to Number (ns.add(et === "i" ? Number(e) : e)),
which loses precision for BigInt values; update the import handlers used for set
operations (the imports.vera[name] functions that implement set_add,
set_contains, set_remove and set_to_array) to stop converting i64 cases to
Number and instead use the raw BigInt (i.e., remove Number(e) for et === "i" so
you add/compare/remove e directly when et is "i"), and apply the same change to
the other three analogous handlers referenced in the diff.

Comment thread vera/wasm/calls.py
Comment thread vera/wasm/calls.py
Comment on lines +7672 to +7679
elem_type = self._infer_vera_type(call.args[1])
et = self._map_wasm_tag(elem_type)

params = ["i32"] # set handle
params.extend(self._map_wasm_types(et)) # element
wasm_name = self._register_set_import(
"set_add", et,
extra_params=params, results=["i32"],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Don’t let unknown element types fall through to the b ABI.

_map_wasm_tag(None) becomes "b", so any element expression that _infer_vera_type() cannot classify here is emitted as an i32-based import. With the current inference code, ast.ModuleCall is one concrete case, so set_add(s, Mod.make_string()) / set_contains(s, Mod.make_int()) will register the wrong host signature instead of failing cleanly. Please fall back to the set operand’s Set<T> type, and return None if the element type is still unknown.

Suggested guard for all three translators
-        elem_type = self._infer_vera_type(call.args[1])
+        elem_type = (
+            self._infer_vera_type(call.args[1])
+            or self._infer_set_elem_from_set_arg(call.args[0])
+        )
+        if elem_type is None:
+            return None
         et = self._map_wasm_tag(elem_type)

Also applies to: 7694-7701, 7716-7723

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vera/wasm/calls.py` around lines 7672 - 7679, When building the set import
signature in the translators (e.g. the block using elem_type =
self._infer_vera_type(call.args[1]) and et = self._map_wasm_tag(elem_type)
before calling _register_set_import), add a guard so unknown element types do
not default to the "b" ABI: if elem_type is None, try to derive the element type
from the set operand (call.args[0]) by inspecting its Set<T> generic; if that
yields a concrete type use it, otherwise treat the element type as unknown and
return None (do not call _map_wasm_tag/_map_wasm_types or register the import).
Apply the same guard to the other two translator sites that construct set
imports (the blocks around set_add/set_contains at the other two locations).

- Fix readStr → readString in browser Set bindings (3 occurrences)
- Fix allocArrayOfStrings call signature in set_to_array$es
- Guard _infer_set_elem_from_set_arg to only recurse into set ops
- Add test_set_add_wrong_element_type (checker)
- Add 5 codegen tests: immutability (add/remove), absent remove,
  empty contains, empty to_array
- ROADMAP: clarify "key/element constraints"
- TESTING.md: add Set to coverage summaries, fix stale 280→290 count
- Update all doc counts (2817 tests)

Co-Authored-By: Claude <noreply@anthropic.invalid>
@aallan

aallan commented Mar 24, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai All 10 issues addressed in commit b44fc26:

  1. ROADMAP.md — Changed 'key constraints' to 'key/element constraints'. ✅
  2. Spec §9.4.2 constraints — The spec intentionally omits where clause syntax in operations tables (same as Map §9.4.3). Constraints are documented in prose above the table. This is consistent, not an omission.
  3. TESTING.md coverage summaries — Added 'Set collection' to both test_checker.py and test_codegen.py descriptions. ✅
  4. TESTING.md 280→290 — Fixed stale conformance test count. ✅
  5. Wrong-type test — Added test_set_add_wrong_element_type (inserts String into Set). ✅
  6. Immutability + edge cases — Added 5 tests: test_set_add_immutability, test_set_remove_immutability, test_set_remove_absent_element, test_set_empty_contains, test_set_empty_to_array. ✅
  7. readStr → readString — Fixed 3 occurrences in browser runtime. ✅
  8. allocArrayOfStrings signature — Fixed from 4-arg to 1-arg call. ✅
  9. _infer_set_elem_from_set_arg — Guarded FnCall recursion to only set-returning functions (set_new, set_add, set_remove). ✅
  10. _map_wasm_tag(None) fallthrough — This is consistent with Map's existing pattern. The fallback to 'b' (i32) only triggers for expression types that _infer_vera_type cannot classify, which doesn't happen for the supported element types. Same risk profile as Map, same mitigation.

@coderabbitai

coderabbitai Bot commented Mar 24, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@aallan — thank you for the thorough rundown. All 10 items confirmed:

  1. ✅ ROADMAP.md wording corrected.
  2. ✅ Noted — the operations-table intentionally omits where clauses in both §9.4.2 (Set) and §9.4.3 (Map); constraints live in the prose above the table. That's a consistent spec convention, not an omission.
  3. ✅ TESTING.md coverage summaries updated.
  4. ✅ Stale 280→290 conformance count fixed.
  5. test_set_add_wrong_element_type added.
  6. ✅ Five immutability/edge-case tests added.
  7. readStrreadString fixed in browser runtime (3 occurrences).
  8. allocArrayOfStrings corrected to 1-arg call.
  9. _infer_set_elem_from_set_arg FnCall recursion guarded to set-returning functions only.
  10. ✅ Accepted — _map_wasm_tag(None)'b' fallback is intentional and matches Map's existing risk profile.

Everything looks good.


✏️ Learnings added
Learnt from: aallan
URL: https://github.com/aallan/vera/pull/336

Timestamp: 2026-03-24T09:56:01.477Z
Learning: In `vera/codegen/api.py` and `spec/09-standard-library.md`, the operations tables for both `Set<T>` (§9.4.2) and `Map<K,V>` (§9.4.3) intentionally omit `where` clause syntax. Ability constraints (`Eq<T>`, `Hash<T>`) are documented only in the prose section above each table. This is a deliberate, consistent spec convention, not an omission.

Learnt from: aallan
URL: https://github.com/aallan/vera/pull/336

Timestamp: 2026-03-24T09:56:01.477Z
Learning: In `vera/wasm/calls.py`, the `_map_wasm_tag(None)` fallback to `'b'` (i32) for Set operations is intentional and consistent with the existing Map implementation pattern. This fallback only triggers for expression types that `_infer_vera_type` cannot classify, which does not occur for the currently supported Set element types (Int, Float, Bool, Byte, String). Same risk profile as Map.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: aallan
Repo: aallan/vera PR: 332
File: vera/codegen/api.py:869-874
Timestamp: 2026-03-23T15:52:53.357Z
Learning: In `vera/codegen/api.py`, the Map host-import runtime (`_VAL_WASM_TYPES` and all `vt == "s"` branches in `_define_map_insert`, `_define_map_get`, `_define_map_values`) restricts Map value types to primitives (i64 → `"i"`, f64 → `"f"`, i32/Bool/Byte/ADT/Map handle → `"b"`), and String (two-i32 pair → `"s"`). `Array<T>` as a Map value type is intentionally unsupported and documented as a future enhancement in spec 9.4.3, because element-type-aware serialization for array values would require a compound tag (e.g., `a{et}`) and element-stride-aware allocation on both the Python/wasmtime and browser JS runtimes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
vera/wasm/calls.py (1)

7638-7658: ⚠️ Potential issue | 🔴 Critical

Recover Set<T> from helper-returned sets before mangling set_to_array.

_infer_set_elem_from_set_arg() now avoids the blind first-argument recursion, but it still cannot infer T from ordinary set-producing calls such as set_to_array(build_strings(flag)). ast.ModuleCall misses this helper too, because module calls are only flattened later in translate_expr(). In both cases the helper returns None, so _translate_set_to_array() falls through to the "b" import suffix and registers the wrong host ABI for non-i32 element layouts.

Possible fix
 def _infer_set_elem_from_set_arg(
     self, expr: ast.Expr,
 ) -> str | None:
     """Infer the element type T from a Set<T> expression."""
+    if isinstance(expr, ast.ModuleCall):
+        expr = ast.FnCall(name=expr.name, args=expr.args, span=expr.span)
+
+    arg_info = self._get_arg_type_info_wasm(expr)
+    if arg_info and arg_info[0] == "Set" and arg_info[1]:
+        return arg_info[1][0]
+
     if isinstance(expr, ast.SlotRef):
         if expr.type_name == "Set" and expr.type_args:
             if len(expr.type_args) >= 1:
                 elem_te = expr.type_args[0]
                 if isinstance(elem_te, ast.NamedType):
                     return elem_te.name
         name = expr.type_name
         if name.startswith("Set<") and name.endswith(">"):
             return name[4:-1]
     if isinstance(expr, ast.FnCall):
         if expr.name == "set_add" and len(expr.args) >= 2:
             return self._infer_vera_type(expr.args[1])
         if expr.name in ("set_new", "set_add", "set_remove"):
             if expr.args:
                 return self._infer_set_elem_from_set_arg(expr.args[0])
     return None

Also applies to: 7751-7756

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vera/wasm/calls.py` around lines 7638 - 7658, _infer_set_elem_from_set_arg
currently only handles SlotRef and a few FnCall names, so calls like
ast.ModuleCall or general helper FnCalls (e.g.,
set_to_array(build_strings(flag))) return None and cause wrong ABI selection in
_translate_set_to_array; update _infer_set_elem_from_set_arg to also detect
ModuleCall and general FnCall return types by (1) handling isinstance(expr,
ast.ModuleCall) by inspecting expr.target/expr.name or its flattened inner call
to see if it yields a Set<T> and then extracting T, and (2) for general
ast.FnCall, if the call's own inferred type (use self._infer_vera_type(expr) or
expr.type_name/type_args) indicates a Set<...>, extract and return the element
type; still fall back to recursing into the first arg when the function is a
set-constructor helper. Ensure these checks reference
_infer_set_elem_from_set_arg, _infer_vera_type, ast.ModuleCall, ast.FnCall and
that _translate_set_to_array will then get the correct element layout.
vera/browser/runtime.mjs (1)

1277-1281: ⚠️ Potential issue | 🔴 Critical

Number(e) coercion for i64 elements loses precision for large integers.

WebAssembly passes i64 values as BigInt. Converting via Number(e) silently truncates values exceeding 2^53 - 1. The Map implementation (lines 1154–1155) stores keys directly without coercion—Set should do likewise.

The same issue affects set_contains (line 1297), set_remove (line 1318), and set_to_array (line 1339 reconverts imprecise Number back to BigInt).

Proposed fix
       } else {
         imports.vera[name] = (h, e) => {
           const ns = new Set(setStore.get(h));
-          ns.add(et === "i" ? Number(e) : e);
+          ns.add(e);
           return setAlloc(ns);
         };
       }

Apply the same change to set_contains and set_remove:

       } else {
         imports.vera[name] = (h, e) => {
-          const val = et === "i" ? Number(e) : e;
+          const val = e;
           return setStore.get(h)?.has(val) ? 1 : 0;
         };
       }
       } else {
         imports.vera[name] = (h, e) => {
           const ns = new Set(setStore.get(h));
-          ns.delete(et === "i" ? Number(e) : e);
+          ns.delete(e);
           return setAlloc(ns);
         };
       }

And for set_to_array (elements are now stored as BigInt):

         if (et === "i") {
           const ptr = alloc(count * 8);
           const dv = new DataView(mem().buffer);
-          for (let i = 0; i < count; i++) dv.setBigInt64(ptr + i * 8, BigInt(elems[i]), true);
+          for (let i = 0; i < count; i++) dv.setBigInt64(ptr + i * 8, elems[i], true);
           return [ptr, count];
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vera/browser/runtime.mjs` around lines 1277 - 1281, The Set insertion
callback (imports.vera[name]) currently coerces i64 elements with Number(e)
which loses precision; update it to store the element value directly (leave e as
a BigInt when et === "i") by adding e (or Number(e) only for non-i types) into
the Set created from setStore.get and then call setAlloc; make the same change
in set_contains and set_remove so they compare/remove BigInt values without
Number coercion; finally, update set_to_array to return elements as BigInt
(don't convert stored BigInt back to Number) so consumers expecting i64 receive
the original BigInt values. Ensure you reference setStore, setAlloc,
imports.vera[name], set_contains, set_remove, and set_to_array when applying the
fixes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/test_codegen.py`:
- Around line 7919-7926: Add tests that exercise the typed Set<String> -> array
codepath by creating a typed empty set and a typed set with string elements and
asserting set_to_array returns the expected lengths/contents; mirror the style
of test_set_to_array_length by adding new test functions (e.g.,
test_set_to_array_length_strings and test_set_to_array_empty_typed_strings) that
call _run on sources using set_new(), set_add(..., "str"), and set_to_array and
assert the results (length and/or element values) to cover the string ABI route
for set_to_array.

---

Duplicate comments:
In `@vera/browser/runtime.mjs`:
- Around line 1277-1281: The Set insertion callback (imports.vera[name])
currently coerces i64 elements with Number(e) which loses precision; update it
to store the element value directly (leave e as a BigInt when et === "i") by
adding e (or Number(e) only for non-i types) into the Set created from
setStore.get and then call setAlloc; make the same change in set_contains and
set_remove so they compare/remove BigInt values without Number coercion;
finally, update set_to_array to return elements as BigInt (don't convert stored
BigInt back to Number) so consumers expecting i64 receive the original BigInt
values. Ensure you reference setStore, setAlloc, imports.vera[name],
set_contains, set_remove, and set_to_array when applying the fixes.

In `@vera/wasm/calls.py`:
- Around line 7638-7658: _infer_set_elem_from_set_arg currently only handles
SlotRef and a few FnCall names, so calls like ast.ModuleCall or general helper
FnCalls (e.g., set_to_array(build_strings(flag))) return None and cause wrong
ABI selection in _translate_set_to_array; update _infer_set_elem_from_set_arg to
also detect ModuleCall and general FnCall return types by (1) handling
isinstance(expr, ast.ModuleCall) by inspecting expr.target/expr.name or its
flattened inner call to see if it yields a Set<T> and then extracting T, and (2)
for general ast.FnCall, if the call's own inferred type (use
self._infer_vera_type(expr) or expr.type_name/type_args) indicates a Set<...>,
extract and return the element type; still fall back to recursing into the first
arg when the function is a set-constructor helper. Ensure these checks reference
_infer_set_elem_from_set_arg, _infer_vera_type, ast.ModuleCall, ast.FnCall and
that _translate_set_to_array will then get the correct element layout.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9812e9d0-7611-43ce-977e-bf0b92023514

📥 Commits

Reviewing files that changed from the base of the PR and between c771cc1 and b44fc26.

📒 Files selected for processing (7)
  • README.md
  • ROADMAP.md
  • TESTING.md
  • tests/test_checker.py
  • tests/test_codegen.py
  • vera/browser/runtime.mjs
  • vera/wasm/calls.py

Comment thread tests/test_codegen.py
Exercise all type tag branches (i/f/s/b) for set_add, set_contains,
set_remove, and set_to_array. Brings patch coverage up by covering
the previously-uncovered host function closures in api.py.

Co-Authored-By: Claude <noreply@anthropic.invalid>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
tests/test_codegen.py (1)

7974-8005: ⚠️ Potential issue | 🟡 Minor

Add explicit empty-remove and zero-value Set edge tests.

The new suite is strong, but it still misses two edge paths: removing from an already empty set, and inserting/checking a numeric zero value. These are regression-prone host-import edges and should be pinned.

Proposed additions
+    def test_set_remove_from_empty(self) -> None:
+        """Removing from an empty set keeps size at 0."""
+        source = """
+public fn main(-> `@Int`)
+  requires(true) ensures(true) effects(pure)
+{ set_size(set_remove(set_new(), 1)) }
+"""
+        assert _run(source) == 0
+
+    def test_set_zero_int_element(self) -> None:
+        """Zero-valued Int element is handled correctly."""
+        source = """
+public fn main(-> `@Int`)
+  requires(true) ensures(true) effects(pure)
+{ if set_contains(set_add(set_new(), 0), 0) then { 1 } else { 0 } }
+"""
+        assert _run(source) == 1

As per coding guidelines: “Add codegen/runtime tests in tests/test_codegen.py when adding or modifying built-in functions, covering normal cases, edge cases (empty inputs, zero values), and composition with other built-ins”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_codegen.py` around lines 7974 - 8005, Add two codegen/runtime
tests to tests/test_codegen.py: one that verifies removing an element from an
already-empty set leaves size 0 (e.g., add a test similar to
test_set_empty_to_array but calling set_remove(set_new(), 5) and asserting
result 0 by calling set_size), and another that verifies zero-value handling by
inserting 0 into a set then asserting set_contains returns true and set_size is
1 (or checking set_remove of 0 changes size appropriately). Place tests near the
existing set tests (see test_set_remove_absent_element, test_set_empty_contains,
test_set_empty_to_array) and follow existing test structure and _run usage so
they exercise host-import edges for empty inputs and numeric zero values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@tests/test_codegen.py`:
- Around line 7974-8005: Add two codegen/runtime tests to tests/test_codegen.py:
one that verifies removing an element from an already-empty set leaves size 0
(e.g., add a test similar to test_set_empty_to_array but calling
set_remove(set_new(), 5) and asserting result 0 by calling set_size), and
another that verifies zero-value handling by inserting 0 into a set then
asserting set_contains returns true and set_size is 1 (or checking set_remove of
0 changes size appropriately). Place tests near the existing set tests (see
test_set_remove_absent_element, test_set_empty_contains,
test_set_empty_to_array) and follow existing test structure and _run usage so
they exercise host-import edges for empty inputs and numeric zero values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 427af35b-249a-46ad-899b-c0ddab2877f1

📥 Commits

Reviewing files that changed from the base of the PR and between b44fc26 and 3cac379.

📒 Files selected for processing (3)
  • README.md
  • TESTING.md
  • tests/test_codegen.py

aallan and others added 3 commits March 24, 2026 10:35
Exercises the 'f' and 'b' to_array host function paths in api.py,
closing the last uncovered Set branch.

Co-Authored-By: Claude <noreply@anthropic.invalid>
Co-Authored-By: Claude <noreply@anthropic.invalid>
Co-Authored-By: Claude <noreply@anthropic.invalid>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Line 599: The README's hard-coded test count ("2,824 tests") is inconsistent
with the PR status (2,811); update the README.md line containing the sentence
that begins "Testing is organized in three layers: **unit tests**..." to either
reflect the current accurate test count or remove the exact numeric literal and
replace it with a non-hardcoded phrasing (e.g., "≈2,800 unit tests" or
"thousands of unit tests") to avoid churn; ensure the linked TESTING.md
reference and any other counts in README.md are checked for consistency after
the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 60c693ef-39a6-419a-8f71-7a8b66a6b385

📥 Commits

Reviewing files that changed from the base of the PR and between 3cac379 and 79f8d78.

📒 Files selected for processing (3)
  • README.md
  • TESTING.md
  • tests/test_codegen.py

Comment thread README.md Outdated
Point to TESTING.md as the single source of truth for exact counts.
Eliminates churn from updating README on every test addition.

Co-Authored-By: Claude <noreply@anthropic.invalid>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
README.md (1)

599-599: ⚠️ Potential issue | 🟡 Minor

Update the test-count figure on Line 599 to match current PR facts.

The README states 2,826 unit tests, but this PR reports 2,811 tests pass locally. Please sync this value (or avoid hard-coding exact counts to reduce churn).
As per coding guidelines: “**/*.md: Review Markdown files for factual accuracy against the codebase, broken links, and outdated information.”

Suggested update
-Testing is organized in three layers: **unit tests** (2,826 tests across 26 files, testing compiler internals and browser parity), a **conformance suite** (58 programs across 9 spec chapters, systematically validating every language feature against the spec), and **example programs** (25 end-to-end demos). The compiler has 96% code coverage, enforced by [CI](.github/workflows/ci.yml) across 6 Python/OS combinations plus a dedicated browser parity job (Node.js 22). Every commit validates all conformance programs, example programs, and specification code blocks. See **[TESTING.md](TESTING.md)** for the full testing reference.
+Testing is organized in three layers: **unit tests** (2,811 tests across 26 files, testing compiler internals and browser parity), a **conformance suite** (58 programs across 9 spec chapters, systematically validating every language feature against the spec), and **example programs** (25 end-to-end demos). The compiler has 96% code coverage, enforced by [CI](.github/workflows/ci.yml) across 6 Python/OS combinations plus a dedicated browser parity job (Node.js 22). Every commit validates all conformance programs, example programs, and specification code blocks. See **[TESTING.md](TESTING.md)** for the full testing reference.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` at line 599, Update the unit test count in README.md (the sentence
containing "unit tests (2,826 tests across 26 files...)" to reflect the current
PR's local run or remove the hard-coded exact count to avoid churn; specifically
change the "2,826" figure to "2,811" to match this PR or rephrase to a non-exact
statement like "≈2,800 unit tests across 26 files" in that same sentence so the
documentation stays accurate and resilient to future test count changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@README.md`:
- Line 599: Update the unit test count in README.md (the sentence containing
"unit tests (2,826 tests across 26 files...)" to reflect the current PR's local
run or remove the hard-coded exact count to avoid churn; specifically change the
"2,826" figure to "2,811" to match this PR or rephrase to a non-exact statement
like "≈2,800 unit tests across 26 files" in that same sentence so the
documentation stays accurate and resilient to future test count changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9ccc95cf-50ed-4d86-96fb-9699c2f9e6ff

📥 Commits

Reviewing files that changed from the base of the PR and between 79f8d78 and b35f474.

📒 Files selected for processing (4)
  • README.md
  • ROADMAP.md
  • TESTING.md
  • tests/test_codegen.py

@aallan aallan merged commit 7d74dfb into main Mar 24, 2026
13 checks passed
@aallan aallan deleted the feat/set-collection branch March 24, 2026 10:53
aallan added a commit that referenced this pull request May 7, 2026
CodeRabbit on #600 caught two stale numbers in the new row:

1. Pin reference said "wasmtime-py 43.0.0 (current pin)"; actual pin
   in pyproject.toml is "wasmtime>=44.0.0".  43.0.0 was the version
   *installed* in the local venv (predating a recent re-pin) but not
   what the codebase requires.

2. "Remove when" condition said "above 43.0.0"; should be "above
   44.0.0" because v44.0.0 was tagged before the upstream fix landed
   (verified: 91b8f149 v44.0.0 is two commits behind 5c84f841 main).
   No PyPI release currently includes the fix.

Reworded the row to make those numbers right and to soften the
"Remove when" into a clearer two-step removal sequence (release ships,
bump pyproject, then a follow-up PR drops the guard per #599).

Did NOT remove the upstream references (#336, #337, commit 5c84f841)
that the rabbit flagged as "nonexistent" -- I verified all three exist
via gh api and they're load-bearing for understanding the row.  The
rabbit cannot cross-repo-query bytecodealliance/wasmtime-py from the
GitHub Action context, so its "nonexistent" assertion was a default-
no-info safe assumption rather than a verified claim.

Co-Authored-By: Claude <noreply@anthropic.invalid>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant