July 29, 2026, 8:26am 1
From discussion on issue on codeberg (last paragraph of the comment) I understood that this code will no longer work when RLS goes away (code simplified compared to the code in issue).
self.* = .{
.rt = rt: {
self.rt.initStatic(gpa) catch unreachable;
break :rt self.rt;
},
.io = self.rt.io(),
};
Why?
To my understanding RLS makes it there is no intermediary copy. Which means the self.* being assigned to and self used within initialization is the same. So in theory this would also currently work thanks to the RLS.
self.* = .{
.rt = self.rt.init(gpa) catch unreachable, // rt: *Runtime
.io = self.rt.io(),
};
But in the first example, it seems to me it should work even after RLS goes away, because in the .rt initialization I actually modify the original self, and during .io initialization I still use the original self so I do not depend on the original self and the new self being the same.
Am I misunderstanding how it currently works or how it will work after RLS goes away?
EDIT: The first example is maybe not the best one, because self.rt.io() just takes a pointer and so it does not really matter if self.rt is initialized or not. So this modified example can be considered:
self.* = .{
.rt = rt: {
self.rt = .init(gpa) catch unreachable;
break :rt self.rt;
},
.io = self.rt.io(),
};
spiffyk July 29, 2026, 8:44am 2
The code you present here doesn’t indeed seem to trigger any illegal behaviour.
But the original code in your linked issue does, and I think you are just misunderstanding the reason. I also don’t think this has anything to do with RLS. It’s not even mentioned in the original issue.
The crucial fact is that your original code has the optional type rt: ?zio.Runtime, which could be interpreted as syntax sugar for something like this:
rt_desugared: struct {
is_present: bool,
value: zio.Runtime,
}
The problem is that when you do rt = undefined, it basically means this:
rt_desugared = .{ .is_present = undefined, .value = undefined };
When you then do rt.?, that is syntax sugar for:
if (rt_desugared.is_present) rt_desugared.value else unreachable
But rt_desugared.is_present is undefined, so by reading it you’ve hit Illegal Behaviour.
If instead you do rt = @as(zio.Runtime, undefined), that’s syntax sugar for this (note the true instead of undefined in the is_present field):
rt_desugared = .{ .is_present = true, .value = undefined };
Suddenly, you’re fine with rt.?, because rt_desugared.is_present is a defined value of true.
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.