[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
Fri May 19 02:34:43 PDT 2017


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

--- Comment #9 from uplink.coder at googlemail.com ---
(In reply to Andrei Alexandrescu from comment #6)
> (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.

I can give you a access to ref at ctfe assuming you never modify the literal
given

--


More information about the Digitalmars-d-bugs mailing list