diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 45fc5ff80093a..1528560a3c360 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -22,13 +22,15 @@ use borrow::{Borrow, BorrowMut}; use clone::Clone; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; -use convert::{AsRef, AsMut}; +use convert::{AsRef, AsMut, Into}; use default::Default; use fmt; use hash::{Hash, self}; use iter::IntoIterator; use marker::{Copy, Sized, Unsize}; +use mem; use option::Option; +use ptr; use slice::{Iter, IterMut, SliceExt}; /// Utility trait implemented only on arrays of fixed size @@ -220,10 +222,10 @@ array_impls! { 30 31 32 } -// The Default impls cannot be generated using the array_impls! macro because -// they require array literals. +// These impls cannot be generated using the array_impls! macro because +// they require repeating code by the size of the array. -macro_rules! array_impl_default { +macro_rules! array_impls_with_ts { {$n:expr, $t:ident $($ts:ident)*} => { #[stable(since = "1.4.0", feature = "array_default")] impl Default for [T; $n] where T: Default { @@ -231,14 +233,60 @@ macro_rules! array_impl_default { [$t::default(), $($ts::default()),*] } } - array_impl_default!{($n - 1), $($ts)*} + + #[unstable(feature = "array_tuple_conversions", issue = "0")] // FIXME: file tracking issue + impl AsRef<( $t, $($ts),* )> for [T; $n] { + fn as_ref(&self) -> &( $t, $($ts),* ) { + unsafe { &*(self as *const Self as *const _) } + } + } + + #[unstable(feature = "array_tuple_conversions", issue = "0")] // FIXME: file tracking issue + impl AsMut<( $t, $($ts),* )> for [T; $n] { + fn as_mut(&mut self) -> &mut ( $t, $($ts),* ) { + unsafe { &mut *(self as *mut Self as *mut _) } + } + } + + #[unstable(feature = "array_tuple_conversions", issue = "0")] // FIXME: file tracking issue + impl Into<( $t, $($ts),* )> for [T; $n] { + fn into(self) -> ( $t, $($ts),* ) { + let transmuted = unsafe { ptr::read(&self as *const Self as *const _) }; + mem::forget(self); + transmuted + } + } + + array_impls_with_ts!{($n - 1), $($ts)*} }; {$n:expr,} => { #[stable(since = "1.4.0", feature = "array_default")] impl Default for [T; $n] { fn default() -> [T; $n] { [] } } + + + #[unstable(feature = "array_tuple_conversions", issue = "0")] // FIXME: file tracking issue + impl AsRef<()> for [T; $n] { + fn as_ref(&self) -> &() { + unsafe { &*(self as *const Self as *const _) } + } + } + + #[unstable(feature = "array_tuple_conversions", issue = "0")] // FIXME: file tracking issue + impl AsMut<()> for [T; $n] { + fn as_mut(&mut self) -> &mut () { + unsafe { &mut *(self as *mut Self as *mut _) } + } + } + + #[unstable(feature = "array_tuple_conversions", issue = "0")] // FIXME: file tracking issue + impl Into<()> for [T; $n] { + fn into(self) -> () { + () + } + } }; } -array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T} +array_impls_with_ts!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T} diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index abaabfd129b38..69efd52b00449 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -13,9 +13,12 @@ use clone::Clone; use cmp::*; use cmp::Ordering::*; +use convert::{AsRef, AsMut, Into}; use default::Default; +use mem; use option::Option; use option::Option::Some; +use ptr; // FIXME(#19630) Remove this work-around macro_rules! e { @@ -231,3 +234,57 @@ tuple_impls! { (11) -> L } } + +macro_rules! uniform_tuple_impl { + {$n:expr, $t:ident $($ts:ident)*} => { + #[unstable(feature = "array_tuple_conversions", issue = "0")] // FIXME: file tracking issue + impl AsRef<[T; $n]> for ( $t, $($ts),* ) { + fn as_ref(&self) -> &[T; $n] { + unsafe { &*(self as *const Self as *const _) } + } + } + + #[unstable(feature = "array_tuple_conversions", issue = "0")] // FIXME: file tracking issue + impl AsMut<[T; $n]> for ( $t, $($ts),* ) { + fn as_mut(&mut self) -> &mut [T; $n] { + unsafe { &mut *(self as *mut Self as *mut _) } + } + } + + #[unstable(feature = "array_tuple_conversions", issue = "0")] // FIXME: file tracking issue + impl Into<[T; $n]> for ( $t, $($ts),* ) { + fn into(self) -> [T; $n] { + let transmuted = unsafe { ptr::read(&self as *const Self as *const _) }; + mem::forget(self); + transmuted + } + } + + uniform_tuple_impl!{($n - 1), $($ts)*} + }; + {$n:expr,} => { + #[unstable(feature = "array_tuple_conversions", issue = "0")] // FIXME: file tracking issue + impl AsRef<[T; $n]> for () { + fn as_ref(&self) -> &[T; $n] { + unsafe { &*(self as *const Self as *const _) } + } + } + + #[unstable(feature = "array_tuple_conversions", issue = "0")] // FIXME: file tracking issue + impl AsMut<[T; $n]> for () { + fn as_mut(&mut self) -> &mut [T; $n] { + unsafe { &mut *(self as *mut Self as *mut _) } + } + } + + #[unstable(feature = "array_tuple_conversions", issue = "0")] // FIXME: file tracking issue + impl Into<[T; $n]> for () { + fn into(self) -> [T; $n] { + [] + } + } + }; +} + + +uniform_tuple_impl!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T} diff --git a/src/libcoretest/array.rs b/src/libcoretest/array.rs index 6af031dee5845..8bb12a33dcc69 100644 --- a/src/libcoretest/array.rs +++ b/src/libcoretest/array.rs @@ -26,3 +26,25 @@ fn fixed_size_array() { assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_array).len(), 0); assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0); } + +#[test] +fn fixed_size_array_conversions() { + let mut empty: [u32; 0] = []; + let () = empty.into(); + let &() = empty.as_ref(); + let &mut () = empty.as_mut(); + + let mut foo: [u8; 3] = *b"foo"; + let (a, b, c) = foo.into(); + assert!((a, b, c) == (b'f', b'o', b'o')); + + let &(a, b, c) = foo.as_ref(); + assert!((a, b, c) == (b'f', b'o', b'o')); + + { + let &mut (ref mut a, b, c) = foo.as_mut(); + assert!((*a, b, c) == (b'f', b'o', b'o')); + *a = b'F'; + } + assert!(&foo == b"Foo"); +} diff --git a/src/libcoretest/tuple.rs b/src/libcoretest/tuple.rs index 4fe5e0a740bf7..d2fa242992157 100644 --- a/src/libcoretest/tuple.rs +++ b/src/libcoretest/tuple.rs @@ -66,3 +66,26 @@ fn test_show() { let s = format!("{:?}", (1, "hi", true)); assert_eq!(s, "(1, \"hi\", true)"); } + +#[test] +fn test_tuple_conversions() { + let _: [u32; 0] = ().into(); + let _: &[u32; 0] = ().as_ref(); + let _: &mut [u32; 0] = ().as_mut(); + + let mut foo = (b'f', b'o', b'o'); + assert_eq!(foo.as_ref().iter().cloned().collect::>(), vec![b'f', b'o', b'o']); + + let [a, b, c]: [u8; 3] = foo.into(); + assert!(&[a, b, c] == b"foo"); + + let &[a, b, c] = foo.as_ref(); + assert!(&[a, b, c] == b"foo"); + + { + let &mut [ref mut a, b, c] = foo.as_mut(); + assert!(&[*a, b, c] == b"foo"); + *a = b'F'; + } + assert!(foo == (b'F', b'o', b'o')); +}