diff --git a/src/librustc/back/abi.rs b/src/librustc/back/abi.rs index e722e1a33c62b..004170dea7fe6 100644 --- a/src/librustc/back/abi.rs +++ b/src/librustc/back/abi.rs @@ -57,12 +57,10 @@ pub static n_tydesc_fields: uint = 8u; pub static fn_field_code: uint = 0u; pub static fn_field_box: uint = 1u; -// The three fields of a trait object/trait instance: vtable, box, and type -// description. +// The two fields of a trait object/trait instance: vtable and box. +// The vtable contains the type descriptor as first element. pub static trt_field_vtable: uint = 0u; pub static trt_field_box: uint = 1u; -// This field is only present in unique trait objects, so it comes last. -pub static trt_field_tydesc: uint = 2u; pub static vec_elt_fill: uint = 0u; diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 3e3fdf686e34c..e9febb51005cf 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -40,7 +40,6 @@ use middle::trans::type_::Type; use core::io; use core::libc::c_uint; use core::str; -use core::vec; use extra::time; use syntax::ast; @@ -578,11 +577,19 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) { bcx } ty::ty_trait(_, _, ty::UniqTraitStore, _) => { - let llval = GEPi(bcx, v, [0, abi::trt_field_box]); - let lltydesc = Load(bcx, GEPi(bcx, v, [0, abi::trt_field_tydesc])); - call_tydesc_glue_full(bcx, llval, lltydesc, - abi::tydesc_field_take_glue, None); - bcx + let lluniquevalue = GEPi(bcx, v, [0, abi::trt_field_box]); + let llvtable = Load(bcx, GEPi(bcx, v, [0, abi::trt_field_vtable])); + + // Cast the vtable to a pointer to a pointer to a tydesc. + let llvtable = PointerCast(bcx, llvtable, + bcx.ccx().tydesc_type.ptr_to().ptr_to()); + let lltydesc = Load(bcx, llvtable); + call_tydesc_glue_full(bcx, + lluniquevalue, + lltydesc, + abi::tydesc_field_take_glue, + None); + bcx } ty::ty_opaque_closure_ptr(ck) => { closure::make_opaque_cbox_take_glue(bcx, ck, v) diff --git a/src/test/run-pass/owned-trait-objects.rs b/src/test/run-pass/owned-trait-objects.rs new file mode 100644 index 0000000000000..50b6666a20be1 --- /dev/null +++ b/src/test/run-pass/owned-trait-objects.rs @@ -0,0 +1,37 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::uint::{range}; + +trait FooTrait { + fn foo(&self) -> uint; +} + +struct BarStruct { + x: uint +} + +impl FooTrait for BarStruct { + fn foo(&self) -> uint { + self.x + } +} + +pub fn main() { + let foos: ~[ ~FooTrait ] = ~[ + ~BarStruct{ x: 0 } as ~FooTrait, + ~BarStruct{ x: 1 } as ~FooTrait, + ~BarStruct{ x: 2 } as ~FooTrait + ]; + + for range(0, foos.len()) |i| { + assert_eq!(i, foos[i].foo()); + } +}