Description
Currently we have some rather complex rules for when an object type @T
(or &T
etc) for a trait T
implements the trait T
. I think we should just say that @T
does not implement T
.
We can instead add a deriving mode #[deriving_self(managed|borrowed|owned)]
to derive an implementation of T
for @T
, &T
, or ~T
.
Problems that this avoids
There are a number of unsoundness issues that can result from object types implementing their associated trait. Consider the following examples:
fn foo<T: Eq>(x: &T, y: &T) { ... x.eq(y) ... }
foo::<@Eq>(1 as @Eq, @"hi" as @Eq) // now we are comparing 1.eq("hi")!
trait AtFoo { fn foo(@self, ...) { ... } }
fn bar<T: AtFoo>(x: @T) { x.foo(); }
bar::<~AtFoo>(@(x as ~AtFoo)) // now we are calling `bar()` with a `~Foo` receiver!
trait MakeMe { fn foo() -> Self { ... } }
fn bar<T: MakeMe>(x: T) { ... let y = MakeMe::foo(); ... }
bar::<@MakeMe>(1 as @MakeMe); // now x has type @MakeMe but y has type int
We can come up with rules that prevent these examples, but those rules ultimately get quite complex. Simply saying that @T does not implement T
avoids all these problems. Then we can add a deriving rule. All of the scenarios above would result in a type check violation when you tried to actually write out that impl.