New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: for "enum inference" improvements (with a view towards succinct local "anonymous" but type-sound enums) #4241
Comments
what would this proposal emit for export fn entry() void {
foo(5);
}
fn foo(comptime a: u8) void {
comptime var x = switch (a) {
0 => .zero,
1 => .one,
2 => .two,
else => .none,
};
@compileLog(@TypeOf(x)); // (enum literal)
} |
I'm not going to comment on the cherry on top proposal, but as for the points before that, I think it's a general bug or missing feature in Zig that type resolution doesn't work on nested conditionals. There are a few github issues which are related to this, e.g. #3750. |
@mikdusan my guess would be |
#4241 (comment) is only meant to show a case of when inferring an comptime var x: `@TypeOf(.foo)` = switch (a) { |
@mikdusan interesting, but why should the current |
I'm assuming in this PR that the nested-if example above a switch would equally result in "cherry on top" inferral of type "anon-enum" which conflicts with an inferral of type "enum-literal". |
True that. So this scenario, does it come up a lot in practice? I mean I was actually slightly surprised it wouldn't print |
The below snippets may appear contrived (it's for brevity) but bear with for now, more real-world(ish) reasoning then at bottom of post.
Inside any
fn
, this compiles and works today:Knowing the rest of Zig's existing overall inference capabilities, the first "smoothening" one would like to see is "enumerant inference" so as to be able to:
As of today (yesterday's nightly), this compiler-errors with
values of type '(enum literal)' must be comptime known
, arrow hinting at the 3rdif
. (Same without the parens nesting btw.)With that out of the way, it should also then in principle (putting subjective desirability discussions / style sensibilities aside) technically be possible, following Zigs similar powers (elsewhere outside the fn-local-enum situation, consider the anon-structs-aka-tuple-literals one can pass to
std.debug.warn
andstd.fmt
funcs) to be able to drop the named local type entirely:Naturally same error as of today as above, as this sort of inference isn't present so far.
Now the cherry on top would then be the ability to actually:
Don't choke! The structural unnamed underlying enum type to back
var foo
here gets derived/inferred from all the possible "value expressions" the right-hand-side expression can potentially resolve to. (If not all branches conform to the (shall we call it) "dotIdent" pattern, then simply just fail inference, no biggie --- I'm not suggesting "inference of unions" here =)This kind of local-tagging can be a great readability helper in more expansive big-block multi-branching situations, to now switch on the just-decided local enum instead, which also lets one explain / delineate from the very outset of one's
fn
the various major cases being handled via the enumerant ("tag") names, while still preserving the short-circuiting evaluation of potentially involved runtime condition-expressions etc. And they're not scattered "deep way down there" but together and summarized under succinct names at the top --- and not as n different bool vars but inferred enumerants because one wanted neither to evaluate all of them, nor to noisily via AND/OR/NOT "manually shortcircuit" into such local named bools, a whole bunch of them (as a de-facto-quasi-enum-semantically-but-not-as-clearly-demarkated-to-the-compiler-typechecker-and-reader), such as one'd have to declare today for lack of the suggested "inferred anonymous local enumerants".This whole consideration / proposal is also partially motivated by the fact that
switch
(currently) requires comptime-known cases (rather than desugaring-into-ifs-in-IR-for-noncompliant-switch
-occurrences transparently). Otherwise one couldswitch (true)
with the runtime-dynamic condition checks before the=>
arrows. Still more readable for multiple (>=3) big-block handlings than a multi-if or multiple top-located bools.Now, does this mean asking for
||
as well, or "generalizing existing error-sets capabilities to all userland enums"? Not so, in my view. No need to go too wild with cross-func/cross-module inferencings or whatever. Just hook into the current failure path for the above and if all possible-result-expressions have the same "dotIdent" form ( .foo , .bar , .baz etc.) the inference to an exactly definedenum
is both clear, unambiguous and tractable. (And once Zig-LSP is up and feature complete, hover overvar foo
to see theenum
"def" as-if-code..)This is for light-weight, mostly-for-explanatory/understandability-purposes enumerants: a full-blown named-type-def would make it falsely look more important (or false suggesting it's part of business logic) than it usually is for such cases. Locally-scoped "anonymous-enum" enumerants could neatly help tag/annotate/document/illuminate local logic flow --- a bit of a "fluffy/sugary" suggestion at first sight but I feel it when used habitually (enabled by the-near-zero-cost-to-the-typist thanks to maximal inferencing) could be positively impactful on intricate code-bases such as the ones likely to be attacked in or ported to Zig
The text was updated successfully, but these errors were encountered: