I've been trying to correctly implement the interpreter patten/expression templates in D (for reference this is a summary of the C++ interpreter patten can be found here http://www.drdobbs.com/184401627). I've run into a problem and I'm not sure if it's a compiler bug or not. The testcase is:

struct BinaryOp(L,string op,R) {
        pragma(msg,"Instansiating " ~ typeof(this).stringof);
        BinaryOp!(typeof(this),s,R1) opBinary(string s,R1)(R1 r) {
pragma(msg,"Instansiating BinaryOp.opBinary ~L.stringof ~ op ~ R1.stringof);
                return typeof(return)();
        }
}

struct Leaf {
        BinaryOp!(typeof(this),s,R) opBinary(string s,R)(R r) {
                pragma(msg,"Instansiating leaf.opBinary(" ~ R.stringof ~ ")");
                return typeof(return)();
        }
};

void main() {
        Leaf v1,v2,v3;
        pragma(msg,"");
        pragma(msg,"======= This Compiles ======");
        v1*(v2*v3);
        pragma(msg,"");
        pragma(msg,"======= This Doesn't ======");
        (v1*v2)*v3;
}
Output:
======= This Compiles ======
Instansiating BinaryOp!(Leaf,s,Leaf)
Instansiating leaf.opBinary(Leaf)
Instansiating BinaryOp!(Leaf,s,BinaryOp!(Leaf,s,Leaf))
Instansiating leaf.opBinary(BinaryOp!(Leaf,s,Leaf))

======= This Doesn't ======
Error: recursive template expansion for template argument BinaryOp!(Leaf,s,Leaf)

I've tracked the problem down to the return type of BinaryOp.opBinary. Clearly putting BinaryOp!(typeof(this),...) would be a Bad Thing in the main template body but opBinary is a template that may or may not be instantiated so it shouldn't automatically lead to runaway instantiation. It seems the compiler is a little bit overzealous in making sure that such runaway instantiations do not happen.

Is this a bug? Should I file it? Here's what I think a minimal test case might look like:

struct A(T1) {
        void templateFunc(T2)(T2 a) {
                 alias A!(typeof(this)) error;
        }
}


void main() {
         A!int a;
         a.templateFunc!int(0);
}



Reply via email to