It seems the argument on single-inheritance hinges on the following use
case:

struct Foo { foo: int }

struct Bar : Foo { bar: bar }

fn main() {
    let myFoos = [Foo{ foo: 1 } as ~Foo, Bar{ foo: Foo{foo: 1}, bar: 2} as
~Foo];
    for myFoo in myFoos.iter() {
        myFoo.foo; // Fixed offset access
    }
}

If I understand correctly, this member access is vital for Servo.

At the same time, I (and I think others) would like to see some form of a
flexible implementation reuse for traits, with the understanding the
invoking trait methods incurs the cost of a virtual function anyway.

I think it is "obvious" that the same mechanism can't do both. So how about
a compromise? There would be two mechanisms, but we'll make them play nice
with each other.

Mechanism #1: Struct-traits.
Mechanism #3: Anonymous fields.

struct Foo { foo: int }

// Note: Use "Foo" as a trait.
// Any type implementing "Foo" has a publicly-reachable "Foo" member at
offset 0.
// The trait "Foo" allows constant-offset access to all the "Foo" data
members.
fn use_foo<T: Foo>(ptr: &T) -> int {
    ptr.foo // Fixed offset
}

// By construction, Bar implements the Foo struct-trait
struct Bar {
    Foo;
    bar: int;
}

(It is also possible to add a new syntax "struct Bar : Foo { bar int }", if
this is seen as clearer, but IMO it isn't really needed).

// Baz also implements Foo by construction.
struct Baz {
    Bar;
    baz: int;
}

// Qux doesn't implement Foo.
struct Qux {
    qux: int,
    Foo
}

As for non-struct traits, anonymous fields would provide a default
implementation. That is, suppose that:

impl Trait for Foo { ... }

Then one would be need to write (explicitly!):

impl Trait for Bar {} // Just use the default from Foo

Or:

impl Trait for Bar { ... override some of the methods ... };

(I think it is a bad idea to have traits be implemented implicitly just
because one anonymous field implements them; IMVHO an explicit "impl Trait
for Container" is a "very good idea").

This way you can have your cake and eat it 2. I think it is pretty clean -
traits do arbitrary mixin things with virtual-function cost (_with_
implementation reuse); And there's a "by definition single inheritance"
special access-my-data-members-at-fixed-offset trait whose existence does
not impact the power of the normal mixin traits in any way.
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to