digitalmars.D.learn - internal compiler error with immutable
- Danny (87/87) Feb 07 2015 Hi,
- H. S. Teoh via Digitalmars-d-learn (8/19) Feb 07 2015 [...]
- Danny (7/7) Feb 07 2015 Hi,
- ketmar (3/19) Feb 08 2015 this is both non-DMD bug, and nonexistent-in-new-gdc bug.=
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (23/32) Feb 08 2015 You are not alone. :)
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (51/55) Feb 08 2015 The following is based on my understanding of that description:
- Danny (37/39) Feb 08 2015 Hi Ketmar,
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (10/20) Feb 09 2015 Yes, opEquals for classes has a particular syntax:
Hi, I'm trying to use immutable class instances and that seems to be really difficult. For example, with the following program I get an internal compiler error: ------------------------------------<cut>------------------------- import std.outbuffer : OutBuffer; import std.typecons : Rebindable; enum Attrkey : ubyte { Fgcolor, Bgcolor, } enum MAX_COMPRESSED_ATTRS = 128U; alias Codes = Rebindable!(Attrs)[MAX_COMPRESSED_ATTRS]; static shared Codes codes; private class Attrsp { immutable(Attrsp) next; Attrkey key; ubyte value; private this(Attrkey key, ubyte value, immutable(Attrsp) next) { this.next = next; this.key = key; this.value = value; } // FIXME allow comparing the entire chain for equality. private immutable void print(OutBuffer destination /* destination */) { destination.write("Attrs("); destination.write(cast(ubyte) key); // FIXME .toString() destination.write(", "); destination.write(value); destination.write(", \n"); if(this.next is null) destination.write("null"); else next.print(destination); destination.write(")"); } override immutable string toString() { auto destination = new OutBuffer(); print(destination); return destination.toString(); } // TODO add newless static opCall which also does compression? /*doesn't work static immutable immutable(Attrsp) opCall(Attrkey key, ubyte value, immutable(Attrsp) next) { return new immutable Attrsp(key, value, next); }*/ alias Code = ubyte; /* Compresses the given attributes into 1 Byte, if possible. Returns MAX_COMPRESSED if it's not possible. */ static Code compress(immutable(Attrs) node) { // FIXME make thread safe ubyte i; for(i = 0U; i < MAX_COMPRESSED_ATTRS; ++i) { if(codes[i] is null) { codes[i] = node; return i; } else if(codes[i] == node) return i; } return i; // tell that it didn't work. } static immutable(Attrs) uncompress(Code value) { assert(value >= 0U && value < MAX_COMPRESSED_ATTRS); return codes[value]; } } alias Attrs = immutable(Attrsp); ------------------------------------<cut>------------------------- gdc A.d cc1d: ../../src/gcc/d/dfrontend/statement.c:293: ErrorStatement::ErrorStatement(): Assertion `global.gaggedErrors || global.errors' failed. cc1d: internal compiler error: Aborted Please submit a full bug report, with preprocessed source if appropriate. See <file:///usr/share/doc/gcc-4.9/README.Bugs> for instructions. gdc (Debian 4.9.1-19) 4.9.1 ------------------------------------<cut>------------------------- What I'm trying to do is save space by putting often-used Attrs into an array and just compressing references to those into 1 Byte in the other data structures where it's used (these other data structures are not thread-local). Why do I need Rebindable to begin with? I'm not even trying to modify the contents of the instance, I'm just trying to assign another one to the array slot (actually not even another one - it was null before).
Feb 07 2015
On Sat, Feb 07, 2015 at 02:35:13PM +0000, Danny via Digitalmars-d-learn wrote: [...]------------------------------------<cut>------------------------- gdc A.d cc1d: ../../src/gcc/d/dfrontend/statement.c:293: ErrorStatement::ErrorStatement(): Assertion `global.gaggedErrors || global.errors' failed. cc1d: internal compiler error: Aborted Please submit a full bug report, with preprocessed source if appropriate. See <file:///usr/share/doc/gcc-4.9/README.Bugs> for instructions. gdc (Debian 4.9.1-19) 4.9.1 ------------------------------------<cut>-------------------------[...] Please file a bug at http://issues.dlang.org/. Compiler internal errors are *always* bugs that need to be fixed. Thanks! T -- English is useful because it is a mess. Since English is a mess, it maps well onto the problem space, which is also a mess, which we call reality. Similarly, Perl was designed to be a mess, though in the nicest of all possible ways. -- Larry Wall
Feb 07 2015
Hi, I've filed it with gdcproject.org before reading your reply. Will it be forwarded to issues.dlang.org or should I file it there as well? Also, it seems there's a new DMD release underway right now, does it still happen with that? (I tried but can't get it to build - doesn't seem to support ARMHF target)
Feb 07 2015
On Sat, 07 Feb 2015 09:23:42 -0800, H. S. Teoh via Digitalmars-d-learn wrote:On Sat, Feb 07, 2015 at 02:35:13PM +0000, Danny via Digitalmars-d-learn wrote: [...]this is both non-DMD bug, and nonexistent-in-new-gdc bug.=------------------------------------<cut>------------------------- gdc A.d cc1d: ../../src/gcc/d/dfrontend/statement.c:293: ErrorStatement::ErrorStatement(): Assertion `global.gaggedErrors || global.errors' failed. cc1d: internal compiler error: Aborted Please submit a full bug report, with preprocessed source if appropriate. See <file:///usr/share/doc/gcc-4.9/README.Bugs> for instructions. gdc (Debian 4.9.1-19) 4.9.1 ------------------------------------<cut>-------------------------[...] =20 Please file a bug at http://issues.dlang.org/. Compiler internal errors are *always* bugs that need to be fixed. Thanks!
Feb 08 2015
On 02/07/2015 06:35 AM, Danny wrote:I'm trying to use immutable class instances and that seems to be really difficult.You are not alone. :) Just some reminders: - immutable is a requirement that may not be usable with every type. - immutable string foo() {} is a member function that works on immutable objects. For that reason, that 'immutable' is recommended to appear after the parameter list: string foo() immutable {}For example, with the following program I get an internal compiler error:It generates regular compilation errors with dmd git head.override immutable string toString() {I received the following error for the toString() function above as there is no 'Object.toString immutable' to override: Error: function deneme.Attrsp.toString does not override any function, did you mean to override 'object.Object.toString'?for(i = 0U; i < MAX_COMPRESSED_ATTRS; ++i) { if(codes[i] is null) {I received the followin compilation error for the line above: Error: non-shared inout method std.typecons.Rebindable!(immutable(Attrsp)).Rebindable.RebindableCommon (immutable(Attrsp), Attrsp, Rebindable!(immutable(Attrsp))).get is not callable using a shared mutable objectI'm not even trying to modify the contents of the instance, I'm just trying to assign another one to the array slotThat would be a violation of immutable, no?(actually not even another one - it was null before).The compiler does not keep track of variables to see that it is null. Since immutable (and const) are transitive, it does not allow rebinding a class reference. Ali
Feb 08 2015
On 02/07/2015 06:35 AM, Danny wrote:What I'm trying to do is save space by putting often-used Attrs into an array and just compressing references to those into 1 Byte in the other data structures where it's used (these other data structures are not thread-local).The following is based on my understanding of that description: import std.conv; import std.concurrency; import std.stdio; class C { int value; // Constructor for immutable(C) objects this (int value) immutable { this.value = value; } } // Stores commonly used C objects and allows access to them by // ubyte indexes class CommonlyUsedCs { immutable(C)[] cs; // This add() works on 'shared' CommonlyUsedCs objects ubyte add(immutable(C) c) shared { ubyte index; synchronized { index = cs.length.to!ubyte; cs ~= c; } return index; } immutable(C) get(ubyte index) const shared { return cs[index]; } } void main() { auto cucs = new shared(CommonlyUsedCs)(); // Populate the Cs foreach (ubyte i; 0 .. 10) { if (i % 2) { cucs.add(new immutable(C)(i)); } } // Start a thread and tell it what index its C is at spawn(&user, cucs, ubyte(3)); } void user(shared(CommonlyUsedCs) cucs, ubyte index) { writefln("My C has value %s", cucs.get(index).value); } Ali
Feb 08 2015
Hi Ketmar, Hi Ali, thank you!On Sunday, 8 February 2015 at 09:42:14 UTC, Ali Çehreli wrote: spawn(&user, cucs, ubyte(3));^^^^^^^^^^^^^^^^^^^^^^^^^to! Other than that, it works. (The Attributes are basically literal constants but the library cannot know which are used in a given program - but probably not more than 20 or so are used realistically - it would be a UI design faux pas for content to be - like XP start menu - in hundreds of different yellowish greenish colors) Unfortunately, I can't seem to get opEquals to work with immutable (or const, for that matter) either. (does compile, though) The obvious bool opEquals(immutable(C) b) immutable { return value == b.value; } doesn't work. Probably have to override the one from Object ? Even though I don't really use polymorphism here. override bool opEquals(Object b) immutable { return value == (cast(immutable(C)) b).value; } Nope. Doesn't work (or compile) either. As a test, I added foreach (ubyte i; 0 .. 10) { if (i % 2) { cucs.add(new immutable(C)(i)); assert(new immutable(C)(i) == new immutable(C)(i)); // this } } to your program but the assertion fails after the changes (if it even compiles). Hmm, maybe I should just store immutable struct C pointers? Yep, that works, although then I have to compare for equality by *a == *b... oh well, I use opEquals comparison only internally after all.
Feb 08 2015
On 02/08/2015 05:21 AM, Danny wrote:The obvious bool opEquals(immutable(C) b) immutable { return value == b.value; } doesn't work. Probably have to override the one from Object ? Even though I don't really use polymorphism here. override bool opEquals(Object b) immutable { return value == (cast(immutable(C)) b).value; } Nope. Doesn't work (or compile) either.Yes, opEquals for classes has a particular syntax: http://ddili.org/ders/d.en/object.html#ix_object.opEquals Remember that 'const' binds to immutable as well. The following works with at least git head: override bool opEquals(Object b) const { auto rhs = cast(C)b; return rhs && (value == rhs.value); } Ali
Feb 09 2015