DIP 1017--Add Bottom Type--Final Review
Johannes Loher
johannesloher at fg4f.de
Thu Jan 17 23:45:19 UTC 2019
Am 18.01.19 um 00:34 schrieb H. S. Teoh:
> I don't think we can realistically force empty structs `struct A {}` and
> `struct B {}` to be the same type, because even though they are arguably
> both unit types, they can still be distinguished from each other by
> name. This distinction is also more than just mere convention; it plays
> a crucial role in UDAs, for example:
>
> struct DontSerialize {}
> struct SerializeAsBytes {}
>
> struct Data {
> @DontSerialize uint runtimeId;
> @SerializeAsBytes int payload;
> }
>
> If we collapsed both structs into a single Unit type, the UDA mechanism
> would completely fall apart.
>
> Furthermore, types in D cannot be identified merely by their constituent
> parts. For example:
>
> struct CartesianCoors {
> float x;
> float y;
> }
>
> struct PolarCoors {
> float theta;
> float radius;
> }
>
> Technically, both structs are products of two floats, but that does not
> make them the same thing, because the values of their constituent
> components are interpreted differently and should not be confused one
> for another.
I completely agree. D's types are not structural types.
> At the very least, it would seem that the *name* of the type plays an
> essential role in its identification. I.e., it's almost as if a struct
> declaration is actually defining a type that, in addition to the types
> of its fields, contains also an implicit string type identifying the
> name of the struct. Or alternatively, we're dealing with a type system
> where types are additionally decorated with string identifiers that
> distinguish otherwise-identical types from each other. (Or it could be
> that I've no idea what I'm talking about, and this is the consequence of
> this community having very few people who actually know type theory
> thoroughly enough to be able to work out a sane solution to all of these
> issues. :-P)
This actually sounds like reasonable way to view it. You can even get
that additional field at runtime (typeid).
> In any case, coming back to TBottom*, another issue that makes me wary
> of defining TBottom* == void is the top pointer `void*`. Since any
> pointer implicitly converts to `void*`, this means TBottom* implicitly
> converts to `void*` too, which in turn means `void` should also
> implicitly convert to `void*`:
>
> void procedure(...) { }
>
> void* ptr = procedure(...); // valid if TBottom* == Unit == void
>
> I think the problems that such a construct would cause would far
> outweigh whatever benefits that we may have reaped from introducing Unit
> and Bottom types!
You are absolutely correct. I don't think it makes any sense to define
`void` to be `Tbottom*` if we don't fix the problem with `void*`. I am
even tend to think that in this case it might also not be reasonable to
give `void` a value at all because it would make the difference in
meaning of void in `void fun();` and `void*` even more apparent. This
could also be a good thing though because at the moment almost nobody
realizes that there is a difference.
More information about the Digitalmars-d
mailing list