On Monday, 8 February 2016 at 19:07:01 UTC, Iakh wrote:
import std.stdio;

struct S
{
    void[] arr;

    auto f() pure @safe
    {
        int[] a = new int[4];
        arr = a;
        return a;
    }
}
void main() @safe
{
    S s;
    immutable a = s.f();
    int[] b = (cast(int[])s.arr);
    writeln(a);
    b[0] = 1;
    writeln(a);
}

http://dpaste.dzfl.pl/13751913d2ff

The bug is that it's even legal to declare a as immutable. pure functions that are strongly pure allow for the return value to have its mutability altered, because it's guaranteed that what's being returned isn't referenced anywhere else in the program. However, f is not strongly pure. It's taking the this pointer/reference as mutable, not immutable, which allows for the memory that's allocated in it to escape - as you've done in this example.

So, the compiler logic with regards to pure is buggy. Simply having

    struct S
    {
        void[] arr;

        auto f() pure @safe
        {
            int[] a = new int[4];
            arr = a;
            return a;
        }
    }
    void main() @safe
    {
        S s;
        immutable a = s.f();
    }


in a bug report should be sufficient to show the bug, even without the rest of what you're doing.

In general, it should be impossible for member functions to be considered strongly pure unless they're marked as immutable, though the compiler could certainly be improved to determine that no escaping of the return value or anything referencing it occurs within the function and that thus it can get away with treating the return value as if it's the only reference to that data, but that would likely be farther into the realm of code flow analysis than the compiler typically does.

Regardless, your example definitely shows a bug. Please report it. Thanks.

- Jonathan M Davis

Reply via email to