Is this a bug?
Scalar : {
value : F64,
deps : List Scalar,
}
── CYCLIC ALIAS in grad.roc ────────────────────────────────────────────────────
The Scalar alias is self-recursive in an invalid way:
3│ Scalar : {
^^^^^^
Recursion in aliases is only allowed if recursion happens behind a
tagged union, at least one variant of which is not recursive.
Or am I doing something wrong?
That's how it has been for a while, right?
i have no clue haha
Standard solution is
Scalar : [NoDeps F64, WithDeps {
value : F64,
deps : List Scalar,
}]
that works, ty
I'm not a pro, but I presume that constraint is because of lambda sets? It might change with the changes going on
i don't think it should have anything to do with lambda sets.. i think probably just an unnecessary restriction
It shouldn't have anything to do with them, yes
I'm working (slowly) on the can rework, I can look into it
ty
Oh actually, I think it's because records aren't refcounted
And we don't currently intelligently know that List is refcounted
So without knowing that certain builtins can terminate recursion, we are worried that recursive records will be infinite in size
So we need some way to determine which data types are heap-allocated and mark recursion termination
Yeah the recursion has to be behind a pointer or you don’t know the size of the object at compile time
yeah it was just never implemented fully
I think the check is just "does the alias appear again in itself"
there need to be exceptions added to it, such as this one
I think just handling List
would work, since Dict
and Set
are implemented in native Roc using List
yeah, plus if we move Dict
and Set
to Zig (as has been discussed before) presumably it would be easy to add them to that list of exceptions :big_smile:
yeah seeing it’s under List is sufficient. or any other recursive union
Yeah, super old bug
I tried enabling recursion through list and box a long time ago, but didn't figure it out.
Wait, would Box actually work? Yes, Box is heap-allocated, but it always has a value behind it. So
Scalar : { value : F64, next : Box Scalar }
has a known, finite size, but would take up infinite memory, right?
Unless Box can be null in a way I don't know
Yeah, in roc today, it would be just list, box, and recursive tag. Of course recursive records could automatically box if we wanted.
Oh yeah, box doesn't work I guess
Would need to be an optional box of some sort
This is still different than raw recursive tags though
So would need an exception in current roc
Last updated: Jul 05 2025 at 12:14 UTC