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.
Currently we have some rather complex rules for when an object type
@T(or&Tetc) for a traitTimplements the traitT. I think we should just say that@Tdoes not implementT.We can instead add a deriving mode
#[deriving_self(managed|borrowed|owned)]to derive an implementation ofTfor@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:
We can come up with rules that prevent these examples, but those rules ultimately get quite complex. Simply saying that
@T does not implement Tavoids 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.