Now that structural types are always passed by reference, we can pass
all values conceptually by alias (i.e., without doing a take/drop on
them). The current alias analysis can be used to insert a refcount
bump or explicit copy on the caller side in those cases where it can't
prove the aliasing is safe.

For structurally mutable types, where the value itself, not a shared
box hanging off it, is mutable (i.e. {mutable x: int}, but not {x:
@mutable int}), implicit copying is unsafe, so the old behaviour
applies -- you get an error if you try to unsafely pass it to a
function.

For big structural types, where implicit copying is a silent
performance hazard, the compiler should warn. We can come up with some
heuristic for what counts as big. Copying a few words or
bumping/decrementing a refcount or two can be done implicitly -- the
cases where the copy is needed are rare (see our experiences with the
current alias system), and the solution would have been to make a copy
anyway. For bigger structurals, you can insert an explicit copy
operations (currently written {x}, but let's introduce a more explicit
syntax for that) to suppress the warning.

You can still pass structural types by copy if you want to, but you'll
have to explicitly copy it on the caller side. Needing to pass
structurals by copy is rarely what you want my experience, so this
seems an acceptable burden. If it turns out it's not, we can introduce
a copying argument mode.

I have a branch where this is working. We were not relying on
pass-by-value to copy structurally mutable values in our current
codebase, but always passing them by alias. So apart from changing the
way arguments are translated, no other parts of the compiler had to be
adjusted.

The way this would look in code is that you simply drop the ampersands
from your function signatures.

 * This makes them a lot less ugly
 * And this improves function interoperability -- no longer do you
have to remember which arguments are by alias and which aren't when
writing functions against an interface (say, AST visitors).

Mutable aliases serve a different purpose. They stay. I'd like to
write them by prepending the ampersand before the argument name, not
the type, so you'll say 'fn(&x: int)' for a function that takes its
first argument by mutable alias.

Further ahead, I want to do the same kind of auto-copying for
destructuring by pattern. So alt clauses remain, by default, aliasing.
When aliasing isn't safe, you get an error for structurally mutable
values, a warning for big structural values, and an auto-copy
otherwise. Same with destructuring let clauses (which currently copy).
The alias analysis is already well suited to check those.

My proposal for functions-returning-an-alias will have to be revised
if we adopt this change -- you will have to annotate explicitly which
argument you're going to alias into. This is probably an improvement
anyway.

I'm going to keep working on my experimental branch for a bit and see
if anything else comes up (the size and speed of the compiler are
improved by this change, so it's looking promising). If you see a
problem with this proposal, speak now or watch it being merged in
somewhere next week.
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to