core: Stabilize the mem module

Excluding the functions inherited from the cast module last week (with marked
stability levels), these functions received the following treatment.

* size_of - this method has become #[stable]
* nonzero_size_of/nonzero_size_of_val - these methods have been removed
* min_align_of - this method is now #[stable]
* pref_align_of - this method has been renamed without the
  `pref_` prefix, and it is the "default alignment" now. This decision is in line
  with what clang does (see url linked in comment on function). This function
  is now #[stable].
* init - renamed to zeroed and marked #[stable]
* uninit - marked #[stable]
* move_val_init - renamed to overwrite and marked #[stable]
* {from,to}_{be,le}{16,32,64} - all functions marked #[stable]
* swap/replace/drop - marked #[stable]
* size_of_val/min_align_of_val/align_of_val - these functions are marked
  #[unstable], but will continue to exist in some form. Concerns have been
  raised about their `_val` prefix.

[breaking-change]
This commit is contained in:
Alex Crichton 2014-05-17 00:56:00 -07:00
parent 1ba7bd10c9
commit 19dc3b50bd
19 changed files with 223 additions and 138 deletions

View File

@ -216,9 +216,9 @@ impl<T: Send> Unique<T> {
// we *need* valid pointer.
assert!(!ptr.is_null());
// `*ptr` is uninitialized, and `*ptr = value` would attempt to destroy it
// move_val_init moves a value into this memory without
// `overwrite` moves a value into this memory without
// attempting to drop the original value.
mem::move_val_init(&mut *ptr, value);
mem::overwrite(&mut *ptr, value);
Unique{ptr: ptr}
}
}

View File

