Compiler fails to match array literal to byte[] in templated functions (Was: Re: More putrid beef soup (Was: Re: Implicit string lit conversion) to wstring/dstring)

James Miller james at aatch.net
Sun Mar 18 21:13:00 PDT 2012


On 19 March 2012 16:40, H. S. Teoh <hsteoh at quickfur.ath.cx> wrote:
> OK, perhaps the previous subject line of the previous post deterred
> people from actually reading the contents. :-(
>
> Basically, I'm trying to address Andrei's request that this should work
> with my AA implementation:
>
>        int[dstring] aa;
>        aa["abc"] = 1;  // "abc" implicitly deduced as dstring
>
> Currently, for maximum usability, the code allows any type to be
> supplied for the key, as long as it can be implicitly converted to the
> AA's key type. This is implemented as:
>
>        opIndexAssign(K)(Value v, K key) if (implicitConvertible!K) {}
>
> However, this causes a problem with dstring and wstring, because a
> literal like "abc" defaults to string rather than dstring or wstring, so
> when the compiler tries to find a match for opIndexAssign, it sees that
> string can't implicitly convert to dstring, so it produces an error.
>
> This doesn't happen if opIndexAssign was simply:
>
>        opIndexAssign(Value v, Key key) {}
>
> where Key==dstring, because then the compiler implicitly deduces "abc"
> as a dstring.
>
> In order to fix this, one fix is:
>
>        // Key==dstring
>        opIndexAssign()(Value v, Key key) { __opIndexAssignImpl(v,key); }
>        opIndexAssign(K)(Value v, K key)
>                if (implicitConvertible!K && !is(K==string))
>        {
>                __opIndexAssignImpl(v,key);
>        }
>
> How this works is, when the compiler sees "abc", it first tries to match
> opIndexAssign(K=string)(Value,K), defaulting "abc" to string, but the
> signature constraint declines, so the compiler tries
> opIndexAssign()(Value v, dstring key), which matches with "abc" as
> dstring.
>
> This works for string, wstring, and dstring.
>
> However, the compiler seems to handle numerical literals like [1,2,3]
> differently. For example:
>
>        void func(byte[] b) {}
>        func([1,2,3]);          // OK
>
> However:
>
>        void func()(byte[] b) {}
>        func([1,2,3]);          // Does not match template
>
> Because of this, it's basically impossible to make literals like [1,2,3]
> work with AA's with key type byte[], short[], etc., because [1,2,3] will
> never match byte[] in a templated function, and int[] cannot be
> implicitly converted to byte[]. So it is impossible to replicate the
> implicit conversion in code like:
>
>        byte[] b;
>        b = [1,2,3];
>
> without compiler changes. :-(
>
>
> --T

This sounds like a major bug. At compile time, the compiler should
have more than enough information to do the implicit conversion for
templates.

I haven't looked much at the compiler code, but I assume that there is
a semantic pass that does the implicit conversions? Could that be
used/copied to where templates get instantiated?

--
James Miller


More information about the Digitalmars-d mailing list