www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 15546] New: Spurious circular reference Error when using

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

          Issue ID: 15546
           Summary: Spurious circular reference Error when using Mixin
                    Template
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: puneet coverify.org

I am getting a circular reference error when using a mixin template that
basically envelopes a string mixin. When the underlying string mixin is mixed
directly, no such error occurs.

I reduced the testcase, but it is still 90 lines long. I tried hard but could
not reduce further. I hope the code snippet is workable.

To replicate:

$ dmd -c test.d
test.d-mixin-55(56): Error: circular reference to 'test.R_inst._B_inst'
test.d(78): Error: mixin test.B.MixT!() error instantiating
test.d(66): Error: mixin test.A.MixT!() error instantiating

# string mixin compiles without errors
$ dmd -version=STRING -c test.d


// module test.d
public template Access(A...) {
  static assert(A.length == 0);
  enum string Access = "";
} 
public template Accessor(T, string U="this", size_t I=0) {
  static if(I == (__traits(derivedMembers, T).length)) {
    enum string Accessor = "";
  }
  else {
    enum string mem = __traits(derivedMembers, T)[I];
    static if(mem == "this" || mem == "inst" || mem == "_inst") {
      enum string Accessor = Accessor!(T, U, I+1);
    }
    else {
      enum string Accessor =
    "mixin(Accessor!(Access!(__traits(getAttributes, "
    ~ U ~ "." ~ mem ~ ")),  \"" ~ mem ~ "\", \"" ~ U ~ "\"));
        " ~ Accessor!(T, U, I+1);
    }
  }
}
public template Accessor(string A, string M, string U) {
  static if(U == "_inst" || U == "inst") enum string SCOPE = "static";
  enum string Accessor = A ~ " static final auto " ~ M[1..$] ~
    "() {synchronized(" ~ U ~ ") return " ~ U ~ "." ~ M ~ ";}"
    ~ A ~ " static final void " ~ M[1..$] ~
    "(typeof(" ~ U ~ "." ~ M ~ ") val) {synchronized(" ~ U ~ ") " ~
    U ~ "." ~ M ~ " = val;}";
}

template Mix(T, U, size_t I=0) {
  static if(I == (__traits(derivedMembers, T).length)) {
    enum string Mix = "public static Single inst() {
return root.SingleRoot._" ~ U.stringof ~ "_inst;
}\n" ~  Accessor!(T, "inst");
  }
  else {
    enum string mem = __traits(derivedMembers, T)[I];
    static if(mem == "__ctor" || mem == "__dtor") {
      enum string Mix = Mix!(T, U, I+1);
    }
    else {
      enum string Mix = Mix!(T, U, I+1) ~
    "static if(Access!(__traits(getAttributes, " ~
    T.stringof ~ "." ~ mem ~ ")) != \"none\") {
static private ref " ~ " auto " ~ " " ~ mem ~ "() {
     return inst." ~ mem ~ ";
       }
}";
    }
  }
}

mixin template MixT() {
  mixin(Mix!(Single, typeof(this)));
}

class A {
  static class Single {
    int _a;
  }
  version(STRING) {
    mixin(Mix!(Single, A));
  }
  else {
    mixin MixT;
  }
}
class B
{
  static class Single {
    bool _b;
  }
  version(STRING) {
    mixin(Mix!(Single, B));
  }
  else {
    mixin MixT;
  }
}

Root root;

class Root {
  R_inst SingleRoot() { return new R_inst; }
}
class R_inst {
  A.Single _A_inst;
  B.Single _B_inst;
}

--
Jan 10