@ -35,7 +35,6 @@ use std::cmp;
use std::intrinsics::{TyDesc, get_tydesc};
use std::intrinsics;
use std::mem;
use std::mem::min_align_of;
use std::num;
use std::ptr::read;
use std::rc::Rc;
@ -155,7 +154,7 @@ unsafe fn destroy_chunk(chunk: &Chunk) {
}
// Find where the next tydesc lives
idx = round_up(start + size, mem::pref_align_of::<*TyDesc>());
idx = round_up(start + size, mem::align_of::<*TyDesc>());
}
}
@ -207,9 +206,10 @@ impl Arena {
#[inline]
fn alloc_copy<'a, T>(&'a mut self, op: || -> T) -> &'a T {
unsafe {
let ptr = self.alloc_copy_inner(mem::size_of::<T>(), min_align_of::<T>());
let ptr = self.alloc_copy_inner(mem::size_of::<T>(),
mem::min_align_of::<T>());
let ptr = ptr as *mut T;
mem::move_val_init(&mut (*ptr), op());
mem::overwrite(&mut (*ptr), op());
return &*ptr;
}
}
@ -239,7 +239,7 @@ impl Arena {
return self.alloc_noncopy_grow(n_bytes, align);
}
self.head.fill.set(round_up(end, mem::pref_align_of::<*TyDesc>()));
self.head.fill.set(round_up(end, mem::align_of::<*TyDesc>()));
//debug!("idx = {}, size = {}, align = {}, fill = {}",
// start, n_bytes, align, head.fill);
@ -254,14 +254,15 @@ impl Arena {
unsafe {
let tydesc = get_tydesc::<T>();
let (ty_ptr, ptr) =
self.alloc_noncopy_inner(mem::size_of::<T>(), min_align_of::<T>());
self.alloc_noncopy_inner(mem::size_of::<T>(),
mem::min_align_of::<T>());
let ty_ptr = ty_ptr as *mut uint;
let ptr = ptr as *mut T;
// Write in our tydesc along with a bit indicating that it
// has *not* been initialized yet.
*ty_ptr = mem::transmute(tydesc);
// Actually initialize it
mem::move_val_init(&mut(*ptr), op());
mem::overwrite(&mut(*ptr), op());
// Now that we are done, update the tydesc to indicate that
// the object is there.
*ty_ptr = bitpack_tydesc_ptr(tydesc, true);
@ -357,9 +358,10 @@ impl<T> TypedArenaChunk<T> {
size = size.checked_add(&elems_size).unwrap();
let mut chunk = unsafe {
let chunk = exchange_malloc(size, min_align_of::<TypedArenaChunk<T>>());
let chunk = exchange_malloc(size,
mem::min_align_of::<TypedArenaChunk<T>>());
let mut chunk: Box<TypedArenaChunk<T>> = mem::transmute(chunk);
mem::move_val_init(&mut chunk.next, next);
mem::overwrite(&mut chunk.next, next);
chunk
};
@ -396,7 +398,8 @@ impl<T> TypedArenaChunk<T> {
fn start(&self) -> *u8 {
let this: *TypedArenaChunk<T> = self;
unsafe {
mem::transmute(round_up(this.offset(1) as uint, min_align_of::<T>()))
mem::transmute(round_up(this.offset(1) as uint,
mem::min_align_of::<T>()))
}
}
@ -440,7 +443,7 @@ impl<T> TypedArena<T> {
}
let ptr: &'a mut T = mem::transmute(this.ptr);
mem::move_val_init(ptr, object);
mem::overwrite(ptr, object);
this.ptr = this.ptr.offset(1);
let ptr: &'a T = ptr;
ptr

View File

@ -13,7 +13,7 @@
#![allow(missing_doc)]
use std::clone::Clone;
use std::mem::{move_val_init, init, replace, swap};
use std::mem::{overwrite, zeroed, replace, swap};
use std::slice;
/// A priority queue implemented with a binary heap
@ -157,26 +157,26 @@ impl<T: TotalOrd> PriorityQueue<T> {
// compared to using swaps, which involves twice as many moves.
fn siftup(&mut self, start: uint, mut pos: uint) {
unsafe {
let new = replace(self.data.get_mut(pos), init());
let new = replace(self.data.get_mut(pos), zeroed());
while pos > start {
let parent = (pos - 1) >> 1;
if new > *self.data.get(parent) {
let x = replace(self.data.get_mut(parent), init());
move_val_init(self.data.get_mut(pos), x);
let x = replace(self.data.get_mut(parent), zeroed());
overwrite(self.data.get_mut(pos), x);
pos = parent;
continue
}
break
}
move_val_init(self.data.get_mut(pos), new);
overwrite(self.data.get_mut(pos), new);
}
}
fn siftdown_range(&mut self, mut pos: uint, end: uint) {
unsafe {
let start = pos;
let new = replace(self.data.get_mut(pos), init());
let new = replace(self.data.get_mut(pos), zeroed());
let mut child = 2 * pos + 1;
while child < end {
@ -184,13 +184,13 @@ impl<T: TotalOrd> PriorityQueue<T> {
if right < end && !(*self.data.get(child) > *self.data.get(right)) {
child = right;
}
let x = replace(self.data.get_mut(child), init());
move_val_init(self.data.get_mut(pos), x);
let x = replace(self.data.get_mut(child), zeroed());
overwrite(self.data.get_mut(pos), x);
pos = child;
child = 2 * pos + 1;
}
move_val_init(self.data.get_mut(pos), new);
overwrite(self.data.get_mut(pos), new);
self.siftup(start, pos);
}
}

View File

@ -10,7 +10,7 @@
//! Ordered containers with integer keys, implemented as radix tries (`TrieSet` and `TrieMap` types)
use std::mem::init;
use std::mem::zeroed;
use std::mem;
use std::slice::{Items, MutItems};
use std::slice;
@ -522,7 +522,8 @@ macro_rules! iterator_impl {
remaining_max: 0,
length: 0,
// ick :( ... at least the compiler will tell us if we screwed up.
stack: [init(), init(), init(), init(), init(), init(), init(), init()]
stack: [zeroed(), zeroed(), zeroed(), zeroed(), zeroed(),
zeroed(), zeroed(), zeroed()]
}
}
@ -532,8 +533,10 @@ macro_rules! iterator_impl {
remaining_min: 0,
remaining_max: 0,
length: 0,
stack: [init(), init(), init(), init(), init(), init(), init(), init(),
init(), init(), init(), init(), init(), init(), init(), init()]
stack: [zeroed(), zeroed(), zeroed(), zeroed(),
zeroed(), zeroed(), zeroed(), zeroed(),
zeroed(), zeroed(), zeroed(), zeroed(),
zeroed(), zeroed(), zeroed(), zeroed()]
}
}
}

View File

@ -19,31 +19,36 @@ use intrinsics::{bswap16, bswap32, bswap64};
/// Returns the size of a type in bytes.
#[inline]
#[stable]
pub fn size_of<T>() -> uint {
unsafe { intrinsics::size_of::<T>() }
}
/// Returns the size of the type that `_val` points to in bytes.
#[inline]
#[unstable = "the name of this function may change slightly before stabilizing"]
pub fn size_of_val<T>(_val: &T) -> uint {
size_of::<T>()
}
/// Returns the size of a type in bytes, or 1 if the actual size is zero.
///
/// Useful for building structures containing variable-length arrays.
/// Deprecated, this function will be removed soon
#[inline]
#[deprecated = "this function will be removed soon"]
pub fn nonzero_size_of<T>() -> uint {
match size_of::<T>() {
0 => 1,
x => x
n => n,
}
}
/// Returns the size in bytes of the type of the value that `_val` points to.
/// Deprecated, this function will be removed soon
#[inline]
pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
nonzero_size_of::<T>()
#[deprecated = "this function will be removed soon"]
pub fn nonzero_size_of_val<T>(val: &T) -> uint {
match size_of_val::<T>(val) {
0 => 1,
n => n,
}
}
/// Returns the ABI-required minimum alignment of a type
@ -51,6 +56,7 @@ pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
/// This is the alignment used for struct fields. It may be smaller
/// than the preferred alignment.
#[inline]
#[stable]
pub fn min_align_of<T>() -> uint {
unsafe { intrinsics::min_align_of::<T>() }
}
@ -58,44 +64,100 @@ pub fn min_align_of<T>() -> uint {
/// Returns the ABI-required minimum alignment of the type of the value that
/// `_val` points to
#[inline]
#[unstable = "the name of this function may change slightly before stabilizing"]
pub fn min_align_of_val<T>(_val: &T) -> uint {
min_align_of::<T>()
}
/// Returns the preferred alignment of a type
/// Returns the alignment in memory for a type.
///
/// This function will return the alignment, in bytes, of a type in memory. If
/// the alignment returned is adhered to, then the type is guaranteed to
/// function properly.
#[inline]
pub fn pref_align_of<T>() -> uint {
#[stable]
pub fn align_of<T>() -> uint {
// We use the preferred alignment as the default alignment for a type. This
// appears to be what clang migrated towards as well:
//
// http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20110725/044411.html
unsafe { intrinsics::pref_align_of::<T>() }
}
/// Returns the preferred alignment of the type of the value that
/// `_val` points to
/// Returns the alignment of the type of the value that `_val` points to.
///
/// This is similar to `align_of`, but function will properly handle types such
/// as trait objects (in the future), returning the alignment for an arbitrary
/// value at runtime.
#[inline]
pub fn pref_align_of_val<T>(_val: &T) -> uint {
pref_align_of::<T>()
#[unstable = "the name of this function may change slightly before stabilizing"]
pub fn align_of_val<T>(_val: &T) -> uint {
align_of::<T>()
}
/// Deprecated, this function has been renamed to align_of
#[inline]
#[deprecated = "use mem::align_of instead"]
pub fn pref_align_of<T>() -> uint { align_of::<T>() }
/// Deprecated, this function has been renamed to align_of_val
#[inline]
#[deprecated = "use mem::align_of_val instead"]
pub fn pref_align_of_val<T>(val: &T) -> uint { align_of_val(val) }
/// Create a value initialized to zero.
///
/// `init` is unsafe because it returns a zeroed-out datum,
/// which is unsafe unless T is Copy.
/// This function is similar to allocating space for a a local variable and
/// zeroing it out (an unsafe operation).
///
/// Care must be taken when using this function, if the type `T` has a
/// destructor and the value falls out of scope (due to unwinding or returning)
/// before being initialized, then the destructor will run on zeroed
/// data, likely leading to crashes.
///
/// This is useful for FFI functions sometimes, but should generally be avoided.
#[inline]
pub unsafe fn init<T>() -> T {
#[unstable = "the name of this function is subject to change"]
pub unsafe fn zeroed<T>() -> T {
intrinsics::init()
}
/// Create an uninitialized value.
/// Deprecated, use zeroed() instead
#[inline]
#[deprecated = "this function has been renamed to zeroed()"]
pub unsafe fn init<T>() -> T { zeroed() }
/// Create an uninitialized value.
///
/// Care must be taken when using this function, if the type `T` has a
/// destructor and the value falls out of scope (due to unwinding or returning)
/// before being initialized, then the destructor will run on uninitialized
/// data, likely leading to crashes.
///
/// This is useful for FFI functions sometimes, but should generally be avoided.
#[inline]
#[unstable = "the name of this function is subject to change"]
pub unsafe fn uninit<T>() -> T {
intrinsics::uninit()
}
/// Move a value to an uninitialized memory location.
/// Unsafely overwrite a memory location with the given value without destroying
/// the old value.
///
/// Drop glue is not run on the destination.
/// This operation is unsafe because it does not destroy the previous value
/// contained at the location `dst`. This could leak allocations or resources,
/// so care must be taken to previously deallocate the value at `dst`.
#[inline]
#[unstable = "the name of this function is subject to change"]
pub unsafe fn overwrite<T>(dst: *mut T, src: T) {
intrinsics::move_val_init(&mut *dst, src)
}
/// Deprecated, use move_val_init() instead
#[inline]
#[deprecated = "this function has been renamed to move_val_init()"]
pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
intrinsics::move_val_init(dst, src)
overwrite(dst, src)
}
/// Convert an u16 to little endian from the target's endianness.
@ -106,126 +168,150 @@ pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
/// Convert an u16 to little endian from the target's endianness.
///
/// On little endian, this is a no-op. On big endian, the bytes are swapped.
#[cfg(target_endian = "big")] #[inline] pub fn to_le16(x: u16) -> u16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "big")] #[inline] #[stable]
pub fn to_le16(x: u16) -> u16 { unsafe { bswap16(x) } }
/// Convert an u32 to little endian from the target's endianness.
///
/// On little endian, this is a no-op. On big endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn to_le32(x: u32) -> u32 { x }
#[cfg(target_endian = "little")] #[inline] #[stable]
pub fn to_le32(x: u32) -> u32 { x }
/// Convert an u32 to little endian from the target's endianness.
///
/// On little endian, this is a no-op. On big endian, the bytes are swapped.
#[cfg(target_endian = "big")] #[inline] pub fn to_le32(x: u32) -> u32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "big")] #[inline] #[stable]
pub fn to_le32(x: u32) -> u32 { unsafe { bswap32(x) } }
/// Convert an u64 to little endian from the target's endianness.
///
/// On little endian, this is a no-op. On big endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn to_le64(x: u64) -> u64 { x }
#[cfg(target_endian = "little")] #[inline] #[stable]
pub fn to_le64(x: u64) -> u64 { x }
/// Convert an u64 to little endian from the target's endianness.
///
/// On little endian, this is a no-op. On big endian, the bytes are swapped.
#[cfg(target_endian = "big")] #[inline] pub fn to_le64(x: u64) -> u64 { unsafe { bswap64(x) } }
#[cfg(target_endian = "big")] #[inline] #[stable]
pub fn to_le64(x: u64) -> u64 { unsafe { bswap64(x) } }
/// Convert an u16 to big endian from the target's endianness.
///
/// On big endian, this is a no-op. On little endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn to_be16(x: u16) -> u16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "little")] #[inline] #[stable]
pub fn to_be16(x: u16) -> u16 { unsafe { bswap16(x) } }
/// Convert an u16 to big endian from the target's endianness.
///
/// On big endian, this is a no-op. On little endian, the bytes are swapped.
#[cfg(target_endian = "big")] #[inline] pub fn to_be16(x: u16) -> u16 { x }
#[cfg(target_endian = "big")] #[inline] #[stable]
pub fn to_be16(x: u16) -> u16 { x }
/// Convert an u32 to big endian from the target's endianness.
///
/// On big endian, this is a no-op. On little endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn to_be32(x: u32) -> u32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "little")] #[inline] #[stable]
pub fn to_be32(x: u32) -> u32 { unsafe { bswap32(x) } }
/// Convert an u32 to big endian from the target's endianness.
///
/// On big endian, this is a no-op. On little endian, the bytes are swapped.
#[cfg(target_endian = "big")] #[inline] pub fn to_be32(x: u32) -> u32 { x }
#[cfg(target_endian = "big")] #[inline] #[stable]
pub fn to_be32(x: u32) -> u32 { x }
/// Convert an u64 to big endian from the target's endianness.
///
/// On big endian, this is a no-op. On little endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn to_be64(x: u64) -> u64 { unsafe { bswap64(x) } }
#[cfg(target_endian = "little")] #[inline] #[stable]
pub fn to_be64(x: u64) -> u64 { unsafe { bswap64(x) } }
/// Convert an u64 to big endian from the target's endianness.
///
/// On big endian, this is a no-op. On little endian, the bytes are swapped.
#[cfg(target_endian = "big")] #[inline] pub fn to_be64(x: u64) -> u64 { x }
#[cfg(target_endian = "big")] #[inline] #[stable]
pub fn to_be64(x: u64) -> u64 { x }
/// Convert an u16 from little endian to the target's endianness.
///
/// On little endian, this is a no-op. On big endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn from_le16(x: u16) -> u16 { x }
#[cfg(target_endian = "little")] #[inline] #[stable]
pub fn from_le16(x: u16) -> u16 { x }
/// Convert an u16 from little endian to the target's endianness.
///
/// On little endian, this is a no-op. On big endian, the bytes are swapped.
#[cfg(target_endian = "big")] #[inline] pub fn from_le16(x: u16) -> u16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "big")] #[inline] #[stable]
pub fn from_le16(x: u16) -> u16 { unsafe { bswap16(x) } }
/// Convert an u32 from little endian to the target's endianness.
///
/// On little endian, this is a no-op. On big endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn from_le32(x: u32) -> u32 { x }
#[cfg(target_endian = "little")] #[inline] #[stable]
pub fn from_le32(x: u32) -> u32 { x }
/// Convert an u32 from little endian to the target's endianness.
///
/// On little endian, this is a no-op. On big endian, the bytes are swapped.
#[cfg(target_endian = "big")] #[inline] pub fn from_le32(x: u32) -> u32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "big")] #[inline] #[stable]
pub fn from_le32(x: u32) -> u32 { unsafe { bswap32(x) } }
/// Convert an u64 from little endian to the target's endianness.
///
/// On little endian, this is a no-op. On big endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn from_le64(x: u64) -> u64 { x }
#[cfg(target_endian = "little")] #[inline] #[stable]
pub fn from_le64(x: u64) -> u64 { x }
/// Convert an u64 from little endian to the target's endianness.
///
/// On little endian, this is a no-op. On big endian, the bytes are swapped.
#[cfg(target_endian = "big")] #[inline] pub fn from_le64(x: u64) -> u64 { unsafe { bswap64(x) } }
#[cfg(target_endian = "big")] #[inline] #[stable]
pub fn from_le64(x: u64) -> u64 { unsafe { bswap64(x) } }
/// Convert an u16 from big endian to the target's endianness.
///
/// On big endian, this is a no-op. On little endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn from_be16(x: u16) -> u16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "little")] #[inline] #[stable]
pub fn from_be16(x: u16) -> u16 { unsafe { bswap16(x) } }
/// Convert an u16 from big endian to the target's endianness.
///
/// On big endian, this is a no-op. On little endian, the bytes are swapped.
#[cfg(target_endian = "big")] #[inline] pub fn from_be16(x: u16) -> u16 { x }
#[cfg(target_endian = "big")] #[inline] #[stable]
pub fn from_be16(x: u16) -> u16 { x }
/// Convert an u32 from big endian to the target's endianness.
///
/// On big endian, this is a no-op. On little endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn from_be32(x: u32) -> u32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "little")] #[inline] #[stable]
pub fn from_be32(x: u32) -> u32 { unsafe { bswap32(x) } }
/// Convert an u32 from big endian to the target's endianness.
///
/// On big endian, this is a no-op. On little endian, the bytes are swapped.
#[cfg(target_endian = "big")] #[inline] pub fn from_be32(x: u32) -> u32 { x }
#[cfg(target_endian = "big")] #[inline] #[stable]
pub fn from_be32(x: u32) -> u32 { x }
/// Convert an u64 from big endian to the target's endianness.
///
/// On big endian, this is a no-op. On little endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn from_be64(x: u64) -> u64 { unsafe { bswap64(x) } }
#[cfg(target_endian = "little")] #[inline] #[stable]
pub fn from_be64(x: u64) -> u64 { unsafe { bswap64(x) } }
/// Convert an u64 from big endian to the target's endianness.
///
/// On big endian, this is a no-op. On little endian, the bytes are swapped.
#[cfg(target_endian = "big")] #[inline] pub fn from_be64(x: u64) -> u64 { x }
#[cfg(target_endian = "big")] #[inline] #[stable]
pub fn from_be64(x: u64) -> u64 { x }
/**
* Swap the values at two mutable locations of the same type, without
* deinitialising or copying either one.
*/
#[inline]
#[stable]
pub fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
// Give ourselves some scratch space to work with
@ -279,6 +365,7 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
* ```
*/
#[inline]
#[stable]
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
swap(dest, &mut src);
src
@ -304,6 +391,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
/// println!("{}", *borrow);
/// ```
#[inline]
#[stable]
pub fn drop<T>(_x: T) { }
/// Moves a thing into the void.
@ -415,27 +503,11 @@ mod tests {
assert_eq!(size_of_val(&1u64), 8);
}
#[test]
fn nonzero_size_of_basic() {
type Z = [i8, ..0];
assert_eq!(size_of::<Z>(), 0u);
assert_eq!(nonzero_size_of::<Z>(), 1u);
assert_eq!(nonzero_size_of::<uint>(), size_of::<uint>());
}
#[test]
fn nonzero_size_of_val_basic() {
let z = [0u8, ..0];
assert_eq!(size_of_val(&z), 0u);
assert_eq!(nonzero_size_of_val(&z), 1u);
assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
}
#[test]
fn align_of_basic() {
assert_eq!(pref_align_of::<u8>(), 1u);
assert_eq!(pref_align_of::<u16>(), 2u);
assert_eq!(pref_align_of::<u32>(), 4u);
assert_eq!(align_of::<u8>(), 1u);
assert_eq!(align_of::<u16>(), 2u);
assert_eq!(align_of::<u32>(), 4u);
}
#[test]
@ -443,22 +515,22 @@ mod tests {
#[cfg(target_arch = "arm")]
#[cfg(target_arch = "mips")]
fn align_of_32() {
assert_eq!(pref_align_of::<uint>(), 4u);
assert_eq!(pref_align_of::<*uint>(), 4u);
assert_eq!(align_of::<uint>(), 4u);
assert_eq!(align_of::<*uint>(), 4u);
}
#[test]
#[cfg(target_arch = "x86_64")]
fn align_of_64() {
assert_eq!(pref_align_of::<uint>(), 8u);
assert_eq!(pref_align_of::<*uint>(), 8u);
assert_eq!(align_of::<uint>(), 8u);
assert_eq!(align_of::<*uint>(), 8u);
}
#[test]
fn align_of_val_basic() {
assert_eq!(pref_align_of_val(&1u8), 1u);
assert_eq!(pref_align_of_val(&1u16), 2u);
assert_eq!(pref_align_of_val(&1u32), 4u);
assert_eq!(align_of_val(&1u8), 1u);
assert_eq!(align_of_val(&1u16), 2u);
assert_eq!(align_of_val(&1u32), 4u);
}
#[test]

View File

@ -171,15 +171,17 @@ impl<A: Clone> Clone for ~[A] {
unsafe {
let ret = alloc(size) as *mut Vec<A>;
(*ret).fill = len * mem::nonzero_size_of::<A>();
(*ret).alloc = len * mem::nonzero_size_of::<A>();
let a_size = mem::size_of::<A>();
let a_size = if a_size == 0 {1} else {a_size};
(*ret).fill = len * a_size;
(*ret).alloc = len * a_size;
let mut i = 0;
let p = &mut (*ret).data as *mut _ as *mut A;
try_finally(
&mut i, (),
|i, ()| while *i < len {
mem::move_val_init(
mem::overwrite(
&mut(*p.offset(*i as int)),
self.unsafe_ref(*i).clone());
*i += 1;

View File

@ -1122,7 +1122,7 @@ impl<'a,T> MutableVector<'a, T> for &'a mut [T] {
#[inline]
unsafe fn init_elem(self, i: uint, val: T) {
mem::move_val_init(&mut (*self.as_mut_ptr().offset(i as int)), val);
mem::overwrite(&mut (*self.as_mut_ptr().offset(i as int)), val);
}
#[inline]
@ -1306,7 +1306,8 @@ macro_rules! iterator {
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
let diff = (self.end as uint) - (self.ptr as uint);
let exact = diff / mem::nonzero_size_of::<T>();
let size = mem::size_of::<T>();
let exact = diff / (if size == 0 {1} else {size});
(exact, Some(exact))
}
}

View File

@ -118,7 +118,7 @@ impl rtio::RtioFileStream for FileDesc {
fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result<int, IoError> {
let mut read = 0;
let mut overlap: libc::OVERLAPPED = unsafe { mem::init() };
let mut overlap: libc::OVERLAPPED = unsafe { mem::zeroed() };
overlap.Offset = offset as libc::DWORD;
overlap.OffsetHigh = (offset >> 32) as libc::DWORD;
let ret = unsafe {
@ -135,7 +135,7 @@ impl rtio::RtioFileStream for FileDesc {
fn pwrite(&mut self, buf: &[u8], mut offset: u64) -> Result<(), IoError> {
let mut cur = buf.as_ptr();
let mut remaining = buf.len();
let mut overlap: libc::OVERLAPPED = unsafe { mem::init() };
let mut overlap: libc::OVERLAPPED = unsafe { mem::zeroed() };
while remaining > 0 {
overlap.Offset = offset as libc::DWORD;
overlap.OffsetHigh = (offset >> 32) as libc::DWORD;

View File

@ -68,7 +68,7 @@ fn ip_to_inaddr(ip: ip::IpAddr) -> InAddr {
fn addr_to_sockaddr(addr: ip::SocketAddr) -> (libc::sockaddr_storage, uint) {
unsafe {
let storage: libc::sockaddr_storage = mem::init();
let storage: libc::sockaddr_storage = mem::zeroed();
let len = match ip_to_inaddr(addr.ip) {
InAddr(inaddr) => {
let storage: *mut libc::sockaddr_in = mem::transmute(&storage);
@ -120,7 +120,7 @@ fn setsockopt<T>(fd: sock_t, opt: libc::c_int, val: libc::c_int,
pub fn getsockopt<T: Copy>(fd: sock_t, opt: libc::c_int,
val: libc::c_int) -> IoResult<T> {
unsafe {
let mut slot: T = mem::init();
let mut slot: T = mem::zeroed();
let mut len = mem::size_of::<T>() as libc::socklen_t;
let ret = c::getsockopt(fd, opt, val,
&mut slot as *mut _ as *mut _,
@ -152,7 +152,7 @@ fn sockname(fd: sock_t,
*mut libc::socklen_t) -> libc::c_int)
-> IoResult<ip::SocketAddr>
{
let mut storage: libc::sockaddr_storage = unsafe { mem::init() };
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
let mut len = mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
unsafe {
let storage = &mut storage as *mut libc::sockaddr_storage;
@ -221,7 +221,7 @@ pub fn init() {
let _guard = LOCK.lock();
if !INITIALIZED {
let mut data: c::WSADATA = mem::init();
let mut data: c::WSADATA = mem::zeroed();
let ret = c::WSAStartup(0x202, // version 2.2
&mut data);
assert_eq!(ret, 0);
@ -497,7 +497,7 @@ impl TcpAcceptor {
try!(util::await(self.fd(), Some(self.deadline), util::Readable));
}
unsafe {
let mut storage: libc::sockaddr_storage = mem::init();
let mut storage: libc::sockaddr_storage = mem::zeroed();
let storagep = &mut storage as *mut libc::sockaddr_storage;
let size = mem::size_of::<libc::sockaddr_storage>();
let mut size = size as libc::socklen_t;
@ -622,7 +622,7 @@ impl rtio::RtioSocket for UdpSocket {
impl rtio::RtioUdpSocket for UdpSocket {
fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, ip::SocketAddr)> {
let fd = self.fd();
let mut storage: libc::sockaddr_storage = unsafe { mem::init() };
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
let storagep = &mut storage as *mut _ as *mut libc::sockaddr;
let mut addrlen: libc::socklen_t =
mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;

View File

@ -86,8 +86,8 @@
use libc;
use std::c_str::CString;
use std::intrinsics;
use std::io;
use std::mem;
use std::os::win32::as_utf16_p;
use std::os;
use std::ptr;
@ -345,7 +345,7 @@ impl rtio::RtioPipe for UnixStream {
}
let mut bytes_read = 0;
let mut overlapped: libc::OVERLAPPED = unsafe { intrinsics::init() };
let mut overlapped: libc::OVERLAPPED = unsafe { mem::zeroed() };
overlapped.hEvent = self.read.get_ref().handle();
// Pre-flight check to see if the reading half has been closed. This
@ -417,7 +417,7 @@ impl rtio::RtioPipe for UnixStream {
}
let mut offset = 0;
let mut overlapped: libc::OVERLAPPED = unsafe { intrinsics::init() };
let mut overlapped: libc::OVERLAPPED = unsafe { mem::zeroed() };
overlapped.hEvent = self.write.get_ref().handle();
while offset < buf.len() {
@ -633,7 +633,7 @@ impl UnixAcceptor {
// someone on the other end connects. This function can "fail" if a
// client connects after we created the pipe but before we got down
// here. Thanks windows.
let mut overlapped: libc::OVERLAPPED = unsafe { intrinsics::init() };
let mut overlapped: libc::OVERLAPPED = unsafe { mem::zeroed() };
overlapped.hEvent = self.event.handle();
if unsafe { libc::ConnectNamedPipe(handle, &mut overlapped) == 0 } {
let mut err = unsafe { libc::GetLastError() };

View File

@ -896,8 +896,8 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
// self-pipe plus the old handler registered (return value of sigaction).
fn register_sigchld() -> (libc::c_int, c::sigaction) {
unsafe {
let mut old: c::sigaction = mem::init();
let mut new: c::sigaction = mem::init();
let mut old: c::sigaction = mem::zeroed();
let mut new: c::sigaction = mem::zeroed();
new.sa_handler = sigchld_handler;
new.sa_flags = c::SA_NOCLDSTOP;
assert_eq!(c::sigaction(c::SIGCHLD, &new, &mut old), 0);
@ -916,7 +916,7 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
messages: Receiver<Req>,
(read_fd, old): (libc::c_int, c::sigaction)) {
util::set_nonblocking(input, true).unwrap();
let mut set: c::fd_set = unsafe { mem::init() };
let mut set: c::fd_set = unsafe { mem::zeroed() };
let mut tv: libc::timeval;
let mut active = Vec::<(libc::pid_t, Sender<p::ProcessExit>, u64)>::new();
let max = cmp::max(input, read_fd) + 1;

View File

@ -87,17 +87,17 @@ pub enum Req {
// returns the current time (in milliseconds)
pub fn now() -> u64 {
unsafe {
let mut now: libc::timeval = mem::init();
let mut now: libc::timeval = mem::zeroed();
assert_eq!(c::gettimeofday(&mut now, ptr::null()), 0);
return (now.tv_sec as u64) * 1000 + (now.tv_usec as u64) / 1000;
}
}
fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
let mut set: c::fd_set = unsafe { mem::init() };
let mut set: c::fd_set = unsafe { mem::zeroed() };
let mut fd = FileDesc::new(input, true);
let mut timeout: libc::timeval = unsafe { mem::init() };
let mut timeout: libc::timeval = unsafe { mem::zeroed() };
// active timers are those which are able to be selected upon (and it's a
// sorted list, and dead timers are those which have expired, but ownership

View File

@ -89,7 +89,7 @@ pub fn connect_timeout(fd: net::sock_t,
// to use select() with a timeout.
-1 if os::errno() as int == INPROGRESS as int ||
os::errno() as int == WOULDBLOCK as int => {
let mut set: c::fd_set = unsafe { mem::init() };
let mut set: c::fd_set = unsafe { mem::zeroed() };
c::fd_set(&mut set, fd);
match await(fd, &mut set, timeout_ms) {
0 => Err(timeout("connection timed out")),
@ -137,13 +137,13 @@ pub fn connect_timeout(fd: net::sock_t,
pub fn await(fd: net::sock_t, deadline: Option<u64>,
status: SocketStatus) -> IoResult<()> {
let mut set: c::fd_set = unsafe { mem::init() };
let mut set: c::fd_set = unsafe { mem::zeroed() };
c::fd_set(&mut set, fd);
let (read, write) = match status {
Readable => (&set as *_, ptr::null()),
Writable => (ptr::null(), &set as *_),
};
let mut tv: libc::timeval = unsafe { mem::init() };
let mut tv: libc::timeval = unsafe { mem::zeroed() };
match retry(|| {
let now = ::io::timer::now();

View File

@ -176,7 +176,7 @@ mod imp {
if handle as uint == libc::INVALID_HANDLE_VALUE as uint {
fail!("create file error: {}", os::last_os_error());
}
let mut overlapped: libc::OVERLAPPED = unsafe { mem::init() };
let mut overlapped: libc::OVERLAPPED = unsafe { mem::zeroed() };
let ret = unsafe {
LockFileEx(handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0,
&mut overlapped)
@ -192,7 +192,7 @@ mod imp {
impl Drop for Lock {
fn drop(&mut self) {
let mut overlapped: libc::OVERLAPPED = unsafe { mem::init() };
let mut overlapped: libc::OVERLAPPED = unsafe { mem::zeroed() };
unsafe {
UnlockFileEx(self.handle, 0, 100, 0, &mut overlapped);
libc::CloseHandle(self.handle);

View File

@ -79,7 +79,7 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
fn addr_to_sockaddr(addr: ip::SocketAddr) -> (libc::sockaddr_storage, uint) {
unsafe {
let mut storage: libc::sockaddr_storage = mem::init();
let mut storage: libc::sockaddr_storage = mem::zeroed();
let len = match addr.ip {
ip::Ipv4Addr(a, b, c, d) => {
let storage: &mut libc::sockaddr_in =
@ -133,7 +133,7 @@ fn socket_name(sk: SocketNameKind,
};
// Allocate a sockaddr_storage since we don't know if it's ipv4 or ipv6
let mut sockaddr: libc::sockaddr_storage = unsafe { mem::init() };
let mut sockaddr: libc::sockaddr_storage = unsafe { mem::zeroed() };
let mut namelen = mem::size_of::<libc::sockaddr_storage>() as c_int;
let sockaddr_p = &mut sockaddr as *mut libc::sockaddr_storage;

View File

@ -306,8 +306,10 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
// this should pass the real required alignment
let ret = exchange_malloc(size, 8) as *mut RawVec<()>;
(*ret).fill = len * mem::nonzero_size_of::<T>();
(*ret).alloc = len * mem::nonzero_size_of::<T>();
let a_size = mem::size_of::<T>();
let a_size = if a_size == 0 {1} else {a_size};
(*ret).fill = len * a_size;
(*ret).alloc = len * a_size;
// Be careful with the following loop. We want it to be optimized
// to a memcpy (or something similarly fast) when T is Copy. LLVM
@ -318,7 +320,7 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
try_finally(
&mut i, (),
|i, ()| while *i < len {
mem::move_val_init(
mem::overwrite(
&mut(*p.offset(*i as int)),
self.unsafe_ref(*i).clone());
*i += 1;

View File

@ -390,8 +390,8 @@ mod imp {
impl Mutex {
pub unsafe fn new() -> Mutex {
let m = Mutex {
lock: Unsafe::new(mem::init()),
cond: Unsafe::new(mem::init()),
lock: Unsafe::new(mem::zeroed()),
cond: Unsafe::new(mem::zeroed()),
};
pthread_mutex_init(m.lock.get(), 0 as *libc::c_void);

View File

@ -117,7 +117,7 @@ impl<T> Vec<T> {
unsafe {
let mut xs = Vec::with_capacity(length);
while xs.len < length {
mem::move_val_init(xs.as_mut_slice().unsafe_mut_ref(xs.len),
mem::overwrite(xs.as_mut_slice().unsafe_mut_ref(xs.len),
op(xs.len));
xs.len += 1;
}
@ -214,7 +214,7 @@ impl<T: Clone> Vec<T> {
unsafe {
let mut xs = Vec::with_capacity(length);
while xs.len < length {
mem::move_val_init(xs.as_mut_slice().unsafe_mut_ref(xs.len),
mem::overwrite(xs.as_mut_slice().unsafe_mut_ref(xs.len),
value.clone());
xs.len += 1;
}
@ -325,7 +325,7 @@ impl<T:Clone> Clone for Vec<T> {
let this_slice = self.as_slice();
while vector.len < len {
unsafe {
mem::move_val_init(
mem::overwrite(
vector.as_mut_slice().unsafe_mut_ref(vector.len),
this_slice.unsafe_ref(vector.len).clone());
}
@ -600,7 +600,7 @@ impl<T> Vec<T> {
unsafe {
let end = (self.ptr as *T).offset(self.len as int) as *mut T;
mem::move_val_init(&mut *end, value);
mem::overwrite(&mut *end, value);
self.len += 1;
}
}
@ -963,7 +963,7 @@ impl<T> Vec<T> {
ptr::copy_memory(p.offset(1), &*p, len - index);
// Write it in, overwriting the first copy of the `index`th
// element.
mem::move_val_init(&mut *p, element);
mem::overwrite(&mut *p, element);
}
self.set_len(len + 1);
}
@ -1542,8 +1542,10 @@ impl<T> FromVec<T> for ~[T] {
unsafe {
let ret = allocate(size, 8) as *mut RawVec<()>;
(*ret).fill = len * mem::nonzero_size_of::<T>();
(*ret).alloc = len * mem::nonzero_size_of::<T>();
let a_size = mem::size_of::<T>();
let a_size = if a_size == 0 {1} else {a_size};
(*ret).fill = len * a_size;
(*ret).alloc = len * a_size;
ptr::copy_nonoverlapping_memory(&mut (*ret).data as *mut _ as *mut u8,
vp as *u8, data_size);

View File

@ -14,6 +14,6 @@ pub fn main() {
unsafe {
let mut x: bool = false;
// this line breaks it
mem::move_val_init(&mut x, false);
mem::overwrite(&mut x, false);
}
}