July 26, 2012 Inherited mutability, freeze, thaw and more in Rust | ||||
---|---|---|---|---|
| ||||
Another post from the Rust language blog: http://smallcultfollowing.com/babysteps/blog/2012/07/24/generalizing-inherited-mutability/ From the post: >This is a powerful idea but quite beyond Rust’s type system, and I am interested in exploring solutions that lead to similar expressiveness while avoiding the quagmire of dependent types.< Adding dependent types to Rust increases the language complexity, but it also offers very good capabilities that only very few languages like ATS have. A first part, "More background: inherited mutability" is about a problem that I have discussed a little in this newsgroup. So it seems it wasn't a so naive and useless topic. Rust immutability seems better thought out/designed than D immutability, but Rust design is not finished yet. Rust type system is much more powerful than D type system, but maybe it's also a little harder to understand. In Rust even if a struct (record) field is not mutable, you are allowed to replace the contents of a mutable variable that contains one of such struct instances. It means it accepts code similar to this one, because inherits mutability: struct Foo { immutable int x; int y; } void main() { Foo f = Foo(5, 10); f = Foo(20, 30); } This is quite handy, because in D once a struct has an immutable field, you can't do a lot with it, you can't reassign, etc. A D class instance with one immutable field doesn't have such problems: Doing this is of course not accepted in Rust: void main() { immutable Foo f = Foo(5, 10); f = Foo(20, 30); } Bye, bearophile |
July 26, 2012 Re: Inherited mutability, freeze, thaw and more in Rust | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Thursday, 26 July 2012 at 14:54:59 UTC, bearophile wrote:
> struct Foo {
> immutable int x;
> int y;
> }
> void main() {
> Foo f = Foo(5, 10);
> f = Foo(20, 30);
> }
There's problems with this which would have significant consequences in D. It would destroy the ability to reason about code and make many different possible optimizations.
A quick example of one of the problems that would be raised by this:
int calc(immutable int * input) {
auto result = input * 7;
// ... lots of other things
result += input + otherThing;
return result;
}
void main() {
Foo f = Foo(5, 10);
auto bar = task!calc(&f.x);
bar.executeInNewThread();
// do some things...
f = Foo(20, 30);
// do some other things...
writeln(bar.yieldForce()); // Oops.
}
In this case, the problem is pretty clear. Even though calc takes an immutable int pointer, we have no idea whether calc will use 5 or 20 in its calculation. It may even **change while calc is running!**
Furthermore, the compiler might generate code that *is not equivalent to the program as written* as a side effect to that unpredictable state of affairs. For instance, it might choose to cache the int in a register and therefore wouldn't change while calc is running ... which is clearly not equivalent, but *should* be correct if we assume that the input couldn't change ... which is what immutable normally guarantees.
Now Rust may have other features/limitations which make this not a problem (and even correct), but it could have far reaching consequences for D.
|
Copyright © 1999-2021 by the D Language Foundation