No we should not support enum types derived from strings

Jonathan M Davis newsgroup.d at jmdavisprog.com
Wed May 12 10:36:59 UTC 2021


On Tuesday, May 11, 2021 12:37:20 PM MDT Meta via Digitalmars-d wrote:
> On Tuesday, 11 May 2021 at 16:44:03 UTC, Andrei Alexandrescu
>
> wrote:
> >> Again with moving the goalposts.
> >
> > To clarify: you can't make up your own definitions as you go so
> > as to support the point you're making at the moment. You can't
> > go "oh, call it something else than a type, my point stays".
> > No. Your point doesn't stay.
> >
> > By the same token you can't make up your own definition of what
> > subtyping is and isn't. Value types and reference types are
> > well-trodden ground. You can't just claim new terminology and
> > then prove your own point by using it.
>
> I apologize for injecting myself into this conversation, but with
> all due respect, what the hell are you talking about? Everything
> Deadalnix is saying makes perfect sense - it's basic type theory,
> and yet you're accusing him of moving goalposts and making up
> definitions, etc. The problem is that `isSomeString` doesn't
> respect the LSP and the template constraints on the relevant
> stdlib functions for enums are a hack to work around that. End of
> story. if `isSomeString` was defined sensibly, these template
> constraint hacks would not have to exist.
>
> All the bluster about `popFront` on enum strings, etc. is
> completely irrelevant, and is a red herring anyway (as was
> already explained).
>
> I'm sorry for being so blunt, but this conversation is painful to
> read.

Having isSomeString accept types that implicitly converted to string would
be a disaster. Templates do not operate on implict conversions - or even on
subtypes. They operate on the exact type they're given. You can, of course,
write a template constraint which checks for implicit conversions, but you
still don't get the implicit conversion when the template is instantiated.
You get the original type. This has a number of implications, but in
general, it leads to bugs if templates check for implicit conversions
instead of exact types. In particular, any templated function which checks
for an implicit conversion then needs to force the implicit conversion, or
it will likely not work properly - be it because you get compilation errors,
or because the original type compiles with the same code but does not behave
the same way as the type from the implicit conversion which was not actually
made.

In fact, IIRC, at one point, isSomeString _did_ work with enums, and we
fixed it so that it didn't, because it was causing problems. Also, IIRC, it
was my fault that it was ever made to work with enums, and I very much
regret that.

In general, implicit conversions have no business in template constraints.
Obviously, there are exceptions to that, but in general, there will be fewer
bugs if the conversions are done explicitly by the code instantiating the
template. The reason that it's done in Phobos as much as it is is primarily
because of code that was originally not generic which was later templatized
(often because it took string and was changed to work on multiple string
types or to work on general ranges of characters). And in most cases where
we've tried to templatize functions without breaking code, we've had
problems because of the implicit conversions that worked before.
std.traits.isConvertibleToString is one such abomination which came out of
that (its use usually results in code that slices local variables and
escapes them, which is really bad). IIRC, that was done by Walter, and if
he's making mistakes like that with regards to implicit conversions and
templated code, what do you think the average D programmer is doing?

The main reason for bringing up popFront and enums is to show that that
enums with a base type of string are not actually strings, and treating them
as if they were causes serious problems. There are of course places where
that sub-typing results in implicit conversions, but templates do not work
that way, and trying to force it is very problematic. The proliferation of
template constraint and static if complexity that Andrei is complaining
about with regards to stuff like format is the result of that, and it's the
kind of code that's very hard to get right. Simply not trying to support
those implicit conversions with templated functions _significantly_ reduces
the complexity of such code with the only cost being that the code
instantiating the template will have to use cast(string) on the enum value.

- Jonathan M Davis





More information about the Digitalmars-d mailing list