Closed
Description
The code below outputs ((6340760, 140201758297392), (6340840, 140201758297424), (6340856, 140201758297472), (6340872, 140201758297504))
(exact numbers may vary). The important part is that the vtables seem to get newly created for ~1 and ~2 (and also @1 and @2) even though they could easily use the same vtables.
use std::cast::transmute;
trait Foo {
fn foo(&self) {}
}
impl Foo for uint {}
impl Foo for int {}
unsafe {
(transmute::<~Foo, (uint,uint)>(~1i as ~Foo),
transmute::<@Foo, (uint,uint)>(@1i as @Foo),
transmute::<~Foo, (uint,uint)>(~2i as ~Foo),
transmute::<@Foo, (uint,uint)>(@2i as @Foo))
}
The code was fed to rusti, original below (thanks to dbaupp):
13:55 < dbaupp> rusti: use std::cast::transmute; trait Foo { fn foo(&self) {} } impl Foo for uint {} impl Foo for int {} unsafe {(transmute::<~Foo, (uint,uint)>(~1i as ~Foo),transmute::<@Foo, (uint,uint)>(@1i as @Foo),transmute::<~Foo, (uint,uint)>(~2i as ~Foo),transmute::<@Foo, (uint,uint)>(@2i as @Foo))}
13:55 -rusti:#rust- ((6340760, 140201758297392), (6340840, 140201758297424), (6340856, 140201758297472), (6340872, 140201758297504))
Swapping vtables appears to work just fine, even between ~Trait and &Trait (but not between ~Trait and @trait):
use std::cast::transmute;
trait Foo{
fn foo(&mut self);
fn bar(&self)->int;
}
impl Foo for int{
fn foo(&mut self) {
*self=*self+1
}
fn bar(&self)->int{
*self
}
};
unsafe{
let (a1,a2) = transmute::<~Foo,(uint,uint)>(~1 as ~Foo);
let (b1,b2) = transmute::<&mut Foo,(uint,uint)>(&mut 2 as &mut Foo);
let mut a = transmute::<(uint,uint),~Foo>((b1,a2));
let b = transmute::<(uint,uint),&mut Foo>((a1,b2));
a.foo();b.foo();
(a.bar(),b.bar() )
}
Outputs (2,3) in rusti.
14:24 < Thiez> rusti: use std::cast::transmute; trait Foo{fn foo(&mut self);fn bar(&self)->int;} impl Foo for int{fn foo(&mut self){*self=*self+1}fn bar(&self)->int{*self}}; unsafe{ let
(a1,a2)=transmute::<~Foo,(uint,uint)>(~1 as ~Foo); let (b1,b2)=transmute::<&mut Foo,(uint,uint)>(&mut 2 as &mut Foo); let mut a=transmute::<(uint,uint),~Foo>((b1,a2));let b =
transmute::<(uint,uint),&mut Foo>((a1,b2)); a.foo();b.foo();(a.bar(),b.bar()) }
14:24 -rusti:#rust- (2, 3)
It seems to me we should generate the vtables at compile time.