On 11/04/2011 05:32 AM, Marijn Haverbeke wrote:
Kinds are assigned to generic type parameters to determine what a
generic function can do with values of that kind.

Rust currently has three kinds:
  - 'unique' types can be moved and sent (all the scalar types, unique
boxes with no resources in them)
  - 'shared' types can be moved, but can not be sent (anything
involving refcounted boxes-- @, obj, lambda)
  - 'pinned' types can be sent, but not moved (this currently applies
to resources, anything including resources, and blocks)

Pinned types cannot be sent or moved. Also, in the current implementation, but not in the current design, kinds play a role in determining what can be copied (unique and shared can be copied).

I'm arguing that this is not a very good system, and that we'd be
better off considering 'copying' rather than 'moving' as a property.
This was the way the system was originally designed, but when
implementing it,

I agree that copying feels like the more important property, and the current system is unsatisfactory.

I propose the following alternative, which allows resources to be
moved again (*), greatly reduces the awkwardness of declaring types
for generic functions, and defines a more specialized approach to
safety for blocks (**), and actually help define noncopyability (which
the current system doesn't do at all).

We'd have the following kinds (better terms will have to be found, but
I'm using these for clarity):
- 'send,copy' types can be copied and sent (scalar types, unique boxes
without resources in them)
- 'nosend,copy' types can be copied, not sent (the same as the
'shared' types above, refcounted things)
- 'nosend,nocopy' types can't be sent or copied (resources, unique
boxes with resources in them, blocks)

These copy rules are implemented currently (at least to the extent I could guess where copying was happening), but they are not reflected in the big explanatory comments in kind.rs because they are contrary to Graydon's design. The difference here is that 'pinned' kinds become movable and blocks get some rules of their own. That seems ok.

Contrary to the old kinds, this forms a hierarchy, and the kinds lowerd
in the list can be treated as sub-kinds of those above them (a
'send,copy' value can be safely treated as a 'nosend,nocopy' value).
Most generic functions will neither send nor copy values of their
parameterized type, so they can safely default to 'nosend,nocopy'
without losing genericity.

I'm skeptical that this will be the case, primarily because of return values and vectors.

We'll have to define more closely when copying happens. I probably
forgot some cases here, but—an lvalue (rvalues are always conceptually
moved) is copied when:
- It is assigned to some other lvalue with =
- It is copied into a lambda closure
- It is passed as an argument in an unsafe way (safe argument passing
does not copy)
- It is used as the content of a newly created data structure (it is
not yet clear how tag/resource constructors can be distinguished from
other functions for this purpose. maybe they should take their args in
move mode, though that would require one to always say
option::some(copy localvar), which is also awkward)
- It is returned from a function or block

Most operations on vectors involve copy.

It might be useful to consider the last use of a local (let) variable
to be an rvalue, since that local will never be referenced again, and
it is always safe to move out of it. This will cause most returns to
become moves (though returning a non-move-mode argument or the content
of a data structure is still a copy). The intention is to only
annotate things as a copy where there will *actually* be two reachable
versions of a value after the operation. (The translator pass is
already optimizing most of the situations where this isn't the case
into a move or construct-in-place. This system could move some of that
logic into the kind-checking pass.)

This seems like the same kind of special casing that allows @resource to work, i.e. the kind checking pass already uses knowledge about the optimizations in trans to make some things work, and I agree with your assessment that the @resource thing is not good.

A big problem we have now is that the type system cares about copyability and movability, and those properties are mostly defined by optimizations in trans. Now kind checking (maybe some other passes) and trans are both doing their own analyses of what is allowed and hoping they agree.

I'm all for any attempts to make the kind system understandable.



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

Reply via email to