Jump to page: 1 2
Thread overview
Weird rule for immutable
Apr 11, 2020
Victor Porton
Apr 11, 2020
Victor Porton
Apr 11, 2020
Victor Porton
Apr 11, 2020
Nick Treleaven
Apr 11, 2020
Adam D. Ruppe
Apr 11, 2020
Victor Porton
Apr 11, 2020
Adam D. Ruppe
Apr 11, 2020
Walter Bright
Apr 12, 2020
Timon Gehr
Apr 12, 2020
Walter Bright
Apr 12, 2020
Timon Gehr
Apr 12, 2020
Timon Gehr
Apr 12, 2020
Timon Gehr
Apr 12, 2020
Walter Bright
April 11, 2020
https://dlang.org/spec/const3.html has a weird rule:

"The second way is to cast data to immutable. When doing so, it is up to the programmer to ensure that any mutable references to the same data are not used to modify the data after the cast."

This rule is weird because it disallows the following code:

int[] x = [];
{
  immutable y = cast(immutable)x;
}
x = [1, 2];

Here x is modified only after the immutable reference goes out of scope.

Why this is disallowed? Is it the language designers' intention? Why? Or is it bad wording in the specification?

Consider another example, I assume also invalid(?):

void f(ref immutable int v) { }

int x = 1;
f();
x = 2; // the immutable reference does not exist at this point
       // but the assignment is disallowed(?)
April 11, 2020
On Saturday, 11 April 2020 at 01:19:29 UTC, Victor Porton wrote:
> void f(ref immutable int v) { }
>
> int x = 1;
> f();
> x = 2; // the immutable reference does not exist at this point
>        // but the assignment is disallowed(?)

should be:

void f(ref immutable int v) { }

int x = 1;
f(x);
x = 2; // the immutable reference does not exist at this point
       // but the assignment is disallowed(?)
April 11, 2020
On Saturday, 11 April 2020 at 01:19:29 UTC, Victor Porton wrote:
> Why this is disallowed?

Immutable means it NEVER changes. If you want it to just temporarily not change, that's what const is for.
April 11, 2020
On Saturday, 11 April 2020 at 01:24:53 UTC, Victor Porton wrote:
> On Saturday, 11 April 2020 at 01:19:29 UTC, Victor Porton wrote:
>> void f(ref immutable int v) { }
>>
>> int x = 1;
>> f();
>> x = 2; // the immutable reference does not exist at this point
>>        // but the assignment is disallowed(?)
>
> should be:
>
> void f(ref immutable int v) { }
>
> int x = 1;
> f(x);
> x = 2; // the immutable reference does not exist at this point
>        // but the assignment is disallowed(?)

A related issue I've posted: https://issues.dlang.org/show_bug.cgi?id=20728
April 11, 2020
On Saturday, 11 April 2020 at 01:26:28 UTC, Adam D. Ruppe wrote:
> On Saturday, 11 April 2020 at 01:19:29 UTC, Victor Porton wrote:
>> Why this is disallowed?
>
> Immutable means it NEVER changes. If you want it to just temporarily not change, that's what const is for.

Yes, specification reads this way by me, too.

But is there any practical reason that the specification disallows the following?

int[] x = [];
{
  immutable y = cast(immutable)x;
}
x = [1, 2];
April 11, 2020
On Saturday, 11 April 2020 at 01:45:20 UTC, Victor Porton wrote:
> But is there any practical reason that the specification disallows the following?

Any code that actually uses immutable data is allowed to make various assumptions about it, like keeping the reference for later, aggressively caching, etc.

Your code doesn't break that so it works (that's actually allowed by "undefined behavior"; the language doesn't define what it does, but you, the programmer, can know things the spec doesn't), but in general code can do other things with it that would break here.

> int[] x = [];
> {
>   immutable y = cast(immutable)x;
> }
> x = [1, 2];

technically btw this code is not strictly wrong because it is the REFERENCE where immutability matters, and here you are replacing it with new data, not actually modifying the old. Just like `string a = "foo"; a = "bar";` is allowed despite string being immutable contents. But I'm pretending it means what you think it means.
April 11, 2020
On Saturday, 11 April 2020 at 01:24:53 UTC, Victor Porton wrote:
> void f(ref immutable int v) { }
>
> int x = 1;
> f(x);
> x = 2; // the immutable reference does not exist at this point
>        // but the assignment is disallowed(?)

You can't pass a mutable int to a `ref immutable int` parameter. (Without 'ref', D will allow passing a mutable int to an immutable int because a copy is made).
April 11, 2020
On 4/10/2020 6:45 PM, Victor Porton wrote:
> But is there any practical reason that the specification disallows the following?
> 
> int[] x = [];
> {
>    immutable y = cast(immutable)x;
> }
> x = [1, 2];

Because Data Flow Analysis would needed to prove there are not other mutations to x within the lifetime of y. DFA is slow and complex, and doesn't seem worth it for this case.
April 11, 2020
On 4/10/20 9:45 PM, Victor Porton wrote:
> On Saturday, 11 April 2020 at 01:26:28 UTC, Adam D. Ruppe wrote:
>> On Saturday, 11 April 2020 at 01:19:29 UTC, Victor Porton wrote:
>>> Why this is disallowed?
>>
>> Immutable means it NEVER changes. If you want it to just temporarily not change, that's what const is for.
> 
> Yes, specification reads this way by me, too.
> 
> But is there any practical reason that the specification disallows the following?
> 
> int[] x = [];
> {
>    immutable y = cast(immutable)x;
> }
> x = [1, 2];

So let me modify your example to address Adam's point:

int[] x = [1,2];
{
   immutable y = cast(immutable)x;
}

x[] = 5;

And let's do something else:

void foo(const(int)[] z) {writeln(z);}

foo(x);

Theoretically, the compiler could assume that x's data has become immutable and by logical deduction, write "[1, 2]".

It's usually the case that if you invoke undefined behavior, the compiler can do anything it wants under the given assumptions.

-Steve
April 12, 2020
On 11.04.20 03:19, Victor Porton wrote:
> https://dlang.org/spec/const3.html has a weird rule:
> 
> "The second way is to cast data to immutable. When doing so, it is up to the programmer to ensure that any mutable references to the same data are not used to modify the data after the cast."
> 
> This rule is weird because it disallows the following code:
> 
> int[] x = [];
> {
>    immutable y = cast(immutable)x;
> }
> x = [1, 2];
> ...

It does not. You are not mutating any data that has been cast to immutable, you are just rebinding a mutable reference.

Maybe you meant to write something like this instead:

int[] x = [1, 2];
{
    immutable y = cast(immutable)x;
}
x[0] = 3;

> Here x is modified only after the immutable reference goes out of scope.___
> 
> Why this is disallowed? Is it the language designers' intention? Why? Or is it bad wording in the specification?
> ...

The wording in the spec is (probably) both intentional and bad.

> Consider another example, I assume also invalid(?):
> 
> void f(ref immutable int v) { }
> 
> int x = 1;
> f(cast(*immutable(int*)&x);
> x = 2; // the immutable reference does not exist at this point
>         // but the assignment is disallowed(?)

According to spec I think it's invalid, therefore it is impossible to manually manage immutable memory. I think the specification should rather be something along the lines that it is undefined behavior to read different values using the same (logical) reference to immutable data.
« First   ‹ Prev
1 2