digitalmars.D - no size yet for forward reference error
- Erik Smith (53/53) Feb 24 2016 In the process of converting my working database interface to be
- Erik Smith (23/23) Feb 24 2016 Here's a better reduction of the problem. Commenting out either
- Jonathan M Davis (8/32) Feb 25 2016 Actually, both of your examples compile for me - both with master
- bachmeier (4/11) Feb 25 2016 Same here. DMD 2.070.0 running on Linux Mint (built on Ubuntu
- Erik Smith (3/3) Feb 25 2016 I'm running OSX 10.11.2, DMD v2.070 installed via homebrew with
- Marc =?UTF-8?B?U2Now7x0eg==?= (3/9) Feb 25 2016 You need to compile with `-unittest`.
- Jonathan M Davis (27/36) Feb 25 2016 Ah, yes. I see now. And yes, that fails to compile.
- Marc =?UTF-8?B?U2Now7x0eg==?= (23/23) Feb 25 2016 Digger shows that it stopped working after this PR:
- Erik Smith (3/3) Feb 25 2016 Good to know that it's a bug - Thanks for the help. I've
- Walter Bright (4/7) Feb 25 2016 Thanks for preparing the bug report.
- Erik Smith (5/5) Feb 26 2016 The struct->class workaround is unworkable in this case because
In the process of converting my working database interface to be template based, I now get the following compiler error: Error: struct std.database.mock.database.Statement!int.Statement.Payload no size yet for forward reference I minimized the code to make it easier reason about. It seems to have something to do with Payload, but it may also have something to do with the ResultRange / Row circular references. The error is reported in object.d(2762,45). This is DMD v2.070. Any Ideas? unittest { auto db = Database!int.create(); auto con = Connection!int(db); } struct Database(T) { static Database create() { return Database!T();} } struct Connection(T) { alias Database = .Database!T; alias Statement = .Statement!T; } struct Statement(T) { alias Connection = .Connection!T; alias Result = .Result; private: struct Payload { Connection con; this(Connection con_) {con = con_;} this(this) { assert(false); } void opAssign(Statement.Payload rhs) { assert(false); } } alias RefCounted!(Payload, RefCountedAutoInitialize.no) Data; Data data_; } struct Result(T) { alias Statement = .Statement!T; alias ResultRange = .ResultRange!T; alias Range = .ResultRange; alias Row = .Row; this(Statement stmt) {data_ = Data(stmt);} ResultRange range() {return ResultRange(this);} } struct ResultRange(T) { alias Result = .Result!T; alias Row = .Row!T; private Result result_; this(Result result) {result_ = result;} } struct Row(T) { alias Result = .Result!T; this(Result* result) { result_ = result;} private Result* result_; }
Feb 24 2016
Here's a better reduction of the problem. Commenting out either of the lines marked HERE eliminates the error. It's some kind of interaction with templates, RefCounted, and the cross referencing types. erik module database; import std.typecons; unittest { auto con = Connection!int(); } struct Connection(T) { alias Statement = .Statement!T; // HERE } struct Statement(T) { alias Connection = .Connection!T; private: struct Payload { Connection con; this(Connection con_) {con = con_;} } alias RefCounted!(Payload, RefCountedAutoInitialize.no) Data; Data data_; // HERE }
Feb 24 2016
On Thursday, 25 February 2016 at 04:23:52 UTC, Erik Smith wrote:Here's a better reduction of the problem. Commenting out either of the lines marked HERE eliminates the error. It's some kind of interaction with templates, RefCounted, and the cross referencing types. erik module database; import std.typecons; unittest { auto con = Connection!int(); } struct Connection(T) { alias Statement = .Statement!T; // HERE } struct Statement(T) { alias Connection = .Connection!T; private: struct Payload { Connection con; this(Connection con_) {con = con_;} } alias RefCounted!(Payload, RefCountedAutoInitialize.no) Data; Data data_; // HERE }Actually, both of your examples compile for me - both with master and with 2.070.0. I'm running on x86_64 FreeBSD (which you probably aren't), which shouldn't matter for this sort of error, but I suppose that it's possible that it's somehow system-specific, much as I wouldn't expect it to be. So, I don't what to say. :| - Jonathan M Davis
Feb 25 2016
On Thursday, 25 February 2016 at 17:33:34 UTC, Jonathan M Davis wrote:Actually, both of your examples compile for me - both with master and with 2.070.0. I'm running on x86_64 FreeBSD (which you probably aren't), which shouldn't matter for this sort of error, but I suppose that it's possible that it's somehow system-specific, much as I wouldn't expect it to be. So, I don't what to say. :| - Jonathan M DavisSame here. DMD 2.070.0 running on Linux Mint (built on Ubuntu 14.04).
Feb 25 2016
I'm running OSX 10.11.2, DMD v2.070 installed via homebrew with --devel flag. erik
Feb 25 2016
On Thursday, 25 February 2016 at 17:33:34 UTC, Jonathan M Davis wrote:Actually, both of your examples compile for me - both with master and with 2.070.0. I'm running on x86_64 FreeBSD (which you probably aren't), which shouldn't matter for this sort of error, but I suppose that it's possible that it's somehow system-specific, much as I wouldn't expect it to be. So, I don't what to say. :|You need to compile with `-unittest`.
Feb 25 2016
On Thursday, 25 February 2016 at 20:14:20 UTC, Marc Schütz wrote:On Thursday, 25 February 2016 at 17:33:34 UTC, Jonathan M Davis wrote:Ah, yes. I see now. And yes, that fails to compile. Well, given that you have types referring to each other, it's not all that hard to get a circular definition error. The most obvious is when you do something like struct A { B b; } struct B { A a; } And while the code in question doesn't do anything that blatant, it is having types refer to each other. What's incredibly weird is that if the RefCounted!(Payload, RefCountedAutoInitialize.no) is changed to Payload, the code works. If there were going to be a circular definition problem, then I'd think that it would occur without RefCounted being involved. I'd suggest copying RefCounted to your local file and using that version of it rather than introducing std.typecons into the mix, and then use dustmite to reduce it. Then you can track down which part of RefCounted is causing the problem. dustmite is now released with dmd, I believe, so you shouldn't need to track it down, and instructions for it can be found here: https://github.com/CyberShadow/DustMite/wiki - Jonathan M DavisActually, both of your examples compile for me - both with master and with 2.070.0. I'm running on x86_64 FreeBSD (which you probably aren't), which shouldn't matter for this sort of error, but I suppose that it's possible that it's somehow system-specific, much as I wouldn't expect it to be. So, I don't what to say. :|You need to compile with `-unittest`.
Feb 25 2016
Digger shows that it stopped working after this PR: https://github.com/D-Programming-Language/dmd/pull/4457 I could reduce it as far as this: struct RefCounted(T) { struct Impl { T _payload; } Impl* _store; ~this() { destroy(_store._payload); } } struct Connection(T) { alias Statement = .Statement!T; } struct Statement(T) { alias Connection = .Connection!T; struct Payload { Connection con; } RefCounted!Payload Data; } Connection!int x;
Feb 25 2016
Good to know that it's a bug - Thanks for the help. I've created an issue to track this: https://issues.dlang.org/show_bug.cgi?id=15726
Feb 25 2016
On 2/25/2016 9:07 PM, Erik Smith wrote:Good to know that it's a bug - Thanks for the help. I've created an issue to track this: https://issues.dlang.org/show_bug.cgi?id=15726Thanks for preparing the bug report. You can probably work around the problem for the time being by making one of the mutually referencing structs a class.
Feb 25 2016
The struct->class workaround is unworkable in this case because underlying C database clients are often pretty sensitive to out of order resource cleanup and generate errors or crash as a result. The structs are essential but I will limit the design to avoid the issue for now.
Feb 26 2016