-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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: improved semantics for noreturn
-like types
#15909
Comments
Duplicate/related #13807 |
I think we need to reconsider the proposed semantics of pointers to noreturn types. As @jacobly0 pointed out, a pointer isn't required to point to valid memory unless it is dereferenced. As I see it, the logical extension of those semantics for pointers to noreturn types is that a pointer of type This also resolves an inconsistency in the current proposal when viewing a slice as a struct { ptr: [*]noreturn, len: usize } By the struct rule and originally proposed pointer rule this should be a noreturn type. However, there is a valid possible value of this type, the empty slice. Another issue with the current semantics that @jacobly0 brought up is that determining if a pointer is noreturn equivalent or not could cause dependency loops, e.g. due to needing to analyze struct field types in order to determine if a struct is noreturn equivalent. To summarize for all pointer types:
|
This proposal needs a set of test cases to act as acceptance criteria and so we have some very specific semantics to decide between. |
This is a bit odd, because this value doesn't actually exist: see ziglang#15909. This gets all the empty enum/union behavior tests passing. Also adds an assertion to `Sema.analyzeBodyInner` which would have helped figure out the issue here much more quickly.
This is a bit odd, because this value doesn't actually exist: see ziglang#15909. This gets all the empty enum/union behavior tests passing. Also adds an assertion to `Sema.analyzeBodyInner` which would have helped figure out the issue here much more quickly.
This is a bit odd, because this value doesn't actually exist: see #15909. This gets all the empty enum/union behavior tests passing. Also adds an assertion to `Sema.analyzeBodyInner` which would have helped figure out the issue here much more quickly.
This is a bit odd, because this value doesn't actually exist: see #15909. This gets all the empty enum/union behavior tests passing. Also adds an assertion to `Sema.analyzeBodyInner` which would have helped figure out the issue here much more quickly.
This is a bit odd, because this value doesn't actually exist: see ziglang#15909. This gets all the empty enum/union behavior tests passing. Also adds an assertion to `Sema.analyzeBodyInner` which would have helped figure out the issue here much more quickly.
This is a bit odd, because this value doesn't actually exist: see #15909. This gets all the empty enum/union behavior tests passing. Also adds an assertion to `Sema.analyzeBodyInner` which would have helped figure out the issue here much more quickly.
This is a small nitpick, but I'd suggest a name like "vacuous types" instead of noreturn types. Because, you can in fact return them, they just happen to be empty :) |
This is in a sense a continuation of #3257. That issue laid some of the groundwork for the current status of
noreturn
and similar types, but there are a few things missing. Also, thanks to @ifreund for helping me figure out some of the details of this.Lots of types can be constructed which are similar to
noreturn
. In type theory terms, they are "empty types": types for which no values exist. I'll call these types "noreturn-like". Here's an exhaustive list of types which should be considered noreturn-like (note the special cases around pointers mentioned at the end):noreturn
enum {}
enum(T) {}
for anyT
error {}
union
/extern union
where all fields are noreturn-like (including the case where the union has no fields)E!T
whereE
andT
are both noreturn-like (so,error{}!T
)[n]T
/@Vector(n, T)
whereT
is noreturn-like andn != 0
*T
/[*]T
(and any qualifiers) whereT
is noreturn-like[]T
has the value&.{}
so is not noreturn-like, but rather zero-bit OPV[*c]T
has the valuenull
so is not noreturn-like. In principle it's zero-bit OPV, but this is a footgun, so instead is disallowed.Currently, most of these aren't "truly" considered noreturn-like. Such types should terminate semantic analysis when found (akin to
unreachable
). Additionally,undefined
should not coerce to noreturn-like types, to avoid being able to actually "construct" them without terminating analysis.We currently have the restriction that (at function scope)
var x: T = ...
, whereT
is noreturn-like, is a compile error. This, however, is inconsistent -const x: T = ...
is allowed, and moreover, so isvar x = @as(T, ...)
. I propose that we remove this needless restriction. Allocs for noreturn-like types can be special-cased to emit no AIR instructions, and analysis will terminate before we attempt to store to one, as by that point we will have had an instruction whose result type is the child type.Note, however, that global
var
s may not be of a noreturn-like type, nor may a value of a noreturn-like type be exported or marked extern. This is a compile error.One last notable change in semantics here is that switching on a noreturn-like enum is no longer supported in the same way that it is in status quo. The idea currently is that you turn such an enum into the true
noreturn
type using an empty switch,switch (e) {}
. This code will still be accepted under this proposal, but for a different reason: it's never analyzed! The momente
is created, semantic analysis terminates, since we reached a noreturn instruction.The text was updated successfully, but these errors were encountered: