D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 19900 - Rewrites for unary index operator not done per the spec
Summary: Rewrites for unary index operator not done per the spec
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P3 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-05-24 15:28 UTC by Bolpat
Modified: 2024-12-13 19:03 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Bolpat 2019-05-24 15:28:45 UTC
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 Bolpat 2019-05-27 00:51:31 UTC
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 dlangBugzillaToGithub 2024-12-13 19:03:32 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/dmd/issues/19570

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB