On Friday, 17 August 2012 at 02:02:56 UTC, Jonathan M Davis wrote:

How is it a bug? The variable that you're altering is not part of the object. That's part of why having pure with const in so valuable. It prevents stuff
like what you're doing here.

- Jonathan M Davis

Notice that I'm making an immutable(S) in that example. It should then transitively mean that the data pointed to will be immutable as well. The reason this is a bug is because the constructor is currently set up to have the thing you're working with be mutable while you're still constructing it (otherwise, you couldn't even initialize any of the fields). However, this allows invalid code.

Here's a bit simplified version with some extra output:

int gCount;

struct S {
    int* it;
    this(int i) {
        writeln("--- constructor begin ---");
        gCount = i;
        it = &gCount; // Should be compile error
                      //when constructing immutable(S)
        writeln(typeof(it).stringof, " it = ", *it);
        writeln("^^ Notice, typeof(it) is always mutable!");
        writeln("--- constructor end ---");
    }
    ref const(int*) getItem() const {
        ++gCount;
        return it;
    }
}

import std.stdio;

void main() {
    immutable(S) s = immutable(S)(0);
    auto it = s.getItem();
    writeln(typeof(s.it).stringof, " s.it = ", *s.it);
    writeln(typeof(it).stringof, " it = ", *it);
    writeln(typeof(gCount).stringof, " gCount = ", gCount);
    s.getItem();
    writeln(typeof(s.it).stringof, " s.it = ", *s.it);
    writeln(typeof(it).stringof, " it = ", *it);
    writeln(typeof(gCount).stringof, " gCount = ", gCount);
}



I'm almost sure it's been reported before because I've seen talk about this particular issue in the past.

If you run this with optimizations off and on, it shows off the type of optimizations that can be made when something is immutable. For instance, with optimizations off you get:
...
immutable(int*) s.it = 1
const(int*) it = 1
int gCount = 1
immutable(int*) s.it = 2
const(int*) it = 2
int gCount = 2

and on:
...
immutable(int*) s.it = 1
const(int*) it = 1
int gCount = 1
immutable(int*) s.it = 1
const(int*) it = 2
int gCount = 2

As you can see, the optimization is that it doesn't even check s.it's memory location, it just puts the previous value in place.

But yeah, it's a bug that this code is allowed.

Reply via email to