www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Struct constructor, static opCall and object opCall

I'm challenging to fix title issue.

Related issues in bug tracking system:
http://d.puremagic.com/issues/show_bug.cgi?id=3680
http://d.puremagic.com/issues/show_bug.cgi?id=4053
http://d.puremagic.com/issues/show_bug.cgi?id=4253

I think that follows are correct behavior of dmd.
Please point out to me any misunderstanding.

1. Default constructor should always defined.
   It is enhancement request of Issue 3690, but I think this is D scheme.
   Therefore this issue should mark as bug.
   -------
   S s; // Now variable s is initialized with S.init
   S()  // Therefore S() should always equals to  S.init
   --------

2. User constructors and static opCalls should always conflict.
   Object construction using static opCall is old sheme, so mixing constructors
   and static opCalls should always be illegal. Using only one scheme
is still legal.

3. Object opCall (non static method) should be invisible from type name.

4. Constructors should be invisible from object.


Following code is test case.
Comment-out lines are failed with current dmd.
--------
void test1()
{
    static struct Foo1
    {
    }

    Foo1 foo1;
    Foo1 foo1_2 = Foo1();   // struct literal
    static assert(!__traits(compiles, Foo1(1)));

    static assert(!__traits(compiles, foo1()));
    static assert(!__traits(compiles, foo1(1)));
}
void test2()
{
    static struct Foo2
    {
        this(int n){}
    }

    Foo2 foo2;
    Foo2 foo2_2 = Foo2();       // struct literal
    Foo2 foo2_3 = Foo2(1);      // constructor call

    static assert(!__traits(compiles, foo2()));
//  static assert(!__traits(compiles, foo2(1)));
}
void test2a()
{
    static struct Foo2a // alternation of Foo2
    {
        static Foo2a opCall(int n){ Foo2a foo2a; return foo2a; }
    }

    Foo2a foo2a;
//  Foo2a foo2a_2 = Foo2a();    // struct literal
    Foo2a foo2a_3 = Foo2a(1);   // static opCall

    static assert(!__traits(compiles, foo2a()));
    foo2a(1);   // static method call from object
}
void test2c()
{
    static struct Foo2c // conflict version
    {
        this(int n){}
        static Foo2c opCall(int n, int m){ Foo2c foo2c; return foo2c; }
    }

    Foo2c foo2c;
//  Foo2c foo2c_2 = Foo2c();    // struct literal
    Foo2c foo2c_3 = Foo2c(1);   // constructor call
    static assert(!__traits(compiles, Foo2c(1,2))); // static opCall
    // It seems to me that should always conflict with constructor call.
    // Because construction by static opCall is old feature

    static assert(!__traits(compiles, foo2c()));
//  static assert(!__traits(compiles, foo2c(1)));
//  foo2c(1,2); // static method call from object
    // This should pass.
    // Constructor should not visible from object, so static opCall
should match.
}

void test3()
{
    static struct Foo3
    {
        this(int n){}
        int opCall(int n){ return 0; }
    }

    Foo3 foo3;
//  Foo3 foo3_2 = Foo3();       // struct literal
    Foo3 foo3_3 = Foo3(1);      // constructor call

    static assert(!__traits(compiles, foo3()));
//  assert(foo3(1) == 0);       // object opCall
}
void test3c()
{
    static struct Foo3c
    {
        this(int n){}
        int opCall(int n){ return 0; }
        static Foo3c opCall(int n, int m){ Foo3c foo3c; return foo3c; }
    }

    Foo3c foo3c;
//  Foo3c foo3c_2 = Foo3c();    // struct literal
    Foo3c foo3c_3 = Foo3c(1);   // constructor call, should not
conflict with opCall
    static assert(!__traits(compiles, Foo3c(1,2))); // static opCall
    // It seems to me that should always conflict with constructor call.
    // Because construction by static opCall is old feature

    static assert(!__traits(compiles, foo3c()));
//  assert(foo3c(1) == 0);      // opCall
//  foo3c(1,2); // static method call from object
}

void test4()
{
    static struct Foo4
    {
        int opCall(int n){ return 0; }
        static Foo4 opCall(int n, int m){ Foo4 foo4; return foo4; }
    }

    Foo4 foo4;
//  Foo4 foo4_2 = Foo4();       // struct literal
//  static assert(!__traits(compiles, Foo4(1)));
    Foo4 foo4_4 = Foo4(1,2);    // static opCall

    static assert(!__traits(compiles, foo4()));
    assert(foo4(1) == 0);       // opCall
    foo4(1,2);  // static method call from object
}

void main()
{
    test1();
    test2();
    test2a();
    test2c();
    test3();
    test3c();
    test4();
}
--------

Kenji Hara
May 18 2011