fully implement size_of_val
and add various tests that now succeed
This commit is contained in:
parent
17e336c7d9
commit
0f578f0d2e
@ -621,6 +621,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let src = self.eval_operand_to_ptr(operand)?;
|
||||
let src_ty = self.operand_ty(operand);
|
||||
let dest_ty = self.monomorphize(dest_ty, self.substs());
|
||||
// FIXME: cases where dest_ty is not a fat pointer. e.g. Arc<Struct> -> Arc<Trait>
|
||||
assert!(self.type_is_fat_ptr(dest_ty));
|
||||
let (ptr, extra) = self.get_fat_ptr(dest);
|
||||
self.move_(src, ptr, src_ty)?;
|
||||
@ -883,6 +884,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let offset = variant.field_offset(field.index()).bytes();
|
||||
let ptr = base.ptr.offset(offset as isize);
|
||||
match (&field_ty.sty, base.extra) {
|
||||
(&ty::TyStr, extra @ LvalueExtra::Length(_)) |
|
||||
(&ty::TySlice(_), extra @ LvalueExtra::Length(_)) |
|
||||
(&ty::TyTrait(_), extra @ LvalueExtra::Vtable(_)) => return Ok(Lvalue {
|
||||
ptr: ptr,
|
||||
extra: extra,
|
||||
|
@ -188,22 +188,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
"size_of_val" => {
|
||||
let ty = substs.type_at(0);
|
||||
if self.type_is_sized(ty) {
|
||||
let size = self.type_size(ty) as u64;
|
||||
self.memory.write_uint(dest, size, pointer_size)?;
|
||||
} else {
|
||||
match ty.sty {
|
||||
ty::TySlice(_) | ty::TyStr => {
|
||||
let elem_ty = ty.sequence_element_type(self.tcx);
|
||||
let elem_size = self.type_size(elem_ty) as u64;
|
||||
let ptr_size = self.memory.pointer_size() as isize;
|
||||
let n = self.memory.read_usize(args_ptrs[0].offset(ptr_size))?;
|
||||
self.memory.write_uint(dest, n * elem_size, pointer_size)?;
|
||||
}
|
||||
|
||||
_ => return Err(EvalError::Unimplemented(format!("unimplemented: size_of_val::<{:?}>", ty))),
|
||||
}
|
||||
}
|
||||
let (size, _) = self.size_and_align_of_dst(ty, args_ptrs[0])?;
|
||||
self.memory.write_uint(dest, size, pointer_size)?;
|
||||
}
|
||||
// FIXME: wait for eval_operand_to_ptr to be gone
|
||||
/*
|
||||
@ -248,4 +234,114 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
// current frame.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn size_and_align_of_dst(
|
||||
&self,
|
||||
ty: ty::Ty<'tcx>,
|
||||
value: Pointer,
|
||||
) -> EvalResult<'tcx, (u64, u64)> {
|
||||
let pointer_size = self.memory.pointer_size();
|
||||
if self.type_is_sized(ty) {
|
||||
Ok((self.type_size(ty) as u64, self.type_align(ty) as u64))
|
||||
} else {
|
||||
match ty.sty {
|
||||
ty::TyAdt(def, substs) => {
|
||||
// First get the size of all statically known fields.
|
||||
// Don't use type_of::sizing_type_of because that expects t to be sized,
|
||||
// and it also rounds up to alignment, which we want to avoid,
|
||||
// as the unsized field's alignment could be smaller.
|
||||
assert!(!ty.is_simd());
|
||||
let layout = self.type_layout(ty);
|
||||
debug!("DST {} layout: {:?}", ty, layout);
|
||||
|
||||
// Returns size in bytes of all fields except the last one
|
||||
// (we will be recursing on the last one).
|
||||
fn local_prefix_bytes(variant: &ty::layout::Struct) -> u64 {
|
||||
let fields = variant.offset_after_field.len();
|
||||
if fields > 1 {
|
||||
variant.offset_after_field[fields - 2].bytes()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
let (sized_size, sized_align) = match *layout {
|
||||
ty::layout::Layout::Univariant { ref variant, .. } => {
|
||||
(local_prefix_bytes(variant), variant.align.abi())
|
||||
}
|
||||
_ => {
|
||||
bug!("size_and_align_of_dst: expcted Univariant for `{}`, found {:#?}",
|
||||
ty, layout);
|
||||
}
|
||||
};
|
||||
debug!("DST {} statically sized prefix size: {} align: {}",
|
||||
ty, sized_size, sized_align);
|
||||
|
||||
// Recurse to get the size of the dynamically sized field (must be
|
||||
// the last field).
|
||||
let last_field = def.struct_variant().fields.last().unwrap();
|
||||
let field_ty = self.field_ty(substs, last_field);
|
||||
let (unsized_size, unsized_align) = self.size_and_align_of_dst(field_ty, value)?;
|
||||
|
||||
// FIXME (#26403, #27023): We should be adding padding
|
||||
// to `sized_size` (to accommodate the `unsized_align`
|
||||
// required of the unsized field that follows) before
|
||||
// summing it with `sized_size`. (Note that since #26403
|
||||
// is unfixed, we do not yet add the necessary padding
|
||||
// here. But this is where the add would go.)
|
||||
|
||||
// Return the sum of sizes and max of aligns.
|
||||
let size = sized_size + unsized_size;
|
||||
|
||||
// Choose max of two known alignments (combined value must
|
||||
// be aligned according to more restrictive of the two).
|
||||
let align = ::std::cmp::max(sized_align, unsized_align);
|
||||
|
||||
// Issue #27023: must add any necessary padding to `size`
|
||||
// (to make it a multiple of `align`) before returning it.
|
||||
//
|
||||
// Namely, the returned size should be, in C notation:
|
||||
//
|
||||
// `size + ((size & (align-1)) ? align : 0)`
|
||||
//
|
||||
// emulated via the semi-standard fast bit trick:
|
||||
//
|
||||
// `(size + (align-1)) & -align`
|
||||
|
||||
if size & (align - 1) != 0 {
|
||||
Ok((size + align, align))
|
||||
} else {
|
||||
Ok((size, align))
|
||||
}
|
||||
}
|
||||
ty::TyTrait(..) => {
|
||||
let (_, vtable) = self.get_fat_ptr(value);
|
||||
let vtable = self.memory.read_ptr(vtable)?;
|
||||
// the second entry in the vtable is the dynamic size of the object.
|
||||
let size = self.memory.read_usize(vtable.offset(pointer_size as isize))?;
|
||||
let align = self.memory.read_usize(vtable.offset(pointer_size as isize * 2))?;
|
||||
Ok((size, align))
|
||||
}
|
||||
|
||||
ty::TySlice(_) | ty::TyStr => {
|
||||
let elem_ty = ty.sequence_element_type(self.tcx);
|
||||
let elem_size = self.type_size(elem_ty) as u64;
|
||||
let (_, len_ptr) = self.get_fat_ptr(value);
|
||||
let n = self.memory.read_usize(len_ptr)?;
|
||||
let align = self.type_align(elem_ty);
|
||||
Ok((n * elem_size, align as u64))
|
||||
}
|
||||
|
||||
_ => bug!("size_of_val::<{:?}>", ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Returns the normalized type of a struct field
|
||||
fn field_ty(
|
||||
&self,
|
||||
param_substs: &Substs<'tcx>,
|
||||
f: ty::FieldDef<'tcx>,
|
||||
)-> ty::Ty<'tcx> {
|
||||
self.tcx.normalize_associated_type(&f.ty(self.tcx, param_substs))
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
bytes: Vec::new(),
|
||||
relocations: BTreeMap::new(),
|
||||
undef_mask: UndefMask::new(0),
|
||||
align: 1,
|
||||
align: 8, // should be infinity?
|
||||
immutable: false, // must be mutable, because sometimes we "move out" of a ZST
|
||||
};
|
||||
mem.alloc_map.insert(ZST_ALLOC_ID, alloc);
|
||||
|
54
tests/run-pass/cast-rfc0401-vtable-kinds.rs
Normal file
54
tests/run-pass/cast-rfc0401-vtable-kinds.rs
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Check that you can cast between different pointers to trait objects
|
||||
// whose vtable have the same kind (both lengths, or both trait pointers).
|
||||
|
||||
trait Foo<T> {
|
||||
fn foo(&self, _: T) -> u32 { 42 }
|
||||
}
|
||||
|
||||
trait Bar {
|
||||
fn bar(&self) { println!("Bar!"); }
|
||||
}
|
||||
|
||||
impl<T> Foo<T> for () {}
|
||||
impl Foo<u32> for u32 { fn foo(&self, _: u32) -> u32 { self+43 } }
|
||||
impl Bar for () {}
|
||||
|
||||
unsafe fn round_trip_and_call<'a>(t: *const (Foo<u32>+'a)) -> u32 {
|
||||
let foo_e : *const Foo<u16> = t as *const _;
|
||||
let r_1 = foo_e as *mut Foo<u32>;
|
||||
|
||||
(&*r_1).foo(0)
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct FooS<T:?Sized>(T);
|
||||
#[repr(C)]
|
||||
struct BarS<T:?Sized>(T);
|
||||
|
||||
fn foo_to_bar<T:?Sized>(u: *const FooS<T>) -> *const BarS<T> {
|
||||
u as *const BarS<T>
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = 4u32;
|
||||
let y : &Foo<u32> = &x;
|
||||
let fl = unsafe { round_trip_and_call(y as *const Foo<u32>) };
|
||||
assert_eq!(fl, (43+4));
|
||||
|
||||
let s = FooS([0,1,2]);
|
||||
let u: &FooS<[u32]> = &s;
|
||||
let u: *const FooS<[u32]> = u;
|
||||
let bar_ref : *const BarS<[u32]> = foo_to_bar(u);
|
||||
let z : &BarS<[u32]> = unsafe{&*bar_ref};
|
||||
assert_eq!(&z.0, &[0,1,2]);
|
||||
}
|
24
tests/run-pass/dst-irrefutable-bind.rs
Normal file
24
tests/run-pass/dst-irrefutable-bind.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct Test<T: ?Sized>(T);
|
||||
|
||||
fn main() {
|
||||
let x = Test([1,2,3]);
|
||||
let x : &Test<[i32]> = &x;
|
||||
|
||||
let & ref _y = x;
|
||||
|
||||
// Make sure binding to a fat pointer behind a reference
|
||||
// still works
|
||||
let slice = &[1,2,3];
|
||||
let x = Test(&slice);
|
||||
let Test(&_slice) = x;
|
||||
}
|
113
tests/run-pass/dst-raw.rs
Normal file
113
tests/run-pass/dst-raw.rs
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright 2014 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test DST raw pointers
|
||||
|
||||
|
||||
trait Trait {
|
||||
fn foo(&self) -> isize;
|
||||
}
|
||||
|
||||
struct A {
|
||||
f: isize
|
||||
}
|
||||
impl Trait for A {
|
||||
fn foo(&self) -> isize {
|
||||
self.f
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo<T: ?Sized> {
|
||||
f: T
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
// raw trait object
|
||||
let x = A { f: 42 };
|
||||
let z: *const Trait = &x;
|
||||
let r = unsafe {
|
||||
(&*z).foo()
|
||||
};
|
||||
assert_eq!(r, 42);
|
||||
|
||||
// raw DST struct
|
||||
let p = Foo {f: A { f: 42 }};
|
||||
let o: *const Foo<Trait> = &p;
|
||||
let r = unsafe {
|
||||
(&*o).f.foo()
|
||||
};
|
||||
assert_eq!(r, 42);
|
||||
|
||||
// raw slice
|
||||
let a: *const [_] = &[1, 2, 3];
|
||||
unsafe {
|
||||
let b = (*a)[2];
|
||||
assert_eq!(b, 3);
|
||||
let len = (*a).len();
|
||||
assert_eq!(len, 3);
|
||||
}
|
||||
|
||||
// raw slice with explicit cast
|
||||
let a = &[1, 2, 3] as *const [i32];
|
||||
unsafe {
|
||||
let b = (*a)[2];
|
||||
assert_eq!(b, 3);
|
||||
let len = (*a).len();
|
||||
assert_eq!(len, 3);
|
||||
}
|
||||
|
||||
// raw DST struct with slice
|
||||
let c: *const Foo<[_]> = &Foo {f: [1, 2, 3]};
|
||||
unsafe {
|
||||
let b = (&*c).f[0];
|
||||
assert_eq!(b, 1);
|
||||
let len = (&*c).f.len();
|
||||
assert_eq!(len, 3);
|
||||
}
|
||||
|
||||
// all of the above with *mut
|
||||
let mut x = A { f: 42 };
|
||||
let z: *mut Trait = &mut x;
|
||||
let r = unsafe {
|
||||
(&*z).foo()
|
||||
};
|
||||
assert_eq!(r, 42);
|
||||
|
||||
let mut p = Foo {f: A { f: 42 }};
|
||||
let o: *mut Foo<Trait> = &mut p;
|
||||
let r = unsafe {
|
||||
(&*o).f.foo()
|
||||
};
|
||||
assert_eq!(r, 42);
|
||||
|
||||
let a: *mut [_] = &mut [1, 2, 3];
|
||||
unsafe {
|
||||
let b = (*a)[2];
|
||||
assert_eq!(b, 3);
|
||||
let len = (*a).len();
|
||||
assert_eq!(len, 3);
|
||||
}
|
||||
|
||||
let a = &mut [1, 2, 3] as *mut [i32];
|
||||
unsafe {
|
||||
let b = (*a)[2];
|
||||
assert_eq!(b, 3);
|
||||
let len = (*a).len();
|
||||
assert_eq!(len, 3);
|
||||
}
|
||||
|
||||
let c: *mut Foo<[_]> = &mut Foo {f: [1, 2, 3]};
|
||||
unsafe {
|
||||
let b = (&*c).f[0];
|
||||
assert_eq!(b, 1);
|
||||
let len = (&*c).f.len();
|
||||
assert_eq!(len, 3);
|
||||
}
|
||||
}
|
85
tests/run-pass/dst-struct-sole.rs
Normal file
85
tests/run-pass/dst-struct-sole.rs
Normal file
@ -0,0 +1,85 @@
|
||||
// Copyright 2014 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// As dst-struct.rs, but the unsized field is the only field in the struct.
|
||||
|
||||
|
||||
struct Fat<T: ?Sized> {
|
||||
ptr: T
|
||||
}
|
||||
|
||||
// x is a fat pointer
|
||||
fn foo(x: &Fat<[isize]>) {
|
||||
let y = &x.ptr;
|
||||
assert_eq!(x.ptr.len(), 3);
|
||||
assert_eq!(y[0], 1);
|
||||
assert_eq!(x.ptr[1], 2);
|
||||
}
|
||||
|
||||
fn foo2<T:ToBar>(x: &Fat<[T]>) {
|
||||
let y = &x.ptr;
|
||||
let bar = Bar;
|
||||
assert_eq!(x.ptr.len(), 3);
|
||||
assert_eq!(y[0].to_bar(), bar);
|
||||
assert_eq!(x.ptr[1].to_bar(), bar);
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
struct Bar;
|
||||
|
||||
trait ToBar {
|
||||
fn to_bar(&self) -> Bar;
|
||||
}
|
||||
|
||||
impl ToBar for Bar {
|
||||
fn to_bar(&self) -> Bar {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
// With a vec of ints.
|
||||
let f1 = Fat { ptr: [1, 2, 3] };
|
||||
foo(&f1);
|
||||
let f2 = &f1;
|
||||
foo(f2);
|
||||
let f3: &Fat<[isize]> = f2;
|
||||
foo(f3);
|
||||
let f4: &Fat<[isize]> = &f1;
|
||||
foo(f4);
|
||||
let f5: &Fat<[isize]> = &Fat { ptr: [1, 2, 3] };
|
||||
foo(f5);
|
||||
|
||||
// With a vec of Bars.
|
||||
let bar = Bar;
|
||||
let f1 = Fat { ptr: [bar, bar, bar] };
|
||||
foo2(&f1);
|
||||
let f2 = &f1;
|
||||
foo2(f2);
|
||||
let f3: &Fat<[Bar]> = f2;
|
||||
foo2(f3);
|
||||
let f4: &Fat<[Bar]> = &f1;
|
||||
foo2(f4);
|
||||
let f5: &Fat<[Bar]> = &Fat { ptr: [bar, bar, bar] };
|
||||
foo2(f5);
|
||||
|
||||
// Assignment.
|
||||
let f5: &mut Fat<[isize]> = &mut Fat { ptr: [1, 2, 3] };
|
||||
f5.ptr[1] = 34;
|
||||
assert_eq!(f5.ptr[0], 1);
|
||||
assert_eq!(f5.ptr[1], 34);
|
||||
assert_eq!(f5.ptr[2], 3);
|
||||
|
||||
// Zero size vec.
|
||||
let f5: &Fat<[isize]> = &Fat { ptr: [] };
|
||||
assert!(f5.ptr.is_empty());
|
||||
let f5: &Fat<[Bar]> = &Fat { ptr: [] };
|
||||
assert!(f5.ptr.is_empty());
|
||||
}
|
70
tests/run-pass/issue-23261.rs
Normal file
70
tests/run-pass/issue-23261.rs
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Matching on a DST struct should not trigger an LLVM assertion.
|
||||
|
||||
struct Foo<T: ?Sized> {
|
||||
a: i32,
|
||||
inner: T
|
||||
}
|
||||
|
||||
trait Get {
|
||||
fn get(&self) -> i32;
|
||||
}
|
||||
|
||||
impl Get for i32 {
|
||||
fn get(&self) -> i32 {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
fn check_val(val: &Foo<[u8]>) {
|
||||
match *val {
|
||||
Foo { a, .. } => {
|
||||
assert_eq!(a, 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_dst_val(val: &Foo<[u8]>) {
|
||||
match *val {
|
||||
Foo { ref inner, .. } => {
|
||||
assert_eq!(inner, [1, 2, 3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_both(val: &Foo<[u8]>) {
|
||||
match *val {
|
||||
Foo { a, ref inner } => {
|
||||
assert_eq!(a, 32);
|
||||
assert_eq!(inner, [1, 2, 3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait_obj(val: &Foo<Get>) {
|
||||
match *val {
|
||||
Foo { a, ref inner } => {
|
||||
assert_eq!(a, 32);
|
||||
assert_eq!(inner.get(), 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo: &Foo<[u8]> = &Foo { a: 32, inner: [1, 2, 3] };
|
||||
check_val(foo);
|
||||
check_dst_val(foo);
|
||||
check_both(foo);
|
||||
|
||||
let foo: &Foo<Get> = &Foo { a: 32, inner: 32 };
|
||||
check_trait_obj(foo);
|
||||
}
|
28
tests/run-pass/issue-36278-prefix-nesting.rs
Normal file
28
tests/run-pass/issue-36278-prefix-nesting.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2016 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Issue 36278: On an unsized struct with >1 level of nontrivial
|
||||
// nesting, ensure we are computing dynamic size of prefix correctly.
|
||||
|
||||
use std::mem;
|
||||
|
||||
const SZ: usize = 100;
|
||||
struct P<T: ?Sized>([u8; SZ], T);
|
||||
|
||||
type Ack<T> = P<P<T>>;
|
||||
|
||||
fn main() {
|
||||
let size_of_sized; let size_of_unsized;
|
||||
let x: Box<Ack<[u8; 0]>> = Box::new(P([0; SZ], P([0; SZ], [0; 0])));
|
||||
size_of_sized = mem::size_of_val::<Ack<_>>(&x);
|
||||
let y: Box<Ack<[u8 ]>> = x;
|
||||
size_of_unsized = mem::size_of_val::<Ack<_>>(&y);
|
||||
assert_eq!(size_of_sized, size_of_unsized);
|
||||
}
|
61
tests/run-pass/mir_fat_ptr.rs
Normal file
61
tests/run-pass/mir_fat_ptr.rs
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// test that ordinary fat pointer operations work.
|
||||
|
||||
struct Wrapper<T: ?Sized>(u32, T);
|
||||
|
||||
struct FatPtrContainer<'a> {
|
||||
ptr: &'a [u8]
|
||||
}
|
||||
|
||||
fn fat_ptr_project(a: &Wrapper<[u8]>) -> &[u8] {
|
||||
&a.1
|
||||
}
|
||||
|
||||
fn fat_ptr_simple(a: &[u8]) -> &[u8] {
|
||||
a
|
||||
}
|
||||
|
||||
fn fat_ptr_via_local(a: &[u8]) -> &[u8] {
|
||||
let x = a;
|
||||
x
|
||||
}
|
||||
|
||||
fn fat_ptr_from_struct(s: FatPtrContainer) -> &[u8] {
|
||||
s.ptr
|
||||
}
|
||||
|
||||
fn fat_ptr_to_struct(a: &[u8]) -> FatPtrContainer {
|
||||
FatPtrContainer { ptr: a }
|
||||
}
|
||||
|
||||
fn fat_ptr_store_to<'a>(a: &'a [u8], b: &mut &'a [u8]) {
|
||||
*b = a;
|
||||
}
|
||||
|
||||
fn fat_ptr_constant() -> &'static str {
|
||||
"HELLO"
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = Wrapper(4, [7,6,5]);
|
||||
|
||||
let p = fat_ptr_project(&a);
|
||||
let p = fat_ptr_simple(p);
|
||||
let p = fat_ptr_via_local(p);
|
||||
let p = fat_ptr_from_struct(fat_ptr_to_struct(p));
|
||||
|
||||
let mut target : &[u8] = &[42];
|
||||
fat_ptr_store_to(p, &mut target);
|
||||
assert_eq!(target, &a.1);
|
||||
|
||||
assert_eq!(fat_ptr_constant(), "HELLO");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user