ranges of characters and the overabundance of traits that go with them

Jonathan M Davis via Digitalmars-d digitalmars-d at puremagic.com
Fri Mar 17 04:14:53 PDT 2017


On Friday, March 17, 2017 10:25:22 Andrei Alexandrescu via Digitalmars-d 
wrote:
> On 3/17/17 12:42 AM, Jonathan M Davis via Digitalmars-d wrote:
> > And
> > checking isSomeString with an enum is perfectly valid. It's just that
> > we'd like it to be false, whereas right now it's true.
>
> That hasn't been the case for long, and there can't be many designs
> relying on that. I think this is one of those places where we can break
> compatibility if there's enough reason. -- Andrei

Actually, it's been that way for years (since at least  2012), and I suspect
that it's been that way since the beginning, since it would need to
explicitly check for enums to not work with enums thanks to the fact that it
checks for implicit conversion and then disallows the implicit conversions
that we don't want (like for static arrays and user-defined types). And
sadly, when Kenji tried to fix it, I argued against it, because I didn't
understand the issue well enough:

https://issues.dlang.org/show_bug.cgi?id=8508

At the time, I thought that we needed isSomeString to be true for enums in
order to be able to templatize functions that took string, whereas that's
actually a bad idea, because then you didn't actually convert the enum to a
string, and the function is in serious risk of doing the wrong thing with
enums (either by not compiling or by resulting in a value that's not a valid
enum value but still has the enum's type), though it will work in some
cases. Also, templatizing the function and checking isSomeString breaks code
anyway, because then it doesn't accept static arrays or user-defined types
that implicitly convert to string, whereas it did before. And as discussed
in this thread, as far as I can tell, in the general case, the only way to
safely templatize a function that took a string is to include an overload
that templatizes on the character type so that the implicit conversion is
done at the call site. Given all of that, it was ignorant and ultimately
detrimental of me to argue to that isSomeString needed to be true for enums,
and it's been that way for several years at least. If I'd been smarter at
the time, this would have been fixed years ago.

However, in most cases, I would expect that fixing isSomeString to be false
for enums would simply work. Anything range-based wouldn't care, because
enums don't pass isInputRange anyway, and a decent chunk of the time, using
an enum in place of a string would result in a compilation error, which
means that that code wouldn't be broken but would instead catch the enum at
the template constraint instead of not compiling when the template is
instantiated. Really, the only code that we'd be at risk of breaking would
be code that was written with the full understanding that enums passed
isSomeString and did something like

auto foo(S)(S str)
    if(isSomeString!S)
{
    static if(is(T == enum))
        return foo!(StringTypeOf!T)(str);
    else
    {
        ...
    }
}

or that just so happens to use the subset of string transformations or
function calls which work with enums.

So, if we don't fix isSomeString, and we want our code to be fully correct,
we're left with the need to check is(T == enum) in non-range-based code in
order to correctly handle enums (as in the example above or by disallowing
enums) or risk code not compiling or being subtly incorrect when enums are
used with it. And if we do fix isSomeString, then we'll probably have an
occasional function call that happened to work with enums in spite of the
problems and would then break - though the breakage would then be easy to
fix.

So, I would love to fix isSomeString, and I think that the resulting
breakage would be minimal, but I don't expect it to be zero. So, if you
think that that presumably small amount of code breakage is acceptable, I
would gladly create a PR to fix isSomeString and isNarrowString to be false
for enums. I think that it's clear that in the long run, we'll be better off
for it. It's just that we have no way to make this change and guarantee that
we're not breaking anyone's code, much as in many (most?) cases, I would
expect the code to be wrong anyway.

- Jonathan M Davis



More information about the Digitalmars-d mailing list