Open straight-shoota opened 3 years ago
IMO we should go one step further and represent void pointers as some other concrete type, say RawPointer
, and make it so that Pointer(T) < RawPointer
, keeping pointer arithmetic operations in the generic type. This RawPointer
, like Int
and Float
, is never a union root (to prevent unions of different pointers from coalescing into void pointers).
Void*
would still be allowed within libs (maybe outside libs too), but it would be the parser that transforms them into ::RawPointer
s, and any invalid use of Void
results in a parsing error; thus Void
will be gone during semantic analysis.
The main disadvantage is Pointer(T) forall T
will no longer match void pointers, but I don't think this impacts the standard library, since types like Slice(Void)
are ill-formed anyway.
The main purpose of the
Void
type is for C bindings where it represents no value. In Crystal's type system it maps toNil
. The philosophical difference is that aNil
value is still a value and not nothing. Practically, it doesn't have any effect.There should be no reason to use the
Void
type in Crystal code for anything else but C interfaces.And you can't really get a
Void
value in Crystal. It's justNil
.Void
is already disallowed as a field type for lib structs. So why should it be valid in a Crystal struct?I propose to disallow a plain
Void
type from any type restriction in Crystal except for lib functions. The only relevant use case is a void pointer indicating untyped memory. SoPointer(Void)
should be allowed. SubsequentlyVoid
should probably be valid as a generic type argument for any generic type.But any type restriction
x : Void
just doesn't make sense, nor doesuninitialized Void
which can even break the compiler (#5364).Previous discussion: #10146