I want to explain my idea again, in the hope that I’ll manage to make it clearer this time. I also have a refinement of the idea, which makes it applicable without any additional syntax, and immediately allows to throw the special (and confusing) types &str and &[T] away, while making the language more performant.
First, the explanation. Every type Foo has its size_of<Foo>() bytes. Unless some of them are of type Unsafe (usually they aren’t), whenever a view &foo is alive, the compiler makes sure that those bytes are not mutated. If they are not mutated, it means that it doesn’t matter whether you have a pointer to those bytes, or if you have a copy of those bytes. This means that the question of whether the type &Foo is a pointer or a copy of Foo's bytes is just an implementation detail. Take for example the code
let v = &foo;
let x = v.x
Currently the compiler translates it to
Foo* v = &foo; // v is a pointer to foo
int x = (*v).x; // to access v.x you need to follow the pointer
If &Foo were implemented by copy, the code would be translated to:
Foo v = foo; // to create v you copy foo's bytes
int x = v.x; // you can now access v.x immediately
As you can see, it is only a matter of code generation. This would be entirely transparent to a Rust program, unless it checked what is size_of<&Foo>().
Now, based on this, let me propose a variant of the original idea, which doesn’t require any new syntax.
- Types could be decorated, to affect the implementation of their view.
- If a type isn’t decorated, its view is a copy of its bytes.
- A type could be decorated by
#[ref_view], which would make the compiler implement its view as a pointer. Types which include Unsafe members must be decorated with #[ref_view].
- Other types could be decorated to specify fields which are not copied into the view. For example,
Vec would be defined like this:
#[not_in_view(capacity)]
pub struct Vec<T> {
ptr: *mut T
len: uint,
capacity: uint,
}
- Fields listed as
not_in_view must be private, so code outside the type’s module won’t be bothered by the discrepancy between the type and its view.
This has a lot of benefits:
- No extra syntax to the language, just some more work for the machine code generator.
- No need for the special types
&str, &[T], which are confusing a lot of people. There would be just String and &String, Vec and &Vec.
- No need for dynamically sized types (I confess that I didn’t manage to really understand those, so maybe I’m wrong here.)
- Virtually all existing code would continue to run, and I believe most of it would become faster. If some code becomes slower, you can always add
#[ref_view] where it’s needed to get back the original performance.
Did I manage to explain myself? What do you think of this idea?