[Issue 17351] Static const array can't be evaluated at compile time when passed as ref argument

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Sat Apr 29 06:46:26 PDT 2017


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

--- Comment #6 from Andrei Alexandrescu <andrei at erdani.com> ---
(In reply to ag0aep6g from comment #5)
> You have to initialize the int[3], as you did with the int. I suppose the
> compiler assumes that you're going to do run-time initialization via `static
> this` when you're not initializing in the declaration. In that case, the
> value can't be used at compile time, obviously.

Cool. Indeed this works even with structs:

bool fun(const int a) { return true; }
bool gun(const int[3] a) { return true; }
bool hun(const S a) { return true; }

struct S { int a; }

void main()
{
    static const int x1 = 1;
    static assert(fun(x1));
    static const int[3] x = [1, 2, 3];
    static assert(gun(x));
    static const S x2 = S(1);
    static assert(hun(x2));
}

So we're in good shape.

> [...]
> > bool fun(const int a) { return true; }
> > bool fun(ref const int a) { return true; }
> > 
> > void main()
> > {
> >     static const int x1 = 1;
> >     static assert(fun(x1));
> > }
> > 
> > Here, the code attempts to avoid the problem by overloading on ref. However,
> > the call is resolved to the ref version even though it does not go through.
> > This should definitely be fixed, otherwise we're in the position of making a
> > workaround impossible.
> 
> You can work around by using an enum instead of a static const.

Not an option. The context is the following. We're looking at lowering all
array comparisons like this:

e1 == e2 -----> __equals(e1, e2)
e1 != e2 -----> !__equals(e1, e2)

Then implement __equals as a template in object.d. There are a number of
challenges related to that, which we solved together with Walter. The current
approach defines these overloads:

bool __equals(L, R)(L[] lhs, R[] rhs);
bool __equals(L, R, n1)(auto ref L[n1] lhs, R[] rhs);
bool __equals(L, R, n2)(auto ref L[] lhs, auto ref R[n2] rhs);
bool __equals(L, R, n1, n2)(auto ref L[n1] lhs, auto ref R[n2] rhs);

This approach has a number of benefits compared to the status quo, among which
much better speed (and as a perk fewer dynamic allocations for array literals
when passed in comparisons such as arr == [1, 2, 3]).

The auto ref is necessary so we don't copy arrays into the comparison
functions, yet we still work with rvalue arrays.

Now, Lucia (@somzzz) has gotten to the point where it all passes druntime and
phobos unittests, but breaks in exactly one point in the compiler. It can be
reduced to this:

static const int[3] x = [1, 2, 3];
static assert(x == x);

Here, the compiler chooses the "ref" version even though it is not compilable.
The version with rvalues should be taken and used.

--


More information about the Digitalmars-d-bugs mailing list