www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 7868] New: derivedMembers/static if regression

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7868

           Summary: derivedMembers/static if regression
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: regression
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: code klickverbot.at


--- Comment #0 from klickverbot <code klickverbot.at> 2012-04-08 20:31:56 PDT
---
The following snippet compiles on DMD 2.058, but fails using DMD 2.059 Git
(d16cfe5):

---
mixin template A() {
  alias typeof(this) This;

  pragma(msg, "This is true: ", is(B!This));

  static if (is(B!This)) {
    B!This b;
  } else {
    pragma(msg, "But wasn't in the static if.");
  }

  pragma(msg, "Here again, though: ", is(B!This));
}

template B(T) {
  mixin({
    foreach (name; __traits(derivedMembers, T)) {}
    return "struct B {}";
  }());
}

struct C {
  int d;
  mixin A!();
}

auto e = C.init.b;
---

DMD 2.059 prints:
---
This is true: true
But wasn't in the static if.
Here again, though: true
test.d(27): Error: not a property C(0).b
---

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 08 2012
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7868


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |bugzilla digitalmars.com
         Resolution|                            |INVALID


--- Comment #1 from Walter Bright <bugzilla digitalmars.com> 2012-04-08
21:01:26 PDT ---
This line is the problem:

  static if (is(B!This)) {

B!This is not a type, and 'is' expressions expect a type. Hence, it is false.
Replacing it with:

  static if (__traits(compiles, B!This)) {

and the example works.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 08 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7868



--- Comment #2 from Kenji Hara <k.hara.pg gmail.com> 2012-04-09 00:23:12 PDT ---
(In reply to comment #1)
 This line is the problem:
 
   static if (is(B!This)) {
 
 B!This is not a type, and 'is' expressions expect a type. Hence, it is false.
 Replacing it with:
 
   static if (__traits(compiles, B!This)) {
 
 and the example works.
No, this is resolved-invalid forward reference issue. semantic of C semantic of mixin A!() semantic of B!This (== B!C) semantic of __traits(derivedMembers, T) (T == C) // forward reference of C! If remove the line in B: foreach (name; __traits(derivedMembers, T)) {} you can compile it. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 09 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7868


klickverbot <code klickverbot.at> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|INVALID                     |
             Status|RESOLVED                    |REOPENED
         Resolution|INVALID                     |


--- Comment #3 from klickverbot <code klickverbot.at> 2012-04-09 02:11:41 PDT
---
B!This is a type, namely an empty struct – B is an eponymous template.

--- Comment #4 from klickverbot <code klickverbot.at> 2012-04-09 02:11:41 PDT
---
B!This is a type, namely an empty struct – B is an eponymous template.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 09 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7868


klickverbot <code klickverbot.at> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|INVALID                     |
             Status|RESOLVED                    |REOPENED
         Resolution|INVALID                     |


--- Comment #3 from klickverbot <code klickverbot.at> 2012-04-09 02:11:41 PDT
---
B!This is a type, namely an empty struct – B is an eponymous template.

--- Comment #4 from klickverbot <code klickverbot.at> 2012-04-09 02:11:41 PDT
---
B!This is a type, namely an empty struct – B is an eponymous template.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 09 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7868



--- Comment #5 from klickverbot <code klickverbot.at> 2012-04-09 02:37:16 PDT
---
Sorry for the duplicate comments. I reopened the bug because I think it is a
genuine regression:

It's not like B!This could not be instantiated at all; if you hoist B!This b;
out of the conditional, the above snippet compiles fine (also illustrated by
the is() expressions in the msg pragmas returning true). Only from the exp of a
StaticIfCondition, instantiation fails, which is very inconsistent and
bug-prone behavior.

Also, I'd like to note that this has worked in a stable fashion for a number of
DMD releases now (it has been in the Thrift code since the beginning of last
summer's GSoC), so if you decide that an instantiation outside the exp of a
StaticIfCondition should not compile either, please consider mentioning this as
a breaking change in the release notes.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 09 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7868


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|REOPENED                    |RESOLVED
         Resolution|                            |INVALID


--- Comment #6 from Walter Bright <bugzilla digitalmars.com> 2012-04-09
16:30:09 PDT ---
Ok, here's what's happening (took me a couple hours).

As you said, is(B!C) is relying on the eponymous name trick. The eponymous name
trick relies on knowing the names of all the members of a template. So,

   is(B!C)

cannot resolve to an eponymous name until all the members are resolved. But
inside B(T), we have an __traits(derivedMembers, C). Now, in order to produce
all of the members, it has to determine all the members. But some of those
members are inside a static if, which also relies on knowing all the members.

Hence, it fails. And, it fails silently because it fails inside an 'is'
expression, which gags errors.

Why did this not fail on older versions? Because I recently fixed
__traits(derivedMembers) to check for the member list being complete. There
were multiple bugzilla entries that failed because it only looked at the member
list that was in progress.

The compiler tries hard to extract information wherever possible from
incompletely analyzed types, but this one is just too much circular
dependencies that I cannot figure any way out of.

Try it yourself. Start with struct C and mentally follow the steps to do the
semantic analysis. You'll go in a circle with no way out.

Switching the is expression to __traits(compiles) works because it doesn't rely
on the eponymous name trick.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 09 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7868



--- Comment #7 from Walter Bright <bugzilla digitalmars.com> 2012-04-09
17:14:36 PDT ---
It turns out, the A template is irrelevant. Perhaps this is clearer:

template B(T) {
  mixin({
    foreach (name; __traits(derivedMembers, C)) {}
    return "struct B {}";
  }());
}

struct C {
  pragma(msg, "This is true: ", is(B!C));

  static if (is(B!C)) {
    B!C b;
  } else {
    pragma(msg, "But wasn't in the static if.");
  }

  pragma(msg, "Here again, though: ", is(B!C));
}

auto e = C.init.b;

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 09 2012