From 3651470df904090981a8a3456ede0249cbdb25be Mon Sep 17 00:00:00 2001 From: CrLF0710 Date: Thu, 2 May 2019 16:58:27 +0800 Subject: [PATCH 1/5] Switch array implementation to const generics. --- src/libcore/array.rs | 418 +++++++++++++++++++++++-------------------- src/libcore/lib.rs | 1 + 2 files changed, 223 insertions(+), 196 deletions(-) diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 03094bfd33374..2a28e16b4d3ab 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -81,215 +81,241 @@ impl From for TryFromSliceError { } } -macro_rules! __impl_slice_eq1 { - ($Lhs: ty, $Rhs: ty) => { - __impl_slice_eq1! { $Lhs, $Rhs, Sized } - }; - ($Lhs: ty, $Rhs: ty, $Bound: ident) => { - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq { - #[inline] - fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] } - #[inline] - fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] } - } +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[T]> for [T; N] { + #[inline] + fn as_ref(&self) -> &[T] { + &self[..] } } -macro_rules! __impl_slice_eq2 { - ($Lhs: ty, $Rhs: ty) => { - __impl_slice_eq2! { $Lhs, $Rhs, Sized } - }; - ($Lhs: ty, $Rhs: ty, $Bound: ident) => { - __impl_slice_eq1!($Lhs, $Rhs, $Bound); - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq { - #[inline] - fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] } - #[inline] - fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] } - } +#[stable(feature = "rust1", since = "1.0.0")] +impl AsMut<[T]> for [T; N] { + #[inline] + fn as_mut(&mut self) -> &mut [T] { + &mut self[..] } } -// macro for implementing n-element array functions and operations -macro_rules! array_impls { - ($($N:expr)+) => { - $( - #[stable(feature = "rust1", since = "1.0.0")] - impl AsRef<[T]> for [T; $N] { - #[inline] - fn as_ref(&self) -> &[T] { - &self[..] - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl AsMut<[T]> for [T; $N] { - #[inline] - fn as_mut(&mut self) -> &mut [T] { - &mut self[..] - } - } - - #[stable(feature = "array_borrow", since = "1.4.0")] - impl Borrow<[T]> for [T; $N] { - fn borrow(&self) -> &[T] { - self - } - } - - #[stable(feature = "array_borrow", since = "1.4.0")] - impl BorrowMut<[T]> for [T; $N] { - fn borrow_mut(&mut self) -> &mut [T] { - self - } - } - - #[stable(feature = "try_from", since = "1.34.0")] - impl TryFrom<&[T]> for [T; $N] where T: Copy { - type Error = TryFromSliceError; - - fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> { - <&Self>::try_from(slice).map(|r| *r) - } - } - - #[stable(feature = "try_from", since = "1.34.0")] - impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] { - type Error = TryFromSliceError; - - fn try_from(slice: &[T]) -> Result<&[T; $N], TryFromSliceError> { - if slice.len() == $N { - let ptr = slice.as_ptr() as *const [T; $N]; - unsafe { Ok(&*ptr) } - } else { - Err(TryFromSliceError(())) - } - } - } - - #[stable(feature = "try_from", since = "1.34.0")] - impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] { - type Error = TryFromSliceError; - - 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]; - unsafe { Ok(&mut *ptr) } - } else { - Err(TryFromSliceError(())) - } - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for [T; $N] { - fn hash(&self, state: &mut H) { - Hash::hash(&self[..], state) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl fmt::Debug for [T; $N] { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&&self[..], f) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, T> IntoIterator for &'a [T; $N] { - type Item = &'a T; - type IntoIter = Iter<'a, T>; - - fn into_iter(self) -> Iter<'a, T> { - self.iter() - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, T> IntoIterator for &'a mut [T; $N] { - type Item = &'a mut T; - type IntoIter = IterMut<'a, T>; - - fn into_iter(self) -> IterMut<'a, T> { - self.iter_mut() - } - } - - // NOTE: some less important impls are omitted to reduce code bloat - __impl_slice_eq1! { [A; $N], [B; $N] } - __impl_slice_eq2! { [A; $N], [B] } - __impl_slice_eq2! { [A; $N], &'b [B] } - __impl_slice_eq2! { [A; $N], &'b mut [B] } - // __impl_slice_eq2! { [A; $N], &'b [B; $N] } - // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] } - - #[stable(feature = "rust1", since = "1.0.0")] - impl Eq for [T; $N] { } - - #[stable(feature = "rust1", since = "1.0.0")] - impl PartialOrd for [T; $N] { - #[inline] - fn partial_cmp(&self, other: &[T; $N]) -> Option { - PartialOrd::partial_cmp(&&self[..], &&other[..]) - } - #[inline] - fn lt(&self, other: &[T; $N]) -> bool { - PartialOrd::lt(&&self[..], &&other[..]) - } - #[inline] - fn le(&self, other: &[T; $N]) -> bool { - PartialOrd::le(&&self[..], &&other[..]) - } - #[inline] - fn ge(&self, other: &[T; $N]) -> bool { - PartialOrd::ge(&&self[..], &&other[..]) - } - #[inline] - fn gt(&self, other: &[T; $N]) -> bool { - PartialOrd::gt(&&self[..], &&other[..]) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl Ord for [T; $N] { - #[inline] - fn cmp(&self, other: &[T; $N]) -> Ordering { - Ord::cmp(&&self[..], &&other[..]) - } - } - )+ +#[stable(feature = "array_borrow", since = "1.4.0")] +impl Borrow<[T]> for [T; N] { + fn borrow(&self) -> &[T] { + self } } -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 +#[stable(feature = "array_borrow", since = "1.4.0")] +impl BorrowMut<[T]> for [T; N] { + fn borrow_mut(&mut self) -> &mut [T] { + self + } } -// The Default impls cannot be generated using the array_impls! macro because -// they require array literals. +#[stable(feature = "try_from", since = "1.34.0")] +impl TryFrom<&[T]> for [T; N] where T: Copy { + type Error = TryFromSliceError; + + fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> { + <&Self>::try_from(slice).map(|r| *r) + } +} -macro_rules! array_impl_default { - {$n:expr, $t:ident $($ts:ident)*} => { - #[stable(since = "1.4.0", feature = "array_default")] - impl Default for [T; $n] where T: Default { - fn default() -> [T; $n] { - [$t::default(), $($ts::default()),*] - } +#[stable(feature = "try_from", since = "1.34.0")] +impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] { + type Error = TryFromSliceError; + + fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> { + if slice.len() == N { + let ptr = slice.as_ptr() as *const [T; N]; + unsafe { Ok(&*ptr) } + } else { + Err(TryFromSliceError(())) } - array_impl_default!{($n - 1), $($ts)*} - }; - {$n:expr,} => { - #[stable(since = "1.4.0", feature = "array_default")] - impl Default for [T; $n] { - fn default() -> [T; $n] { [] } + } +} + +#[stable(feature = "try_from", since = "1.34.0")] +impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] { + type Error = TryFromSliceError; + + 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]; + unsafe { Ok(&mut *ptr) } + } else { + Err(TryFromSliceError(())) } - }; + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for [T; N] { + fn hash(&self, state: &mut H) { + Hash::hash(&self[..], state) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for [T; N] { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&&self[..], f) + } } -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} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, const N: usize> IntoIterator for &'a [T; N] { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N] { + type Item = &'a mut T; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, A: Sized, B, const N: usize> PartialEq<[B; N]> for [A; N] where A: PartialEq { + #[inline] + fn eq(&self, other: &[B; N]) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &[B; N]) -> bool { self[..] != other[..] } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, A: Sized, B, const N: usize> PartialEq<[B]> for [A; N] where A: PartialEq { + #[inline] + fn eq(&self, other: &[B]) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &[B]) -> bool { self[..] != other[..] } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, A: Sized, B, const N: usize> PartialEq<[A; N]> for [B] where B: PartialEq { + #[inline] + fn eq(&self, other: &[A; N]) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &[A; N]) -> bool { self[..] != other[..] } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, A: Sized, B, const N: usize> PartialEq<&'b [B]> for [A; N] where A: PartialEq { + #[inline] + fn eq(&self, other: &&'b [B]) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &&'b [B]) -> bool { self[..] != other[..] } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, A: Sized, B, const N: usize> PartialEq<[A; N]> for &'b [B] where B: PartialEq { + #[inline] + fn eq(&self, other: &[A; N]) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &[A; N]) -> bool { self[..] != other[..] } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, A: Sized, B, const N: usize> PartialEq<&'b mut [B]> for [A; N] where A: PartialEq { + #[inline] + fn eq(&self, other: &&'b mut [B]) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &&'b mut [B]) -> bool { self[..] != other[..] } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, A: Sized, B, const N: usize> PartialEq<[A; N]> for &'b mut [B] where B: PartialEq { + #[inline] + fn eq(&self, other: &[A; N]) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &[A; N]) -> bool { self[..] != other[..] } +} + +// NOTE: some less important impls are omitted to reduce code bloat +// after const generics came true in 2019, we didn't immediate add these back. + +/* +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, A: Sized, B, const N: usize> PartialEq<&'b [B; N]> for [A; N] where A: PartialEq { + #[inline] + fn eq(&self, other: &&'b [B; N]) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &&'b [B; N]) -> bool { self[..] != other[..] } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, A: Sized, B, const N: usize> PartialEq<[A; N]> for &'b [B; N] where B: PartialEq { + #[inline] + fn eq(&self, other: &[A; N]) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &[A; N]) -> bool { self[..] != other[..] } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, A: Sized, B, const N: usize> PartialEq<&'b mut [B; N]> for [A; N] + where A: PartialEq { + #[inline] + fn eq(&self, other: &&'b mut [B; N]) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &&'b mut [B; N]) -> bool { self[..] != other[..] } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, A: Sized, B, const N: usize> PartialEq<[A; N]> for &'b mut [B; N] + where B: PartialEq { + #[inline] + fn eq(&self, other: &[A; N]) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &[A; N]) -> bool { self[..] != other[..] } +} + +*/ + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for [T; N] { } + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for [T; N] { + #[inline] + fn partial_cmp(&self, other: &[T; N]) -> Option { + PartialOrd::partial_cmp(&&self[..], &&other[..]) + } + #[inline] + fn lt(&self, other: &[T; N]) -> bool { + PartialOrd::lt(&&self[..], &&other[..]) + } + #[inline] + fn le(&self, other: &[T; N]) -> bool { + PartialOrd::le(&&self[..], &&other[..]) + } + #[inline] + fn ge(&self, other: &[T; N]) -> bool { + PartialOrd::ge(&&self[..], &&other[..]) + } + #[inline] + fn gt(&self, other: &[T; N]) -> bool { + PartialOrd::gt(&&self[..], &&other[..]) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for [T; N] { + #[inline] + fn cmp(&self, other: &[T; N]) -> Ordering { + Ord::cmp(&&self[..], &&other[..]) + } +} + +#[stable(since = "1.4.0", feature = "array_default")] +impl Default for [T; N] where T: Default { + fn default() -> [T; N] { + [T::default(); N] + } +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 030f4f1d12cc8..3a5b4f1a2464c 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -75,6 +75,7 @@ #![feature(concat_idents)] #![feature(const_fn)] #![feature(const_fn_union)] +#![feature(const_generics)] #![feature(doc_cfg)] #![feature(doc_spotlight)] #![feature(extern_types)] From e9cbd502270ee954751176809aac54cc6266f009 Mon Sep 17 00:00:00 2001 From: CrLF0710 Date: Sat, 4 May 2019 23:12:46 +0800 Subject: [PATCH 2/5] Add array_stage0.rs for bootstrapping. --- src/libcore/array_stage0.rs | 295 ++++++++++++++++++++++++++++++++++++ src/libcore/lib.rs | 1 + 2 files changed, 296 insertions(+) create mode 100644 src/libcore/array_stage0.rs diff --git a/src/libcore/array_stage0.rs b/src/libcore/array_stage0.rs new file mode 100644 index 0000000000000..03094bfd33374 --- /dev/null +++ b/src/libcore/array_stage0.rs @@ -0,0 +1,295 @@ +//! Implementations of things like `Eq` for fixed-length arrays +//! up to a certain length. Eventually we should able to generalize +//! to all lengths. +//! +//! *[See also the array primitive type](../../std/primitive.array.html).* + +#![stable(feature = "core_array", since = "1.36.0")] + +use crate::borrow::{Borrow, BorrowMut}; +use crate::cmp::Ordering; +use crate::convert::{Infallible, TryFrom}; +use crate::fmt; +use crate::hash::{Hash, self}; +use crate::marker::Unsize; +use crate::slice::{Iter, IterMut}; + +/// Utility trait implemented only on arrays of fixed size +/// +/// This trait can be used to implement other traits on fixed-size arrays +/// without causing much metadata bloat. +/// +/// The trait is marked unsafe in order to restrict implementors to fixed-size +/// arrays. User of this trait can assume that implementors have the exact +/// layout in memory of a fixed size array (for example, for unsafe +/// initialization). +/// +/// Note that the traits AsRef and AsMut provide similar methods for types that +/// may not be fixed-size arrays. Implementors should prefer those traits +/// instead. +#[unstable(feature = "fixed_size_array", issue = "27778")] +pub unsafe trait FixedSizeArray { + /// Converts the array to immutable slice + #[unstable(feature = "fixed_size_array", issue = "27778")] + fn as_slice(&self) -> &[T]; + /// Converts the array to mutable slice + #[unstable(feature = "fixed_size_array", issue = "27778")] + fn as_mut_slice(&mut self) -> &mut [T]; +} + +#[unstable(feature = "fixed_size_array", issue = "27778")] +unsafe impl> FixedSizeArray for A { + #[inline] + fn as_slice(&self) -> &[T] { + self + } + #[inline] + fn as_mut_slice(&mut self) -> &mut [T] { + self + } +} + +/// The error type returned when a conversion from a slice to an array fails. +#[stable(feature = "try_from", since = "1.34.0")] +#[derive(Debug, Copy, Clone)] +pub struct TryFromSliceError(()); + +#[stable(feature = "core_array", since = "1.36.0")] +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 slice to array" + } +} + +#[stable(feature = "try_from_slice_error", since = "1.36.0")] +impl From for TryFromSliceError { + fn from(x: Infallible) -> TryFromSliceError { + match x {} + } +} + +macro_rules! __impl_slice_eq1 { + ($Lhs: ty, $Rhs: ty) => { + __impl_slice_eq1! { $Lhs, $Rhs, Sized } + }; + ($Lhs: ty, $Rhs: ty, $Bound: ident) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq { + #[inline] + fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] } + } + } +} + +macro_rules! __impl_slice_eq2 { + ($Lhs: ty, $Rhs: ty) => { + __impl_slice_eq2! { $Lhs, $Rhs, Sized } + }; + ($Lhs: ty, $Rhs: ty, $Bound: ident) => { + __impl_slice_eq1!($Lhs, $Rhs, $Bound); + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq { + #[inline] + fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] } + } + } +} + +// macro for implementing n-element array functions and operations +macro_rules! array_impls { + ($($N:expr)+) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRef<[T]> for [T; $N] { + #[inline] + fn as_ref(&self) -> &[T] { + &self[..] + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl AsMut<[T]> for [T; $N] { + #[inline] + fn as_mut(&mut self) -> &mut [T] { + &mut self[..] + } + } + + #[stable(feature = "array_borrow", since = "1.4.0")] + impl Borrow<[T]> for [T; $N] { + fn borrow(&self) -> &[T] { + self + } + } + + #[stable(feature = "array_borrow", since = "1.4.0")] + impl BorrowMut<[T]> for [T; $N] { + fn borrow_mut(&mut self) -> &mut [T] { + self + } + } + + #[stable(feature = "try_from", since = "1.34.0")] + impl TryFrom<&[T]> for [T; $N] where T: Copy { + type Error = TryFromSliceError; + + fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> { + <&Self>::try_from(slice).map(|r| *r) + } + } + + #[stable(feature = "try_from", since = "1.34.0")] + impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] { + type Error = TryFromSliceError; + + fn try_from(slice: &[T]) -> Result<&[T; $N], TryFromSliceError> { + if slice.len() == $N { + let ptr = slice.as_ptr() as *const [T; $N]; + unsafe { Ok(&*ptr) } + } else { + Err(TryFromSliceError(())) + } + } + } + + #[stable(feature = "try_from", since = "1.34.0")] + impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] { + type Error = TryFromSliceError; + + 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]; + unsafe { Ok(&mut *ptr) } + } else { + Err(TryFromSliceError(())) + } + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for [T; $N] { + fn hash(&self, state: &mut H) { + Hash::hash(&self[..], state) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::Debug for [T; $N] { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&&self[..], f) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, T> IntoIterator for &'a [T; $N] { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, T> IntoIterator for &'a mut [T; $N] { + type Item = &'a mut T; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } + } + + // NOTE: some less important impls are omitted to reduce code bloat + __impl_slice_eq1! { [A; $N], [B; $N] } + __impl_slice_eq2! { [A; $N], [B] } + __impl_slice_eq2! { [A; $N], &'b [B] } + __impl_slice_eq2! { [A; $N], &'b mut [B] } + // __impl_slice_eq2! { [A; $N], &'b [B; $N] } + // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Eq for [T; $N] { } + + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialOrd for [T; $N] { + #[inline] + fn partial_cmp(&self, other: &[T; $N]) -> Option { + PartialOrd::partial_cmp(&&self[..], &&other[..]) + } + #[inline] + fn lt(&self, other: &[T; $N]) -> bool { + PartialOrd::lt(&&self[..], &&other[..]) + } + #[inline] + fn le(&self, other: &[T; $N]) -> bool { + PartialOrd::le(&&self[..], &&other[..]) + } + #[inline] + fn ge(&self, other: &[T; $N]) -> bool { + PartialOrd::ge(&&self[..], &&other[..]) + } + #[inline] + fn gt(&self, other: &[T; $N]) -> bool { + PartialOrd::gt(&&self[..], &&other[..]) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Ord for [T; $N] { + #[inline] + fn cmp(&self, other: &[T; $N]) -> Ordering { + Ord::cmp(&&self[..], &&other[..]) + } + } + )+ + } +} + +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 +} + +// The Default impls cannot be generated using the array_impls! macro because +// they require array literals. + +macro_rules! array_impl_default { + {$n:expr, $t:ident $($ts:ident)*} => { + #[stable(since = "1.4.0", feature = "array_default")] + impl Default for [T; $n] where T: Default { + fn default() -> [T; $n] { + [$t::default(), $($ts::default()),*] + } + } + array_impl_default!{($n - 1), $($ts)*} + }; + {$n:expr,} => { + #[stable(since = "1.4.0", feature = "array_default")] + impl Default for [T; $n] { + fn default() -> [T; $n] { [] } + } + }; +} + +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} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 3a5b4f1a2464c..402beae3bea25 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -190,6 +190,7 @@ pub mod borrow; /* Core types and methods on primitives */ pub mod any; +#[cfg_attr(stage0, path = "array_stage0.rs")] pub mod array; pub mod ascii; pub mod sync; From 1975a3dbdef0878d3138814e6e8334b3745c5d93 Mon Sep 17 00:00:00 2001 From: CrLF0710 Date: Sun, 5 May 2019 11:53:44 +0800 Subject: [PATCH 3/5] Temporarily revert Default implementation back to old macro-based one. --- src/libcore/array.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 2a28e16b4d3ab..36b43784c8492 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -313,9 +313,42 @@ impl Ord for [T; N] { } } +/* + #[stable(since = "1.4.0", feature = "array_default")] impl Default for [T; N] where T: Default { fn default() -> [T; N] { [T::default(); N] } } + +// FIXME: This doesn't work now because it's using negative bound. + +#[stable(since = "1.4.0", feature = "array_default")] +impl Default for [T; 0] where T: !Default { + fn default() -> [T; 0] { + [] + } +} + +*/ + +macro_rules! array_impl_default { + {$n:expr, $t:ident $($ts:ident)*} => { + #[stable(since = "1.4.0", feature = "array_default")] + impl Default for [T; $n] where T: Default { + fn default() -> [T; $n] { + [$t::default(), $($ts::default()),*] + } + } + array_impl_default!{($n - 1), $($ts)*} + }; + {$n:expr,} => { + #[stable(since = "1.4.0", feature = "array_default")] + impl Default for [T; $n] { + fn default() -> [T; $n] { [] } + } + }; +} + +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} From 6485b6b2283080522bf952339e67c2aea38d02c2 Mon Sep 17 00:00:00 2001 From: CrLF0710 Date: Fri, 31 May 2019 18:06:46 +0800 Subject: [PATCH 4/5] Change expected output of one test case. --- src/test/ui/const-generics/broken-mir-2.rs | 4 +++- src/test/ui/const-generics/broken-mir-2.stderr | 15 +-------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/test/ui/const-generics/broken-mir-2.rs b/src/test/ui/const-generics/broken-mir-2.rs index fb9a63ea738fa..262eb9e88404e 100644 --- a/src/test/ui/const-generics/broken-mir-2.rs +++ b/src/test/ui/const-generics/broken-mir-2.rs @@ -1,9 +1,11 @@ +// run-pass + #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash use std::fmt::Debug; #[derive(Debug)] -struct S([T; N]); //~ ERROR `[T; _]` doesn't implement `std::fmt::Debug` +struct S([T; N]); fn main() {} diff --git a/src/test/ui/const-generics/broken-mir-2.stderr b/src/test/ui/const-generics/broken-mir-2.stderr index fb9b88bde0a25..a2a17a5ff0232 100644 --- a/src/test/ui/const-generics/broken-mir-2.stderr +++ b/src/test/ui/const-generics/broken-mir-2.stderr @@ -1,19 +1,6 @@ warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/broken-mir-2.rs:1:12 + --> $DIR/broken-mir-2.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ -error[E0277]: `[T; _]` doesn't implement `std::fmt::Debug` - --> $DIR/broken-mir-2.rs:7:36 - | -LL | struct S([T; N]); - | ^^^^^^ `[T; _]` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` - | - = help: the trait `std::fmt::Debug` is not implemented for `[T; _]` - = note: required because of the requirements on the impl of `std::fmt::Debug` for `&[T; _]` - = note: required for the cast to the object type `dyn std::fmt::Debug` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. From 0138ad4b3312e84e5aac13482327fe09b1ee150c Mon Sep 17 00:00:00 2001 From: CrLF0710 Date: Sun, 2 Jun 2019 10:37:09 +0800 Subject: [PATCH 5/5] Add two tests for const generics array impls. --- .../const-generics-array-impls-1.rs | 133 ++++++++++++++++++ .../const-generics-array-impls-2.rs | 111 +++++++++++++++ .../const-generics-array-impls-2.stderr | 6 + 3 files changed, 250 insertions(+) create mode 100644 src/test/ui/const-generics/const-generics-array-impls-1.rs create mode 100644 src/test/ui/const-generics/const-generics-array-impls-2.rs create mode 100644 src/test/ui/const-generics/const-generics-array-impls-2.stderr diff --git a/src/test/ui/const-generics/const-generics-array-impls-1.rs b/src/test/ui/const-generics/const-generics-array-impls-1.rs new file mode 100644 index 0000000000000..cde63fb5b712e --- /dev/null +++ b/src/test/ui/const-generics/const-generics-array-impls-1.rs @@ -0,0 +1,133 @@ +// run-pass + +#![allow(dead_code)] +#![allow(unused_variables)] + +use std::borrow::Borrow; +use std::borrow::BorrowMut; +use std::collections::BTreeSet; +use std::collections::HashSet; +use std::convert::TryFrom; + +#[derive(Copy, Clone, Debug)] +struct MyBool(bool); + +impl PartialEq for MyBool { + fn eq(&self, other: &bool) -> bool { + self.0 == *other + } +} + +impl PartialEq for bool { + fn eq(&self, other: &MyBool) -> bool { + *self == other.0 + } +} + +macro_rules! boolean_check_with_len { + ($LEN:expr) => {{ + let a = [true; $LEN]; + let mut b = [true; $LEN]; + let mut c = [false; $LEN]; + let mut d = [false; $LEN]; + + // PartialEq, Debug + assert_eq!(a, b); + if $LEN > 0 { + assert_ne!(a, c); + } else { + assert_eq!(a, c); + } + + // AsRef + let a_slice: &[bool] = a.as_ref(); + + // AsMut + let b_slice: &mut [bool] = b.as_mut(); + + // Borrow + let c_slice: &[bool] = c.borrow(); + + // BorrowMut + let d_slice: &mut [bool] = d.borrow_mut(); + + // TryFrom + let e_ref: &[bool; $LEN] = TryFrom::try_from(a_slice).unwrap(); + + // TryFrom#2 + let f: [bool; $LEN] = TryFrom::try_from(a_slice).unwrap(); + + // TryFrom#3 + let g_mut: &mut [bool; $LEN] = TryFrom::try_from(b_slice).unwrap(); + + // PartialEq, Eq, Hash + let h: HashSet<[bool; $LEN]> = HashSet::new(); + + // PartialEq, Eq, PartialOrd, Ord + let i: BTreeSet<[bool; $LEN]> = BTreeSet::new(); + + // IntoIterator#1 + for j in &a { + let _ = j; + } + + // IntoIterator#2 + for k in &mut c { + let _ = k; + } + + let l = [MyBool(true); $LEN]; + let l_slice: &[MyBool] = l.as_ref(); + + let mut m = [MyBool(false); $LEN]; + let m_slice: &mut [MyBool] = m.as_mut(); + + // PartialEq + assert_eq!(a, l); + assert_eq!(a, *l_slice); + assert_eq!(a_slice, l); + assert_eq!(a, l_slice); + assert_eq!(c, m_slice); + assert_eq!(m_slice, c); + + // The currently omitted impls + /* + assert_eq!(a, &l); + assert_eq!(&l, a); + assert_eq!(a, &mut l); + assert_eq!(&mut l, a); + */ + + /* Default is not using const generics now */ + /* + assert_eq!(c, Default::default()) + */ + }}; +} + +fn check_boolean_array_less_than_32() { + boolean_check_with_len!(0); + boolean_check_with_len!(1); + boolean_check_with_len!(2); + boolean_check_with_len!(4); + boolean_check_with_len!(8); + boolean_check_with_len!(16); + boolean_check_with_len!(31); + boolean_check_with_len!(32); +} + +fn check_boolean_array_more_than_32() { + boolean_check_with_len!(33); + boolean_check_with_len!(64); + boolean_check_with_len!(128); + boolean_check_with_len!(256); + boolean_check_with_len!(512); + boolean_check_with_len!(1024); +} + +fn main() { + // regression check + check_boolean_array_less_than_32(); + // newly added + check_boolean_array_more_than_32(); +} diff --git a/src/test/ui/const-generics/const-generics-array-impls-2.rs b/src/test/ui/const-generics/const-generics-array-impls-2.rs new file mode 100644 index 0000000000000..3f56eecde5b44 --- /dev/null +++ b/src/test/ui/const-generics/const-generics-array-impls-2.rs @@ -0,0 +1,111 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +#![allow(dead_code)] +#![allow(unused_variables)] + +use std::borrow::Borrow; +use std::borrow::BorrowMut; +use std::collections::BTreeSet; +use std::collections::HashSet; +use std::convert::TryFrom; + +#[derive(Copy, Clone, Debug)] +struct MyBool(bool); + +impl PartialEq for MyBool { + fn eq(&self, other: &bool) -> bool { + self.0 == *other + } +} + +impl PartialEq for bool { + fn eq(&self, other: &MyBool) -> bool { + *self == other.0 + } +} + +fn check_boolean_array_with_const_generics() { + let a = [true; LEN]; + let mut b = [true; LEN]; + let mut c = [false; LEN]; + let mut d = [false; LEN]; + + // PartialEq, Debug + assert_eq!(a, b); + if LEN > 0 { + assert_ne!(a, c); + } else { + assert_eq!(a, c); + } + + // AsRef + let a_slice: &[bool] = a.as_ref(); + + // AsMut + let b_slice: &mut [bool] = b.as_mut(); + + // Borrow + let c_slice: &[bool] = c.borrow(); + + // BorrowMut + let d_slice: &mut [bool] = d.borrow_mut(); + + // TryFrom + let e_ref: &[bool; LEN] = TryFrom::try_from(a_slice).unwrap(); + + // TryFrom#2 + let f: [bool; LEN] = TryFrom::try_from(a_slice).unwrap(); + + // TryFrom#3 + let g_mut: &mut [bool; LEN] = TryFrom::try_from(b_slice).unwrap(); + + // PartialEq, Eq, Hash + let h: HashSet<[bool; LEN]> = HashSet::new(); + + // PartialEq, Eq, PartialOrd, Ord + let i: BTreeSet<[bool; LEN]> = BTreeSet::new(); + + // IntoIterator#1 + for j in &a { + let _ = j; + } + + // IntoIterator#2 + for k in &mut c { + let _ = k; + } + + let l = [MyBool(true); LEN]; + let l_slice: &[MyBool] = l.as_ref(); + + let mut m = [MyBool(false); LEN]; + let m_slice: &mut [MyBool] = m.as_mut(); + + // PartialEq + assert_eq!(a, l); + assert_eq!(a, *l_slice); + assert_eq!(a_slice, l); + assert_eq!(a, l_slice); + assert_eq!(c, m_slice); + assert_eq!(m_slice, c); + + // The currently omitted impls + /* + assert_eq!(a, &l); + assert_eq!(&l, a); + assert_eq!(a, &mut l); + assert_eq!(&mut l, a); + */ + + /* Default is not using const generics now */ + /* + assert_eq!(c, Default::default()) + */ +} + +fn main() { + check_boolean_array_with_const_generics::<{ 30 }>(); + check_boolean_array_with_const_generics::<{ 40 }>(); +} diff --git a/src/test/ui/const-generics/const-generics-array-impls-2.stderr b/src/test/ui/const-generics/const-generics-array-impls-2.stderr new file mode 100644 index 0000000000000..fbf5d53754164 --- /dev/null +++ b/src/test/ui/const-generics/const-generics-array-impls-2.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/const-types.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ +