Bug 7815 – Mixin template forward reference (?) regression

Status
RESOLVED
Resolution
WONTFIX
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-04-03T10:08:00Z
Last change time
2015-06-17T21:05:06Z
Keywords
rejects-valid
Assigned to
nobody
Creator
code

Attachments

IDFilenameSummaryContent-TypeSize
1085bug7815.zipA not-very-reduced test case.application/zip197833
1086bug7815 (2).zipDMD 2.059 Beta 4 testcaseapplication/zip198043
1088foo.zipreduced test.d and scid/matrix.dapplication/x-zip-compressed928

Comments

Comment #0 by code — 2012-04-03T10:08:27Z
DMD 2.058 accepted the following snippet, while DMD c2824d43 executes the else branch of the static if. In there, though, instantiating the template will (apparently) just work fine. --- mixin template Helpers() { alias typeof(this) This; static if (is(Flags!This)) { Flags!This flags; } else { // DMD will happily instantiate the allegedly // non-existent Flags!This here. (!) pragma(msg, __traits(derivedMembers, Flags!This)); } } template Flags(T) { mixin({ string defs; foreach (name; __traits(derivedMembers, T)) { defs ~= "bool " ~ name ~ ";\n"; } if (defs.length > 0) { return "struct Flags {" ~ defs ~ "}"; } else { return ""; } }()); } struct Move { int a; mixin Helpers!(); } enum a = Move.init.flags; // isSetFlags should exist. --- (Note that while the above code is probably not the minimal possible example needed to trigger the bug, it has been reduced beyond repair as far as its original intent goes, so don't try to make sense of it in that regard.)
Comment #1 by github-bugzilla — 2012-04-05T21:07:38Z
Commit pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/7a81d73021c456fd546cb241f40420717d2ec365 fix Issue 7815 - Mixin template forward reference (?) regression
Comment #2 by dsimcha — 2012-04-07T15:52:59Z
I think the fix may have only fixed certain cases of this bug. I'm running into another case of what looks to be the same bug using 2.059 beta 2, but I'm still working on reducing it.
Comment #3 by dsimcha — 2012-04-07T17:22:21Z
I reduced the case where it's still failing, reopened. enum Closure { Matrix } struct BasicMatrix { mixin Operand!( Closure.Matrix ); } template Operand( Closure closure_ ) { alias closure_ closure; } struct Expression( string op_, Lhs, Rhs = void ) { enum lhsClosure = closureOf!Lhs; } template closureOf( T ) { enum closureOf = T.closure; } alias Expression!("+", BasicMatrix) Foo; test.d(18): Error: no property 'closure' for type 'BasicMatrix' test.d(14): Error: template instance test.closureOf!(BasicMatrix) error instantiating test.d(21): instantiated from here: Expression!("+",BasicMatrix) test.d(21): Error: template instance test.Expression!("+",BasicMatrix) error instantiating
Comment #4 by bugzilla — 2012-04-07T18:06:42Z
Please, the original two bugs were fixed and are fixed. A new bug should entered for new bugs, not reopening fixed ones. For next time.
Comment #5 by bugzilla — 2012-04-07T18:18:42Z
This new case fails also on dmd 2.058, so it is not a regression.
Comment #6 by bugzilla — 2012-04-07T18:19:31Z
Reduced test case: ----------------------- enum Closure { Matrix } struct BasicMatrix { mixin Operand!( Closure.Matrix ); } template Operand( Closure closure_ ) { alias closure_ closure; } alias BasicMatrix.closure Foo;
Comment #7 by github-bugzilla — 2012-04-07T18:56:07Z
Commit pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/5e7362a96beaa238389170f50261b000c1ae82e3 fix Issue 7815 - Mixin template forward reference (?) regression
Comment #8 by dsimcha — 2012-04-08T06:49:20Z
The fix that was just checked in fixes the test case I submitted but doesn't fix the bug in the code that I reduced the test case from. I'm working on reducing another test case that still fails.
Comment #9 by code — 2012-04-08T10:10:43Z
The original code I reduced the test case from still doesn't work either, will report a new bug once I managed to reduce it again.
Comment #10 by dsimcha — 2012-04-08T11:55:35Z
Created attachment 1085 A not-very-reduced test case. I'll try harder to reduce this later if necessary, but I don't have time right now and every time someone reduces this bug it seems like something important gets left out. Here's a zip file of my mostly unreduced. Just go into the main directory (bug7815/) and do a dmd test.d. This will instantiate all the necessary templates to reproduce the bug even on 2.059 Beta 3. Hopefully this will be easier to reduce for someone who has a better understanding of what changed between releases.
Comment #11 by code — 2012-04-08T15:13:41Z
Issue 7862 might be related to what I'm seeing.
Comment #12 by dsimcha — 2012-04-09T07:31:57Z
Created attachment 1086 DMD 2.059 Beta 4 testcase Here's a new test case that works around a change in Phobos that apparently occurred between betas. This reproduces the failure on DMD 2.059 Beta 4. Usage is the same as the old test case.
Comment #13 by bugzilla — 2012-04-10T10:19:52Z
Created attachment 1088 reduced test.d and scid/matrix.d this replaces the files scid/matrix.d and test.d in the test case. They are somewhat reduced.
Comment #14 by code — 2012-04-10T22:38:19Z
Drastically reduced test case: ——— struct Expression(string op_, Lhs) { enum lhsClosure = closureOf!Lhs; } template closureOf(T) { static if (is(typeof({ T x; x + x; }))) {} enum closureOf = 1; } struct BasicVector { void t() { auto r = Expression!("t", typeof(this))(); } auto opBinary( string op, NewRhs )( NewRhs ) { return Expression!("+", typeof(this))(); } } ———
Comment #15 by bugzilla — 2012-04-11T10:40:51Z
I reduced the test case a little more: struct Expression(int op) { enum lhsClosure = closureOf!(); } template closureOf() { static if (is(typeof({ BasicVector x; x.bar(x); }))) {} enum closureOf = 1; } struct BasicVector { void t() { auto r = Expression!(1)(); } void bar(T)(T) { auto x = Expression!(2)(); } }
Comment #16 by bugzilla — 2012-04-11T10:49:07Z
Ok, here's the problem. Attempt to compile BasicVector. Expand Expression!(1)(). Expand closureOf!() which is needed to initialize lhsClosure. 1. closureOf has two members 1. the static if 2. the enum closureOf 2. in order to initialize lhsClosure, closureOf must be eponymous therefore, we must evaluate the static if. Evaluating the static if evaluates bar(T)(T) bar(T)(T) evaluates Expression!(2)() Expression!(2)() needs to eponymously expand closureOf!() And so we wind up in a circle, hence the confusing error message. It "worked" prior because the circular reference error was ignored.
Comment #17 by github-bugzilla — 2012-04-11T14:43:23Z
Commit pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/f793ed4e3dd7b85c9a0cc703252146f0e7611dbc better error message for Issue 7815 - Mixin template forward reference (?) regression
Comment #18 by github-bugzilla — 2015-05-13T21:38:17Z
Commit pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/d0c854a1722c286777c5e48e0780e5318a986f49 Move issue 7815 case to fail_compilation, because it was invalid It was wrongly accepted by the bug in `StaticIfCondition::include()`. Bug explanation copied from fail_compilation/fail7815.d: ---- When the Move struct member is analyzed: 1. mixin Helpers!() is instantiated. 2. In Helpers!(), static if and its condition is(Flags!Move)) evaluated. 3. In Flags!Move, string mixin evaluates and CTFE lambda. 4. __traits(derivedMembers, Move) tries to see the member of Move. 4a. mixin Helpers!() member is analyzed. 4b. `static if (is(Flags!Move))` in Helpers!() is evaluated 4c. The Flags!Move instantiation is already in progress, so it cannot be resolved. 4d. `static if` fails because Flags!Move cannot be determined as a type. 5. __traits(derivedMembers, Move) returns a 1-length tuple("a"). 6. The lambda in Flags!Move returns a string "struct Flags {...}", then Flags!Move is instantiated to a new struct Flags. 7. Finally Move struct does not have flags member, then the `enum a7815` definition will fail in its initializer.
Comment #19 by github-bugzilla — 2015-06-17T21:05:06Z
Commit pushed to stable at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/d0c854a1722c286777c5e48e0780e5318a986f49 Move issue 7815 case to fail_compilation, because it was invalid