digitalmars.D - Weird rule for immutable
- Victor Porton (20/20) Apr 10 2020 https://dlang.org/spec/const3.html has a weird rule:
- Victor Porton (7/12) Apr 10 2020 should be:
- Victor Porton (3/16) Apr 10 2020 A related issue I've posted:
- Nick Treleaven (4/9) Apr 11 2020 You can't pass a mutable int to a `ref immutable int` parameter.
- Adam D. Ruppe (3/4) Apr 10 2020 Immutable means it NEVER changes. If you want it to just
- Victor Porton (9/13) Apr 10 2020 Yes, specification reads this way by me, too.
- Adam D. Ruppe (15/22) Apr 10 2020 Any code that actually uses immutable data is allowed to make
- Walter Bright (4/11) Apr 11 2020 Because Data Flow Analysis would needed to prove there are not other mut...
- Steven Schveighoffer (15/32) Apr 11 2020 So let me modify your example to address Adam's point:
- Timon Gehr (4/9) Apr 11 2020 No. `const` is for data that may or may not change at any time, just not...
- Walter Bright (3/4) Apr 12 2020 The rule is a consequence of not requiring Data Flow Analysis to diagnos...
- Timon Gehr (3/9) Apr 12 2020 ?
- Timon Gehr (14/41) Apr 11 2020 It does not. You are not mutating any data that has been cast to
- Timon Gehr (2/10) Apr 11 2020
- Walter Bright (8/12) Apr 12 2020 I've made a start on defining lifetimes in the spec, but it's hard to tu...
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(?)
Apr 10 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(?)
Apr 10 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:A related issue I've posted: https://issues.dlang.org/show_bug.cgi?id=20728void 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(?)
Apr 10 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).
Apr 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.
Apr 10 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: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];Why this is disallowed?Immutable means it NEVER changes. If you want it to just temporarily not change, that's what const is for.
Apr 10 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.
Apr 10 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.
Apr 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: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. -SteveOn Saturday, 11 April 2020 at 01:19:29 UTC, Victor Porton wrote: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];Why this is disallowed?Immutable means it NEVER changes. If you want it to just temporarily not change, that's what const is for.
Apr 11 2020
On 11.04.20 03:26, Adam D. Ruppe wrote:On Saturday, 11 April 2020 at 01:19:29 UTC, Victor Porton wrote:No. `const` is for data that may or may not change at any time, just not by accessing it through that `const` reference. He is absolutely right that the rule is weird.Why this is disallowed?Immutable means it NEVER changes. If you want it to just temporarily not change, that's what const is for.
Apr 11 2020
On 4/11/2020 7:30 PM, Timon Gehr wrote:the rule is weird.The rule is a consequence of not requiring Data Flow Analysis to diagnose whether a mutable reference outlives it and is used.
Apr 12 2020
On 12.04.20 22:39, Walter Bright wrote:On 4/11/2020 7:30 PM, Timon Gehr wrote:? The compiler is not even expected to diagnose wrong casting.the rule is weird.The rule is a consequence of not requiring Data Flow Analysis to diagnose whether a mutable reference outlives it and is used.
Apr 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.
Apr 11 2020
On 12.04.20 04:26, Timon Gehr wrote:On 11.04.20 03:19, Victor Porton wrote:Typos, I meant to write `f(*cast(immutable(int)*)&x)`.... int x = 1; f(cast(*immutable(int*)&x);x = 2; // the immutable reference does not exist at this point // but the assignment is disallowed(?)
Apr 11 2020
On 4/11/2020 7:26 PM, Timon Gehr wrote: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.I've made a start on defining lifetimes in the spec, but it's hard to turn "I know what I mean" into legalese. I also wish to carefully avoid crafting semantics that require Data Flow Analysis to implement. It does turn out to be necessary to do DFA for live, but at least that's optional. This is why, for example, the language uses lexical closures to determine where to insert destructors rather than "last use".
Apr 12 2020