Thread overview
Qualified destructors / immutable objects
Jun 12, 2015
Marc Schütz
Jun 12, 2015
anonymous
Jun 12, 2015
anonymous
Jun 12, 2015
Marc Schütz
Jun 13, 2015
Daniel Kozak
Jun 13, 2015
anonymous
Jun 14, 2015
anonymous
Jun 14, 2015
Marc Schütz
June 12, 2015
    struct S {
        int x;
        ~this() {
            import std.stdio;
            writeln("mutable ~this()");
            x = 1;
        }
    }

    void main() {
        const(S) s1;
        immutable(S) s2;
    }

Prints:

    mutable ~this()
    mutable ~this()

This looks very wrong, although I cannot find a way to actually modify immutable memory with it...

Is it a bug?
June 12, 2015
> I cannot find a way to actually modify immutable memory with it...

a.d:

class C {
  int a;

  this(int a) {
     this.a = a;
  }
}

struct S {
    int x;
    C elem = new C(42);

    ~this() {
        import std.stdio;
        writeln("mutable ~this()");
        x = 1;
        elem.a = 123;
    }
}

void foo() {
    S s2;
}

void main() {
    import std.stdio;
    immutable(S) s1;
    //  Error: cannot modify immutable expression s1.elem.a
    // s1.elem.a = 43;
    writeln(s1.elem.a);
    foo();
    writeln(s1.elem.a);
}

dmd a.d
./a

prints:
42
mutable ~this()
123
mutable ~this()

> Is it a bug?

I'll wait with a bug report, but I think this should be forbidden.
June 12, 2015
no need for ~this() to modify immutable data:

class C {
	int a;

	this(int a) {
		this.a = a;
	}
}

struct S {
	C elem = new C(42);
}

void main() {
	import std.stdio;
    immutable(S) s1;

	//  Error: cannot modify immutable expression s1.elem.a
	// s1.elem.a = 43;
	
	writeln(s1.elem.a);

	S s2;
	s2.elem.a = 123;
	writeln(s1.elem.a);
}

Prints:
42
123
June 12, 2015
On Friday, 12 June 2015 at 15:36:22 UTC, anonymous wrote:
> no need for ~this() to modify immutable data:

<snip>

I think that's a another bug related to init values.
June 13, 2015
On Friday, 12 June 2015 at 15:36:22 UTC, anonymous wrote:
> no need for ~this() to modify immutable data:
>
> class C {
> 	int a;
>
> 	this(int a) {
> 		this.a = a;
> 	}
> }
>
> struct S {
> 	C elem = new C(42);
> }
>
> void main() {
> 	import std.stdio;
>     immutable(S) s1;
>
> 	//  Error: cannot modify immutable expression s1.elem.a
> 	// s1.elem.a = 43;
> 	
> 	writeln(s1.elem.a);
>
> 	S s2;
> 	s2.elem.a = 123;
> 	writeln(s1.elem.a);
> }
>
> Prints:
> 42
> 123

Is there an existing issue on issue.dlang.org? If not can you report it
June 13, 2015
> Is there an existing issue on issue.dlang.org? If not can you report it

https://issues.dlang.org/show_bug.cgi?id=10376
June 14, 2015
To come back to destructors and immutable objects:

Even without the default initialized variables issue it is possible to modify immutable data:

struct S {
  int[] bar;

  ~this() {
    bar[0] = 123;
  }
}

void foo(immutable(int[]) i) {
  immutable(S) s = immutable S(i);
}

void main() {
  immutable array = [42, 42];
  foo(array);
  // fails
  assert(array == [42, 42]);
}

I'm not sure whether ~this() should be forbidden to modify immutable data. Consider e.g. some fields need to be free'd. If someone else is using references to such a field after ~this() -> segfault, but it could be seen as analogon to the list of undefined operations on pointer to GC memory.
Additionally the same happens already for stack allocated fields like int[4] inside a (mutable/const/immutable) struct.

June 14, 2015
On Sunday, 14 June 2015 at 07:28:39 UTC, anonymous wrote:
> To come back to destructors and immutable objects:
>
> Even without the default initialized variables issue it is possible to modify immutable data:
>
> struct S {
>   int[] bar;
>
>   ~this() {
>     bar[0] = 123;
>   }
> }
>
> void foo(immutable(int[]) i) {
>   immutable(S) s = immutable S(i);
> }
>
> void main() {
>   immutable array = [42, 42];
>   foo(array);
>   // fails
>   assert(array == [42, 42]);
> }
>
> I'm not sure whether ~this() should be forbidden to modify immutable data. Consider e.g. some fields need to be free'd. If someone else is using references to such a field after ~this() -> segfault, but it could be seen as analogon to the list of undefined operations on pointer to GC memory.
> Additionally the same happens already for stack allocated fields like int[4] inside a (mutable/const/immutable) struct.

Found this bug report [1], in which Andrei says: "Mutable destructors shouldn't apply to objects that were immutable, otherwise they can mutate immutable objects."

[1] https://issues.dlang.org/show_bug.cgi?id=4338#c6