I can't figure out how GitHub works, so can someone please commit the following
RFC, thank you:
- Start Date: 2014-04-17
- RFC PR #:
- Rust Issue #:
# Summary
Add the ability to specify that a type, which implements a certain trait, must
have certain set of fields (data members) of certain types so that the trait
may then use those expected fields in the methods it provides (has a default
definition for).
# Motivation
This enables much more code re-use than traits currently do. This also provides
what other languages call "multiple inheritance" without facing the so called
"diamond problem".
# Detailed design
A trait may specify a set of expected fields. For each expected field the trait
definition must provide a type and a unique name. When a type implements such a
trait, it must specify which of its fields correspond with each of the trait's
expected fields. The types of the fields must match with the types of the
corresponding expected fields of the trait and no two fields of the type may
map to the same expected field of the trait. The type implementing the trait
may have more fields than there are expected fields in the trait, and the order
of fields doesn't matter. The knowledge of which field each expected field
corresponds to can then be used by the trait to locate and use the data it
expects to find by adding the offset of the field to a pointer to the first
byte of ```self``` and by re-interpreting the pointed-to data as the expected
field's type.
What follows next is an example code snippet where I present the syntax I
propose for this feature. And after that I'll provide the (currently valid)
Rust code which the first example would conceptually correspond with.
Example 1: The proposed syntax
```
trait Unify<T: Clone> {
Self {
x: T,
y: T
}
fn unify(&mut self) {
self.y = self.x.clone();
}
}
struct Stuff {
a: u32,
b: u32
}
impl Unify<u32> for Stuff {
Stuff {
x => a,
y => b
}
}
```
Example 2: The code that corresponds with example 1
```
use std::cast::transmute;
trait Unify<T: Clone> {
fn x_offset(&self) -> int; // This should be replaced with an associated
constant once we get those
fn y_offset(&self) -> int; // This should be replaced with an associated
constant once we get those
fn unify(&mut self) {
unsafe {
let self_x: *mut T = transmute::<*mut u8, *mut T>(transmute::<&mut
Self, *mut u8>(self).offset(self.x_offset()));
let self_y: *mut T = transmute::<*mut u8, *mut T>(transmute::<&mut
Self, *mut u8>(self).offset(self.y_offset()));
*self_y = (*self_x).clone();
}
}
}
struct Stuff {
a: u32, // is at offset 0 bytes
b: u32 // is at offset 4 bytes
}
impl Unify<u32> for Stuff {
fn x_offset(&self) -> int {
0 // The offset of field 'a'
}
fn y_offset(&self) -> int {
4 // The offset of field 'b'
}
}
```
# Alternatives
Code re-use is possible also with macros, but this solution is much more
elegant and may allow better opportunities for the compiler to reduce template
code-bloat.
# Unresolved questions
The syntax is completely open to debate.
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev