-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
RLS has reached a point where it works really nicely as the primary mechanism of type inference; so much so that we have removed anonymous struct types without significant breakage in the wild. The idea here was that anonymous struct type coercions were a legacy feature from before we used result types for type inference.
Zig has two more constructs which obviously fit this bill: null
and undefined
.
null
is unfortunately necessary (at least with how ==
works today) for x == null
to work: since ==
doesn't forward a result type to either operand, the RHS of ==
needs to be able to stand without a result type, so null
as a standalone expression needs to work. (This could change by changing how ==
works a little, but that's out of scope for this proposal.)
However, undefined
does not match this description. Comparing any value to undefined
always results in @as(bool, undefined)
(unless the value's type is zero-bit, in which case the comparison is redundant), so it is not a useful construct. In fact, there is no context in which undefined
is useful without a result location:
a + undefined
either invokes Illegal Behavior or returnsundefined
- likewise for all binary operators like
+
,/
,>>
, etc - likewise for unary operators like
-
,~
- likewise for math-ey builtins like
@divExact
,@abs
, etc - passing it to an
anytype
parameter can only be used by checking for@TypeOf(x) == @Type(.undefined)
, which is not useful - initializing an untyped
const
withundefined
just aliasesundefined
, which is not useful
Given this, I am proposing the following change to the language:
- The expression
undefined
always requires a known result type. It is a compile error ifundefined
does not have a known result type.- So,
@TypeOf(undefined)
is a compile error.
- So,
- The
.undefined
variant is removed fromstd.builtin.Type
.
This simplifies the language by removing a type tag, which benefits the language spec (one less type whose behavior must be defined!) and generic Zig code (exhaustively switching on @typeInfo
is simpler). It may also make undefined
a little easier to understand for beginners, since they'll never have to face the awkward concept of @Type(.undefined)
; they'll get a useful compile error as soon as they try to misuse the undefined
identifier.
Note that under this proposal, undefined
retains its status as a builtin identifier which is not a syntactic keyword.
EDIT
I have thought of a realistic use case this will break:
const x = if (something) my_u32 else undefined;
I think code like this ought to have a type annotation for clarity anyway, so if anything, I think this is good, but it is a way in which this proposal is more breaking than I thought.
Note also that #22182 would also break this snippet if accepted.