@quangd42 I think @constCast
is unrelated to this. In your code, you are using @aligncast
.
First, after reasoning a bit more about it, to answer my own question about alignCast
in this context:
Using @alignCast
, I promise to the compiler that the pointer actually has the expected alignment for the result type. And I can promise this for sure because I know that the obj
field is part of an ObjString
struct which was allocated (sorry, not shown in the code) using allocator.create(ObjString)
.
The promise would be broken for example if the ObjString
was instead
part of a packed struct
, unless very carefully constructed.
In fact, as @vulpesx points out, the whole construct is basically a tagged union
in disguise.
But the point is that the content is always created on the heap and allocates only the actual necessary length for the payload.
One could call it a variable length tagged union.
By searching the net for this, I stumbled over More control over the data layout of tagged unions · Issue #1922 · ziglang/zig · GitHub and Can I allocate only the required amount of memory for tagged unions?.
One idea in the comments for issue 1922 is to use NaN tagging (a similar idea is pointer tagging). I know this idea from Robert Nystroms “wren” language (see Performance – Wren).
I’ll keep this idea in mind for later, when I have completed the language. Then I’ll be able to compare the performance of the current basic approach, Nan tagging, pointer tagging or the data-oriented approach (from the other link) for different use cases, because I reckon the results strongly depend on the language’s type system, dynamic vs static typing and the program under test (e.g. number crunching vs typical business logic in DB applications, which usually involve records with many string fields and logic based on strings, so for a real language I’d consider using a special case for short strings).
I already had a solution without @fieldParentPtr
before, by using packed struct
with obj
as the first field. But I had to add @alignCast
in several places nevertheless (that could have been caused by the strange way I allocated memory in that version, though).
The two different approaches from the “Can I callocate…?” discussion could probably be used as well: Using a union of different pointer types, or a data-oriented approach of using different ArrayLists (one for each ObjType tag, in my case). However, @sze’s idea using @unionInit
, std.meta.TagPayload
and std.meta.Child
requires a bit more Zig knowledge than I have ATM.