Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spurious circular reference Error when using Mixin Template #19087

Open
dlangBugzillaToGithub opened this issue Jan 10, 2016 · 0 comments
Open
Labels

Comments

@dlangBugzillaToGithub
Copy link

Puneet Goel (@puneet) reported this on 2016-01-10T18:40:23Z

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

Description

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;
}
" ~  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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant