I committed a patch yesterday that I thought was a very good first
start. However, this morning I've found some holes in it that make
things look very bleak again.

What my patch did was simply ensure one thing -- that whenever an
alias was taken, it was verified that it was 'rooted' in a thing that
would outlive it, where rooted means the value is either a local
variable that isn't assigned to for the lifetime of the alias, or a
local temporary value (which can't be assigned to), or it is a field
directly dereferenced from another root, with the caveat that
dereferencing a mutable field and then a box isn't allowed, because
the mutable field could be reassigned, potentially freeing the box.

This required only a handful changes to uses of aliases in our current
code, and gets by without any kind of alias analysis. That's nice,
because alias analysis is impossible to do perfectly, and since this
is core behaviour, if we ever want to standardize Rust, we'd have to
fix on some heuristic algorithm, describe it in the spec, and require
every implementation to do exactly what our rustc does to be
compatible. Since decent alias analysis is arbitrarily complex, this
sound unattractive.

Unfortunately, there's this hole I mentioned before. What this
analysis guarantees is that the location pointed to by an alias will
always hold a value of type X — if you reassign to it, the alias will
still be valid. Except when going through a tag type. If you have an
alias inside a tag (as alt creates them) and you reassign its parent,
your alias might not point at memory of the right type anymore.

You can restrict values used for alt further, requiring that they are
not just rooted, but 'rooted immutably' -- if they dereference their
root, they may only do so through immutable fields/indices/unboxing. A
very typical pattern in code is to take an alias and do an alt on
that. Four ways to handle this case come to mind, all unattractive:

 - Require all aliases to be immutably rooted. This breaks a *lot* of
code, and would require much extra copying. If we went to a radically
functional paradigm, this might work, but Rust is just not that kind
of language.

 - Don't allow stuff rooted in an alias to be matched with alt. Again,
breaks tons of code, requires clunky copying to fix.

 - Make alt implicitly (or explicitly) copy stuff. Not good for
efficiency either.

 - Have two kinds of aliases, those that must be immutably rooted and
those that don't. Even more pointer types.

I think I'm somewhat of out of ideas here. The scheme Patrick
described with swapping unique pointers in and out would provide
something of an solution that doesn't copy, but that moves Rust so far
away from convenient simplicity that I really can't get behind it.
You'd have a ritualized song and dance, with a bunch of leaky
abstraction issues, every time you need to pass something by alias.
It's important to keep in mind that if the avoidance of refcounting
creates more indirection and overhead than the refcounting itself,
we're on the wrong track.

So, I'm about ready to try an 'everything is garbage collected'
approach. There is a reason almost all recent languages have moved to
that...

Best,
Marijn
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to