D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 15546 - Spurious circular reference Error when using Mixin Template
Summary: Spurious circular reference Error when using Mixin Template
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 Linux
: P3 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-01-10 18:40 UTC by Puneet Goel
Modified: 2024-12-13 18:46 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 Puneet Goel 2016-01-10 18:40:23 UTC
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;
}
Comment 1 dlangBugzillaToGithub 2024-12-13 18:46:28 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

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

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