View mode: basic / threaded / horizontal-split · Log in · Help
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
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.
Top | Discussion index | About this forum | D home