Skip to content

fix(data): convert self-referential container fields and defaults to declared types - #85

Merged
Roger-luo merged 2 commits into
mainfrom
fix/container-type-convert
Jul 12, 2026
Merged

Roger-luo merged 2 commits into
mainfrom
fix/container-type-convert

Conversation

@Roger-luo

Copy link
Copy Markdown
Owner

Fixes two closely-related bugs in how @data handles self-referential /
container-collapsing field types. Both stem from the fact that such fields are
stored as Any in the variant storage struct (the wrapper Type doesn't exist
yet, and self-references can't be named), so Julia's inner constructor performs
no conversion.

#32 — convert constructor arguments to declared field types

When a declared field type collapses to Any in storage (a Vector{Any} field
or a self-referential Vector{Self}), the inner constructor stored the value
unchanged while getproperty / variant_getfield type-asserted against the
declared annotation, raising a TypeError.

Both the positional and keyword constructors now Base.convert each argument to
its declared annotation type, restoring normal struct-construction semantics. The
conversion is a no-op when the value already matches, so construction stays type
stable, and it lets the explicit-brace form of self-referential constructors
promote a parametric singleton bottom (e.g. Empty()).

#33 — resolve the ADT name to .Type in default values

Inside the generated module the bare ADT name resolves to the module, so a
self-referential default like:

@data SExpr begin
    struct Add
        arguments::Vector{SExpr} = SExpr[]
    end
end

SExpr.Add()   # ERROR: MethodError: no method matching getindex(::Module)

expanded SExpr[] to getindex(::Module) and errored. The declared field type
already treated SExpr as SExpr.Type; the default value did not.

New eval_default processes a field's default like eval_global_ref but
additionally rewrites the ADT name (and its explicit SExpr.Type / SExpr{...}
forms) to the module-local Type alias, so the name means SExpr.Type in
defaults just as in field types. Qualified access such as SExpr.Add is
preserved so variant constructors stay reachable.

Tests

Fixes #32
Fixes #33

🤖 Generated with Claude Code

Roger-luo and others added 2 commits July 12, 2026 14:00
Variant storage structs use `Any` for a field whenever its declared type
collapses -- a `Vector{Any}` field or a self-referential `Vector{Self}`
(which cannot reference the not-yet-defined wrapper `Type`). Julia's inner
constructor then performs no conversion, so the stored value keeps its
original type while `getproperty`/`variant_getfield` type-assert against the
declared annotation, raising a `TypeError`.

Convert each argument to its declared annotation type in the positional and
keyword constructors, restoring normal struct-construction semantics. The
conversion is a no-op when the value already matches, so construction stays
type stable. This also lets the explicit-brace form of self-referential
constructors promote a parametric singleton bottom (e.g. `Empty()`).

Fixes #32

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Inside the generated module, the bare ADT name resolves to the module
itself, so a self-referential default like `arguments::Vector{SExpr} =
SExpr[]` expanded to `getindex(::Module)` and errored on construction.

Add `eval_default`, which processes a field's default value like
`eval_global_ref` but additionally rewrites the ADT name (and its
explicit `SExpr.Type` / `SExpr{...}` forms) to the module-local `Type`
alias -- so the name means `SExpr.Type` in defaults just as it already
does in field types. Qualified access such as `SExpr.Add` is preserved
so variant constructors stay reachable.

Fixes #33

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 12, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
moshi-jl Ready Ready Preview, Comment Jul 12, 2026 7:03pm

@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 91.74%. Comparing base (a74db69) to head (d020b87).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/data/emit/cons.jl 96.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #85      +/-   ##
==========================================
+ Coverage   91.69%   91.74%   +0.04%     
==========================================
  Files          43       43              
  Lines        1661     1683      +22     
==========================================
+ Hits         1523     1544      +21     
- Misses        138      139       +1     

☔ View full report in Codecov by Harness.
📢 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.

@github-actions

Copy link
Copy Markdown
Contributor

Benchmark Results (Julia v1)

Time benchmarks
main d020b87... main / d020b87...
adt_transform/transform n=100 6.97 ± 0.15 μs 6.73 ± 0.19 μs 1.04 ± 0.037
adt_transform/transform n=1000 0.0671 ± 0.00081 ms 0.0662 ± 0.00096 ms 1.01 ± 0.019
linked_list/sum n=100 0.471 ± 0.01 μs 0.481 ± 0.001 μs 0.979 ± 0.021
linked_list/sum n=1000 5.19 ± 0.051 μs 5.13 ± 0.041 μs 1.01 ± 0.013
time_to_load 0.0772 ± 0.0019 s 0.0791 ± 0.0012 s 0.976 ± 0.028
Memory benchmarks
main d020b87... main / d020b87...
adt_transform/transform n=100 0.204 k allocs: 6.34 kB 0.204 k allocs: 6.34 kB 1
adt_transform/transform n=1000 2.02 k allocs: 0.0619 MB 2.02 k allocs: 0.0619 MB 1
linked_list/sum n=100 0 allocs: 0 B 0 allocs: 0 B
linked_list/sum n=1000 0 allocs: 0 B 0 allocs: 0 B
time_to_load 0.145 k allocs: 11 kB 0.145 k allocs: 11 kB 1

@Roger-luo
Roger-luo merged commit 79a1053 into main Jul 12, 2026
8 checks passed
@Roger-luo
Roger-luo deleted the fix/container-type-convert branch July 12, 2026 19:08
github-actions Bot referenced this pull request Jul 12, 2026
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

This branch was successfully deployed

1 active deployment
Preview — d020b879 Deployed Jul 12, 2026 by vercel[bot]
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.

Clarify typing of default values in @data TypeError in getproperty on container types

1 participant