Comment #0 by qs.il.paperinik — 2019-05-24T15:28:45Z
The rewrites for unary operator before a slice expression reject valid code.
Only the part tagged with "For backward compatibility" properly compiles.
struct S
{
static struct Slice { size_t l, u; }
Slice opSlice(size_t l, size_t u) { return Slice(l, u); }
S opIndexUnary(string op)(Slice slice)
{
return S.init;
}
}
unittest
{
S a;
S b = ++a[1 .. 2]; // fails
S c = a.opIndexUnary!("++")(a.opSlice(i, j));
}
Comment #1 by qs.il.paperinik — 2019-05-27T00:51:31Z
Some tests [1] show that in the rewrites of opSlice sometimes require a template parameter for the dimension to be performed by the compiler.
The cases I found in [1] are opIndexUnary, opIndexOpAssgin, and opIndex. The rewrite for opIndexAssign, for some reason, is unaffected.
[1]:
struct TestStruct(bool opSliceWithDim, bool opDollarWithDim)
{
static if (opSliceWithDim)
{
size_t[2] opSlice(size_t dim)(size_t l, size_t u) { return [ l, u ]; }
}
else
{
size_t[2] opSlice(size_t l, size_t u) { return [ l, u ]; }
}
static if (opDollarWithDim)
{
enum size_t opDollar(size_t dim) = dim;
}
else
{
enum size_t opDollar = 1;
}
void opIndexUnary(string op)() { }
void opIndexUnary(string op)(size_t index) { }
void opIndexUnary(string op)(size_t[2] slice) { }
void opIndexAssign(int rhs) { }
void opIndexAssign(int rhs, size_t index) { }
void opIndexAssign(int rhs, size_t[2] slice) { }
void opIndexOpAssign(string op)(int rhs) { }
void opIndexOpAssign(string op)(int rhs, size_t index) { }
void opIndexOpAssign(string op)(int rhs, size_t[2] slice) { }
int opIndex() { return 0; }
int opIndex(size_t index) { return 0; }
int opIndex(size_t[2] slice) { return 0; }
}
static foreach (enum bool opSliceWithDim; [ false, true ])
static foreach (enum bool opDollarWithDim; [ false, true ])
{
unittest
{
alias S = TestStruct!(opSliceWithDim, opDollarWithDim);
S s = S.init;
int value = 0;
s[] = value; // same as s.opIndexAssgin(value);
s[1] = value; // same as s.opIndexAssgin(value, 1);
s[3 .. $] = value; // same as s.opIndexAssign(value, s.opSlice(3, s.opDollar))
s[] += value; // same as s.opIndexOpAssgin!"+"(value);
s[1] += value; // same as s.opIndexOpAssgin!"+"(value, 1);
static assert(opSliceWithDim == __traits(compiles,
{
s[3 .. $] += value; // same as s.opIndexOpAssgin!"+"(value, s.opSlice(3, s.opDollar));
}));
++s[]; // same as s.opIndexUnary!"++"();
++s[1]; // same as s.opIndexUnary!"++"(1);
static assert(opSliceWithDim == __traits(compiles,
{
++s[3 .. $]; // same as opIndexUnary!"+"(s.opSlice(3, s.opDollar));
}));
value = s[];
value = s[1];
static assert(opSliceWithDim == __traits(compiles,
{
value = s[3 .. $]; // same as s.opIndex(s.opSlice(3, s.opDollar));
}));
}
}
Comment #2 by robert.schadek — 2024-12-13T19:03:32Z