feat: let init, update and view return error unions - #132
Merged
Merged
Conversation
This was referenced Aug 13, 2026
`view` returns `[]const u8`, so every allocation inside it needs its own fallback. The examples carry 245 of them -- `catch "Error"`, `catch ""`, `catch "?"` -- and the quick-start snippet in the README taught the pattern. Each one turns an allocation failure into a rendering artefact that is indistinguishable from real output. `init`, `update` and `view` may now each return `!T` instead of `T`. The runtime detects that per function at compile time and propagates the error out of `tick()`, where the caller already handles failure. Both forms compile, so nothing existing has to change. `src/core/model.zig` holds the Model contract in one place: the `@hasDecl` checks that were duplicated in `Program` and `SubProgram`, plus the two comptime helpers. `SubProgram` mirrors its child, so a fallible child model gives a `SubProgram` whose `view` is fallible too. `counter` and `hello_world` are converted as worked examples; the rest still compile unchanged and can move over gradually.
meszmate
force-pushed
the
feat/fallible-model-callbacks
branch
from
August 14, 2026 04:37
1fb58a9 to
7d94d85
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Not tied to an issue — this came out of reviewing the codebase for things that would simplify the library.
The problem
viewreturns[]const u8, so it cannot fail. Rendering allocates on nearly every line, which means every allocation needs its own fallback. The examples currently carry 245 of them:The quick-start snippet in
src/root.zigtaught the pattern too. Each one silently turns an allocation failure into a rendering artefact that is indistinguishable from real output —"?"where a number should be, a title that quietly loses its styling.The change
init,updateandviewmay now each return!Tinstead ofT. The runtime detects that per function at compile time and propagates the error out oftick(), where the caller already handles failure.Fully backwards compatible — both forms compile, mixed freely (a fallible
viewalongside a plainupdateis fine). Nothing existing has to change.Also
src/core/model.zigcollects the Model contract in one place: the@hasDeclchecks that were duplicated betweenProgramandSubProgram(now with a message naming the type and the missing declaration), plus the two comptime helpers.SubProgrammirrors its child's fallibility, so a fallible child model gives aSubProgramwhoseviewis fallible too — otherwise composing one would be a compile error with no way out.Tests
refAllDeclsonProgram(FallibleModel)andProgram(DummyModel)forces both instantiations to be fully analysed, so atrythat does not line up is a build failure rather than something that only shows up in a user's app. Verified the test actually bites by removing atryand watching it fail. Same forSubProgramin both shapes, plus unit tests for the comptime helpers.counterandhello_worldare converted as worked examples. The remaining 42 still compile unchanged and can move over gradually.zig build testandzig buildclean on 0.16.0.