From 22c581b2a59838bb2f917ff482ce5f7e8fbd548b Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Sat, 6 Jan 2018 19:39:01 -0500 Subject: [PATCH 1/8] Implement TryFrom for array box types This commit serves to provide the same benefits as PR #44764 except for boxes that refer to owned arrays allocated in the heap. --- src/liballoc/boxed.rs | 61 +++++++++++++++++++++++++++++++++++++++++++ src/libstd/error.rs | 7 +++++ 2 files changed, 68 insertions(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 6f125cdba8190..db0f55721294a 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -61,6 +61,7 @@ use raw_vec::RawVec; use core::any::Any; use core::borrow; use core::cmp::Ordering; +use core::convert::TryFrom; use core::fmt; use core::hash::{self, Hash, Hasher}; use core::iter::FusedIterator; @@ -623,6 +624,66 @@ impl From> for Box<[u8]> { } } +/// The error type returned when a conversion from a boxed slice to a boxed +/// array fails. +#[unstable(feature = "try_from", issue = "33417")] +#[derive(Debug, Copy, Clone)] +pub struct TryFromSliceError(Box<[T]>); + +impl fmt::Display for TryFromSliceError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.__description(), f) + } +} + +impl TryFromSliceError { + #[unstable(feature = "array_error_internals", + reason = "available through Error trait and this method should not \ + be exposed publicly", + issue = "0")] + #[inline] + #[doc(hidden)] + pub fn __description(&self) -> &str { + "could not convert boxed slice to boxed array" + } + + /// Returns the boxed slice that was attempted to convert to a boxed array. + /// + /// This method is meant to avoid allocation. It will consume the error, + /// moving out the boxed slice, so that a copy of the slice does not need to + /// be made. + #[inline] + pub fn into_boxed_slice(self) -> Box<[T]> { + self.0 + } +} + +macro_rules! array_impls { + ($($N:expr)+) => { + #[unstable(feature = "try_from", issue = "33417")] + impl TryFrom> for Box<[T; $N]> { + type Error = TryFromSliceError; + + fn try_from(slice: Box<[T]>) -> Result, TryFromSliceError> { + if slice.len() == $N { + let ptr = Box::into_raw(slice) as *mut [T; $N]; + unsafe { Ok(Box::from_raw(ptr)) } + } else { + Err(TryFromSliceError(slice)) + } + } + } + } +} + +array_impls! { + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 +} + impl Box { #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/error.rs b/src/libstd/error.rs index eb5022ad5776a..28e833bb47fb0 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -290,6 +290,13 @@ impl Error for array::TryFromSliceError { } } +#[unstable(feature = "try_from", issue = "33417")] +impl Error for boxed::TryFromSliceError { + fn description(&self) -> &str { + self.__description() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Error for num::ParseFloatError { fn description(&self) -> &str { From b25334a61eaaf12dbb2dcde7479abb6969933ae7 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Sun, 7 Jan 2018 14:58:26 -0500 Subject: [PATCH 2/8] Add missing repetition for array_impls! macro item --- src/liballoc/boxed.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index db0f55721294a..2beb3f6ce4bd7 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -661,19 +661,21 @@ impl TryFromSliceError { macro_rules! array_impls { ($($N:expr)+) => { - #[unstable(feature = "try_from", issue = "33417")] - impl TryFrom> for Box<[T; $N]> { - type Error = TryFromSliceError; - - fn try_from(slice: Box<[T]>) -> Result, TryFromSliceError> { - if slice.len() == $N { - let ptr = Box::into_raw(slice) as *mut [T; $N]; - unsafe { Ok(Box::from_raw(ptr)) } - } else { - Err(TryFromSliceError(slice)) + $( + #[unstable(feature = "try_from", issue = "33417")] + impl TryFrom> for Box<[T; $N]> { + type Error = TryFromSliceError; + + fn try_from(slice: Box<[T]>) -> Result, TryFromSliceError> { + if slice.len() == $N { + let ptr = Box::into_raw(slice) as *mut [T; $N]; + unsafe { Ok(Box::from_raw(ptr)) } + } else { + Err(TryFromSliceError(slice)) + } } } - } + )+ } } From 8cb0b3e6f7b04e89a54ee27156cc84d331324b59 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Sun, 7 Jan 2018 15:00:12 -0500 Subject: [PATCH 3/8] Inline all TryFrom<[T]> for [T; N] instances The functions are very short and there may be relatively unreasonable calling overhead if they're not inlined. --- src/liballoc/boxed.rs | 1 + src/libcore/array.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 2beb3f6ce4bd7..7808ec5999fe7 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -666,6 +666,7 @@ macro_rules! array_impls { impl TryFrom> for Box<[T; $N]> { type Error = TryFromSliceError; + #[inline] fn try_from(slice: Box<[T]>) -> Result, TryFromSliceError> { if slice.len() == $N { let ptr = Box::into_raw(slice) as *mut [T; $N]; diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 3d24f8902bd83..77087b55bcd90 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -152,6 +152,7 @@ macro_rules! array_impls { impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] { type Error = TryFromSliceError; + #[inline] fn try_from(slice: &[T]) -> Result<&[T; $N], TryFromSliceError> { if slice.len() == $N { let ptr = slice.as_ptr() as *const [T; $N]; @@ -166,6 +167,7 @@ macro_rules! array_impls { impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] { type Error = TryFromSliceError; + #[inline] fn try_from(slice: &mut [T]) -> Result<&mut [T; $N], TryFromSliceError> { if slice.len() == $N { let ptr = slice.as_mut_ptr() as *mut [T; $N]; From 45d68395260aa833401398e030ee0aa4d0055269 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Sun, 7 Jan 2018 17:26:17 -0500 Subject: [PATCH 4/8] Add try_from feature to liballoc --- src/liballoc/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 3cc3ea467966b..903cd73703b50 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -118,6 +118,7 @@ #![feature(staged_api)] #![feature(str_internals)] #![feature(trusted_len)] +#![feature(try_from)] #![feature(unboxed_closures)] #![feature(unicode)] #![feature(unique)] From da9a570fb2208fd8b89c5a7c36a3f5c285c98624 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Sun, 7 Jan 2018 17:40:55 -0500 Subject: [PATCH 5/8] Remove Copy derive from boxed::TryFromSliceError --- src/liballoc/boxed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 7808ec5999fe7..b953757e1d960 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -627,7 +627,7 @@ impl From> for Box<[u8]> { /// The error type returned when a conversion from a boxed slice to a boxed /// array fails. #[unstable(feature = "try_from", issue = "33417")] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Clone)] pub struct TryFromSliceError(Box<[T]>); impl fmt::Display for TryFromSliceError { From 909e35fe3f05b78b02ba7e7302b5344c613a6b38 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Sun, 7 Jan 2018 18:18:06 -0500 Subject: [PATCH 6/8] Add stability attribute to TryFromSliceError nodes --- src/liballoc/boxed.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index b953757e1d960..4fc4deb8d31dd 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -630,6 +630,7 @@ impl From> for Box<[u8]> { #[derive(Debug, Clone)] pub struct TryFromSliceError(Box<[T]>); +#[unstable(feature = "try_from", issue = "33417")] impl fmt::Display for TryFromSliceError { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -653,6 +654,7 @@ impl TryFromSliceError { /// This method is meant to avoid allocation. It will consume the error, /// moving out the boxed slice, so that a copy of the slice does not need to /// be made. + #[unstable(feature = "try_from", issue = "33417")] #[inline] pub fn into_boxed_slice(self) -> Box<[T]> { self.0 From aba11fd686d89523c53516c811b2bb99925d4df4 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Sun, 7 Jan 2018 18:43:30 -0500 Subject: [PATCH 7/8] Import 'boxed' module to use TryFromSliceError --- src/libstd/error.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 28e833bb47fb0..a55807766c9e1 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -54,6 +54,7 @@ use alloc::allocator; use any::TypeId; use borrow::Cow; +use boxed; use cell; use char; use convert; From 544fb2ac51fc0854e57f2540cdff342a72a7d660 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Sun, 7 Jan 2018 20:14:13 -0500 Subject: [PATCH 8/8] Manually implement Debug for TryFromSliceError --- src/liballoc/boxed.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 4fc4deb8d31dd..c8540c53d4ff9 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -627,9 +627,17 @@ impl From> for Box<[u8]> { /// The error type returned when a conversion from a boxed slice to a boxed /// array fails. #[unstable(feature = "try_from", issue = "33417")] -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct TryFromSliceError(Box<[T]>); +#[unstable(feature = "try_from", issue = "33417")] +impl fmt::Debug for TryFromSliceError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("TryFromSliceError").finish() + } +} + #[unstable(feature = "try_from", issue = "33417")] impl fmt::Display for TryFromSliceError { #[inline]