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