From c1663078cb56b4ae8d8ed699a945cb8e71758b09 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Fri, 13 Mar 2020 19:36:00 +0100 Subject: [PATCH 01/16] Add `FromIterator` impl `for [T; N]` --- library/core/src/array/mod.rs | 61 +++++++++++++++++++++++++++++++ library/std/src/primitive_docs.rs | 1 + 2 files changed, 62 insertions(+) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 966272ca11549..8f0385cf33d1b 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -11,7 +11,9 @@ use crate::cmp::Ordering; use crate::convert::{Infallible, TryFrom}; use crate::fmt; use crate::hash::{self, Hash}; +use crate::iter::{FromIterator, ExactSizeIterator}; use crate::marker::Unsize; +use crate::mem::MaybeUninit; use crate::slice::{Iter, IterMut}; mod iter; @@ -188,6 +190,65 @@ impl fmt::Debug for [T; N] { } } +#[stable(feature = "array_from_iter_impl", since = "1.44.0")] +impl FromIterator for [T; N] +where + [T; N]: LengthAtMost32, +{ + #[inline] + fn from_iter>(iter: I) -> Self { + >::from_iter(iter.into_iter()) + } +} + +// Specialization trait used for array::from_iter +trait ArrayFromIter { + fn from_iter(iter: I) -> Self; +} + +impl ArrayFromIter for [T; N] + where I: Iterator, + [T; N]: LengthAtMost32, +{ + default fn from_iter(mut iter: I) -> Self { + let mut array: [MaybeUninit; N] = MaybeUninit::uninit_array(); + + for p in array.iter_mut() { + p.write(iter.next().expect("Iterator is to short")); + } + + // FIXME: actually use `mem::transmute` here, once it + // works with const generics: + // `mem::transmute::<[T; N], [MaybeUninit; N]>(array)` + unsafe { + crate::ptr::read(&array as *const [MaybeUninit; N] as *const [T; N]) + } + } +} + +// Early panic if we know the size of the iterator +impl ArrayFromIter for [T; N] + where I: ExactSizeIterator, + [T; N]: LengthAtMost32, +{ + default fn from_iter(iter: I) -> Self { + assert_eq!(N, iter.len(), "Iterator is not the same length as the array"); + + let mut array: [MaybeUninit; N] = MaybeUninit::uninit_array(); + + for (p, v) in array.iter_mut().zip(iter) { + p.write(v); + } + + // FIXME: actually use `mem::transmute` here, once it + // works with const generics: + // `mem::transmute::<[T; N], [MaybeUninit; N]>(array)` + unsafe { + crate::ptr::read(&array as *const [MaybeUninit; N] as *const [T; N]) + } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, const N: usize> IntoIterator for &'a [T; N] { type Item = &'a T; diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 81bbf37637875..116fc1e49cfa2 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -492,6 +492,7 @@ mod prim_pointer {} /// Arrays of *any* size implement the following traits if the element type allows it: /// /// - [`Debug`] +/// - [`FromIterator`] /// - [`IntoIterator`] (implemented for `&[T; N]` and `&mut [T; N]`) /// - [`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] /// - [`Hash`] From 1bee9929e2f7cf6aee01c91631db72175b66fc34 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 14 Mar 2020 13:28:58 +0100 Subject: [PATCH 02/16] remove specializations --- library/core/src/array/mod.rs | 40 ++--------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 8f0385cf33d1b..cc69be98d9f43 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -11,7 +11,7 @@ use crate::cmp::Ordering; use crate::convert::{Infallible, TryFrom}; use crate::fmt; use crate::hash::{self, Hash}; -use crate::iter::{FromIterator, ExactSizeIterator}; +use crate::iter::{FromIterator}; use crate::marker::Unsize; use crate::mem::MaybeUninit; use crate::slice::{Iter, IterMut}; @@ -197,20 +197,7 @@ where { #[inline] fn from_iter>(iter: I) -> Self { - >::from_iter(iter.into_iter()) - } -} - -// Specialization trait used for array::from_iter -trait ArrayFromIter { - fn from_iter(iter: I) -> Self; -} - -impl ArrayFromIter for [T; N] - where I: Iterator, - [T; N]: LengthAtMost32, -{ - default fn from_iter(mut iter: I) -> Self { + let mut iter = iter.into_iter(); let mut array: [MaybeUninit; N] = MaybeUninit::uninit_array(); for p in array.iter_mut() { @@ -226,29 +213,6 @@ impl ArrayFromIter for [T; N] } } -// Early panic if we know the size of the iterator -impl ArrayFromIter for [T; N] - where I: ExactSizeIterator, - [T; N]: LengthAtMost32, -{ - default fn from_iter(iter: I) -> Self { - assert_eq!(N, iter.len(), "Iterator is not the same length as the array"); - - let mut array: [MaybeUninit; N] = MaybeUninit::uninit_array(); - - for (p, v) in array.iter_mut().zip(iter) { - p.write(v); - } - - // FIXME: actually use `mem::transmute` here, once it - // works with const generics: - // `mem::transmute::<[T; N], [MaybeUninit; N]>(array)` - unsafe { - crate::ptr::read(&array as *const [MaybeUninit; N] as *const [T; N]) - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, const N: usize> IntoIterator for &'a [T; N] { type Item = &'a T; From f536b98eff7c98cd65be60b3f475ac0a4e142bfc Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 14 Mar 2020 13:42:08 +0100 Subject: [PATCH 03/16] drop values of partialy initalized array --- library/core/src/array/mod.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index cc69be98d9f43..6207cf435a6e5 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -200,8 +200,15 @@ where let mut iter = iter.into_iter(); let mut array: [MaybeUninit; N] = MaybeUninit::uninit_array(); - for p in array.iter_mut() { - p.write(iter.next().expect("Iterator is to short")); + for i in 0..N { + let value = iter.next().unwrap_or_else(|| { + // Drop already writen elements + for elem in &mut array[0..i] { + unsafe { crate::ptr::drop_in_place(elem.as_mut_ptr()); } + } + panic!("Iterator is to short"); + }); + array[i].write(value); } // FIXME: actually use `mem::transmute` here, once it From f6034e2669f1e30e98c87be9979c80180d09f2f0 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 14 Mar 2020 14:28:39 +0100 Subject: [PATCH 04/16] add tests --- library/core/tests/array.rs | 34 ++++++++++++++++++++++++++++++++++ src/doc/book | 2 +- src/doc/reference | 2 +- src/tools/cargo | 2 +- src/tools/miri | 2 +- src/tools/rls | 2 +- src/tools/rustfmt | 2 +- 7 files changed, 40 insertions(+), 6 deletions(-) diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index 89c2a969c28bb..d9f95c1b7b60b 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -374,3 +374,37 @@ fn cell_allows_array_cycle() { b3.a[0].set(Some(&b1)); b3.a[1].set(Some(&b2)); } + +#[test] +fn array_collects() { + let v = vec![1, 2, 3, 4, 5]; + let a: [i32; 5] = v.clone().into_iter().collect(); + + assert_eq!(v[..], a[..]); +} + +#[test] +fn array_collect_drop_on_panic() { + use std::sync::atomic::{AtomicUsize, Ordering}; + use std::sync::Arc; + + #[derive(Clone)] + struct Foo(Arc); + + // count the number of eleemts that got dropped + impl Drop for Foo { + fn drop(&mut self) { + self.0.fetch_add(1, Ordering::SeqCst); + } + } + + let i = Arc::new(AtomicUsize::new(0)); + let foo = Foo(i.clone()); + + std::panic::catch_unwind(move || { + let _a: [Foo; 5] = from_iter(vec![foo.clone(), foo.clone(), foo.clone(), foo]); + }) + .unwrap_err(); + + assert_eq!(i.load(Ordering::SeqCst), 4); +} diff --git a/src/doc/book b/src/doc/book index cb28dee95e5e5..363293c1c5ce9 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit cb28dee95e5e50b793e6ba9291c5d1568d3ad72e +Subproject commit 363293c1c5ce9e84ea3935a5e29ce8624801208a diff --git a/src/doc/reference b/src/doc/reference index 56a13c082ee90..c9b2736a05946 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 56a13c082ee90736c08d6abdcd90462517b703d3 +Subproject commit c9b2736a059469043177e1e4ed41a55d7c63ac28 diff --git a/src/tools/cargo b/src/tools/cargo index 9d1a4863abd92..ab32ee88dade1 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 9d1a4863abd9237dbf9d1b74c78632b6a205f6bb +Subproject commit ab32ee88dade1b50c77347599e82ca2de3fb8a51 diff --git a/src/tools/miri b/src/tools/miri index 3fafb835ea42e..1bfb26d6cae6f 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 3fafb835ea42e6e3af27f5dc8f26bda590cb49e9 +Subproject commit 1bfb26d6cae6f535ac1034877635fc0cef87fe64 diff --git a/src/tools/rls b/src/tools/rls index 9bfb47a79299d..942aa2b5d729a 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 9bfb47a79299d52f45304367762c9bfc96d9ed7c +Subproject commit 942aa2b5d729a63f8b81592ab7b2720b63a884e9 diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 97d0301011533..48f6c32ec1dd3 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 97d0301011533e1c131c0edd660d77b4bd476c8b +Subproject commit 48f6c32ec1dd370f3157a27b48a000fd8c1185af From ac02e716d77535e05288bd7da9a8866c350fd366 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 14 Mar 2020 14:45:58 +0100 Subject: [PATCH 05/16] change on drop impl to `if let` --- library/core/src/array/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 6207cf435a6e5..96a89ea278f71 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -201,14 +201,15 @@ where let mut array: [MaybeUninit; N] = MaybeUninit::uninit_array(); for i in 0..N { - let value = iter.next().unwrap_or_else(|| { + if let Some(value) = iter.next() { + array[i].write(value); + } else { // Drop already writen elements for elem in &mut array[0..i] { unsafe { crate::ptr::drop_in_place(elem.as_mut_ptr()); } } panic!("Iterator is to short"); - }); - array[i].write(value); + } } // FIXME: actually use `mem::transmute` here, once it From 67f531220a1d9f4ff4b04fda50ced5ca33f7dfec Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Tue, 31 Mar 2020 07:39:41 +0200 Subject: [PATCH 06/16] change impl to Resutl<[T;N], FillError> --- library/core/src/array/mod.rs | 90 +++++++++++++++++++++++++++-------- library/core/tests/array.rs | 2 +- 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 96a89ea278f71..8dbbbebbc5ef6 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -11,7 +11,7 @@ use crate::cmp::Ordering; use crate::convert::{Infallible, TryFrom}; use crate::fmt; use crate::hash::{self, Hash}; -use crate::iter::{FromIterator}; +use crate::iter::FromIterator; use crate::marker::Unsize; use crate::mem::MaybeUninit; use crate::slice::{Iter, IterMut}; @@ -190,34 +190,84 @@ impl fmt::Debug for [T; N] { } } -#[stable(feature = "array_from_iter_impl", since = "1.44.0")] -impl FromIterator for [T; N] +/// Return Value of the FromIterator impl for array +#[unstable(feature = "array_from_iter_impl", issue = "none")] +#[derive(Debug)] +pub struct FillError where - [T; N]: LengthAtMost32, + [MaybeUninit; N]: LengthAtMost32, { - #[inline] - fn from_iter>(iter: I) -> Self { + array: [MaybeUninit; N], + len: usize, +} + +#[unstable(feature = "array_from_iter_impl", issue = "none")] +impl Drop for FillError +where + [MaybeUninit; N]: LengthAtMost32, +{ + fn drop(&mut self) { + for elem in &mut self.array[0..self.len] { + unsafe { + crate::ptr::drop_in_place(elem.as_mut_ptr()); + } + } + } +} + +#[unstable(feature = "array_from_iter_impl", issue = "none")] +impl FillError +where + [MaybeUninit; N]: LengthAtMost32, +{ + fn new() -> Self { + Self { array: MaybeUninit::uninit_array(), len: 0 } + } + + /// Returns the how many elements were read from the given iterator. + pub fn len(&self) -> usize { + self.len + } + + /// Returns an immutable slice of all initialized elements. + pub fn as_slice(&self) -> &[T] { + unsafe { MaybeUninit::slice_get_ref(&self.array[0..self.len]) } + } + + /// Returns a mutable slice of all initialized elements. + pub fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { MaybeUninit::slice_get_mut(&mut self.array[0..self.len]) } + } + + /// Tries to initialize the left-over elements using `iter`. + pub fn fill>(mut self, iter: I) -> Result<[T; N], FillError> { let mut iter = iter.into_iter(); - let mut array: [MaybeUninit; N] = MaybeUninit::uninit_array(); - - for i in 0..N { + + for i in self.len..N { if let Some(value) = iter.next() { - array[i].write(value); + self.array[i].write(value); } else { - // Drop already writen elements - for elem in &mut array[0..i] { - unsafe { crate::ptr::drop_in_place(elem.as_mut_ptr()); } - } - panic!("Iterator is to short"); - } + self.len = i; + return Err(self); + } } - + // FIXME: actually use `mem::transmute` here, once it // works with const generics: // `mem::transmute::<[T; N], [MaybeUninit; N]>(array)` - unsafe { - crate::ptr::read(&array as *const [MaybeUninit; N] as *const [T; N]) - } + Ok(unsafe { crate::ptr::read(&self.array as *const [MaybeUninit; N] as *const [T; N]) }) + } +} + +#[unstable(feature = "array_from_iter_impl", issue = "none")] +impl FromIterator for Result<[T; N], FillError> +where + [T; N]: LengthAtMost32, + [MaybeUninit; N]: LengthAtMost32, +{ + #[inline] + fn from_iter>(iter: I) -> Self { + FillError::::new().fill(iter) } } diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index d9f95c1b7b60b..c9e971e902a8a 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -378,7 +378,7 @@ fn cell_allows_array_cycle() { #[test] fn array_collects() { let v = vec![1, 2, 3, 4, 5]; - let a: [i32; 5] = v.clone().into_iter().collect(); + let a: [i32; 5] = v.clone().into_iter().collect().unwrap(); assert_eq!(v[..], a[..]); } From b6def98a67153443bb268fec5e1f0eebbd802ba5 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Tue, 31 Mar 2020 10:23:50 +0200 Subject: [PATCH 07/16] add SAFTEY comments and impl Display for FillError --- library/core/src/array/mod.rs | 41 +++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 8dbbbebbc5ef6..3f01d5e4f83c9 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -190,7 +190,7 @@ impl fmt::Debug for [T; N] { } } -/// Return Value of the FromIterator impl for array +/// Return Error of the FromIterator impl for array #[unstable(feature = "array_from_iter_impl", issue = "none")] #[derive(Debug)] pub struct FillError @@ -201,17 +201,32 @@ where len: usize, } +#[unstable(feature = "array_from_iter_impl", issue = "none")] +impl fmt::Display for FillError +where + [MaybeUninit; N]: LengthAtMost32, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt( + &format_args!( + "The iterator only returned {} items, but {} where needed", + self.len(), + N + ), + f, + ) + } +} + #[unstable(feature = "array_from_iter_impl", issue = "none")] impl Drop for FillError where [MaybeUninit; N]: LengthAtMost32, { fn drop(&mut self) { - for elem in &mut self.array[0..self.len] { - unsafe { - crate::ptr::drop_in_place(elem.as_mut_ptr()); - } - } + // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice + // of elements that have been initialized and need to be droped + unsafe { crate::ptr::drop_in_place(self.as_mut_slice()) } } } @@ -231,11 +246,13 @@ where /// Returns an immutable slice of all initialized elements. pub fn as_slice(&self) -> &[T] { + // SAFETY: We know that all elements from 0 to len are properly initialized. unsafe { MaybeUninit::slice_get_ref(&self.array[0..self.len]) } } /// Returns a mutable slice of all initialized elements. pub fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: We know that all elements from 0 to len are properly initialized. unsafe { MaybeUninit::slice_get_mut(&mut self.array[0..self.len]) } } @@ -252,9 +269,19 @@ where } } + // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit` + // promise: + // + // > `MaybeUninit` is guaranteed to have the same size and alignment + // > as `T`. + // + // The docs even show a transmute from an array of `MaybeUninit` to + // an array of `T`. + // + // With that, this initialization satisfies the invariants. // FIXME: actually use `mem::transmute` here, once it // works with const generics: - // `mem::transmute::<[T; N], [MaybeUninit; N]>(array)` + // `mem::transmute::<[MaybeUninit; N], [T; N]>(array)` Ok(unsafe { crate::ptr::read(&self.array as *const [MaybeUninit; N] as *const [T; N]) }) } } From ca3d898e592a951ccb5280ca8d3bc554b6f0c866 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Tue, 31 Mar 2020 11:02:05 +0200 Subject: [PATCH 08/16] manuel impl Debug for FillError --- library/core/src/array/mod.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 3f01d5e4f83c9..53bb12724fc0c 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -192,7 +192,6 @@ impl fmt::Debug for [T; N] { /// Return Error of the FromIterator impl for array #[unstable(feature = "array_from_iter_impl", issue = "none")] -#[derive(Debug)] pub struct FillError where [MaybeUninit; N]: LengthAtMost32, @@ -218,6 +217,19 @@ where } } +#[unstable(feature = "array_from_iter_impl", issue = "none")] +impl fmt::Debug for FillError +where + [MaybeUninit; N]: LengthAtMost32, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FillError") + .field("array", &self.as_slice()) + .field("len", &self.len()) + .finish() + } +} + #[unstable(feature = "array_from_iter_impl", issue = "none")] impl Drop for FillError where From e86909e324da71de9e8594d7b0dc1db447cdbee6 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Tue, 31 Mar 2020 14:13:31 +0200 Subject: [PATCH 09/16] add type anotation to test --- library/core/tests/array.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index c9e971e902a8a..fd8b698ea8e08 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -378,7 +378,11 @@ fn cell_allows_array_cycle() { #[test] fn array_collects() { let v = vec![1, 2, 3, 4, 5]; - let a: [i32; 5] = v.clone().into_iter().collect().unwrap(); + let a: [i32; 5] = v + .clone() + .into_iter() + .collect::>>() + .unwrap(); assert_eq!(v[..], a[..]); } From bb4fceb7c43e53b8836a0861f8bcec5257e1f1c9 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Wed, 1 Apr 2020 10:13:01 +0200 Subject: [PATCH 10/16] add feature to test lib --- library/core/tests/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 0c4ce867f542d..e13999de41c97 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -60,6 +60,7 @@ #![feature(unsafe_block_in_unsafe_fn)] #![feature(int_bits_const)] #![deny(unsafe_op_in_unsafe_fn)] +#![feature(array_from_iter_impl)] extern crate test; From 53a49f82dd07ebd886d0adcddaf5d8dca90e9052 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Fri, 24 Apr 2020 13:18:02 +0200 Subject: [PATCH 11/16] remove LengthAtMost32 bound --- library/core/src/array/mod.rs | 37 +++++++---------------------------- 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 53bb12724fc0c..fbe82e0666bca 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -192,36 +192,23 @@ impl fmt::Debug for [T; N] { /// Return Error of the FromIterator impl for array #[unstable(feature = "array_from_iter_impl", issue = "none")] -pub struct FillError -where - [MaybeUninit; N]: LengthAtMost32, -{ +pub struct FillError { array: [MaybeUninit; N], len: usize, } #[unstable(feature = "array_from_iter_impl", issue = "none")] -impl fmt::Display for FillError -where - [MaybeUninit; N]: LengthAtMost32, -{ +impl fmt::Display for FillError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt( - &format_args!( - "The iterator only returned {} items, but {} where needed", - self.len(), - N - ), + &format_args!("The iterator only returned {} items, but {} were needed", self.len(), N), f, ) } } #[unstable(feature = "array_from_iter_impl", issue = "none")] -impl fmt::Debug for FillError -where - [MaybeUninit; N]: LengthAtMost32, -{ +impl fmt::Debug for FillError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FillError") .field("array", &self.as_slice()) @@ -231,10 +218,7 @@ where } #[unstable(feature = "array_from_iter_impl", issue = "none")] -impl Drop for FillError -where - [MaybeUninit; N]: LengthAtMost32, -{ +impl Drop for FillError { fn drop(&mut self) { // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice // of elements that have been initialized and need to be droped @@ -243,10 +227,7 @@ where } #[unstable(feature = "array_from_iter_impl", issue = "none")] -impl FillError -where - [MaybeUninit; N]: LengthAtMost32, -{ +impl FillError { fn new() -> Self { Self { array: MaybeUninit::uninit_array(), len: 0 } } @@ -299,11 +280,7 @@ where } #[unstable(feature = "array_from_iter_impl", issue = "none")] -impl FromIterator for Result<[T; N], FillError> -where - [T; N]: LengthAtMost32, - [MaybeUninit; N]: LengthAtMost32, -{ +impl FromIterator for Result<[T; N], FillError> { #[inline] fn from_iter>(iter: I) -> Self { FillError::::new().fill(iter) From 4424ee7c40318cd2a0b573095b83f4f87f5b3320 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sun, 16 Aug 2020 12:25:41 +0200 Subject: [PATCH 12/16] remove LengthAtMost32 bound From 0f08007dadc0e87b021b482bc6f1bf9ffd03aa4f Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Thu, 8 Oct 2020 16:44:25 +0200 Subject: [PATCH 13/16] fix books --- src/doc/book | 2 +- src/doc/reference | 2 +- src/tools/cargo | 2 +- src/tools/miri | 2 +- src/tools/rls | 2 +- src/tools/rustfmt | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/book b/src/doc/book index 363293c1c5ce9..cb28dee95e5e5 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 363293c1c5ce9e84ea3935a5e29ce8624801208a +Subproject commit cb28dee95e5e50b793e6ba9291c5d1568d3ad72e diff --git a/src/doc/reference b/src/doc/reference index c9b2736a05946..56a13c082ee90 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit c9b2736a059469043177e1e4ed41a55d7c63ac28 +Subproject commit 56a13c082ee90736c08d6abdcd90462517b703d3 diff --git a/src/tools/cargo b/src/tools/cargo index ab32ee88dade1..9d1a4863abd92 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit ab32ee88dade1b50c77347599e82ca2de3fb8a51 +Subproject commit 9d1a4863abd9237dbf9d1b74c78632b6a205f6bb diff --git a/src/tools/miri b/src/tools/miri index 1bfb26d6cae6f..3fafb835ea42e 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 1bfb26d6cae6f535ac1034877635fc0cef87fe64 +Subproject commit 3fafb835ea42e6e3af27f5dc8f26bda590cb49e9 diff --git a/src/tools/rls b/src/tools/rls index 942aa2b5d729a..9bfb47a79299d 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 942aa2b5d729a63f8b81592ab7b2720b63a884e9 +Subproject commit 9bfb47a79299d52f45304367762c9bfc96d9ed7c diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 48f6c32ec1dd3..97d0301011533 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 48f6c32ec1dd370f3157a27b48a000fd8c1185af +Subproject commit 97d0301011533e1c131c0edd660d77b4bd476c8b From 0992c4e8eec75606abc1080f6554cdea1fb491be Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sun, 1 Nov 2020 19:13:17 +0100 Subject: [PATCH 14/16] dont leak on panic --- library/core/src/array/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index fbe82e0666bca..af10f843fa8b2 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -240,13 +240,13 @@ impl FillError { /// Returns an immutable slice of all initialized elements. pub fn as_slice(&self) -> &[T] { // SAFETY: We know that all elements from 0 to len are properly initialized. - unsafe { MaybeUninit::slice_get_ref(&self.array[0..self.len]) } + unsafe { MaybeUninit::slice_assume_init_ref(&self.array[0..self.len]) } } /// Returns a mutable slice of all initialized elements. pub fn as_mut_slice(&mut self) -> &mut [T] { // SAFETY: We know that all elements from 0 to len are properly initialized. - unsafe { MaybeUninit::slice_get_mut(&mut self.array[0..self.len]) } + unsafe { MaybeUninit::slice_assume_init_mut(&mut self.array[0..self.len]) } } /// Tries to initialize the left-over elements using `iter`. @@ -256,6 +256,7 @@ impl FillError { for i in self.len..N { if let Some(value) = iter.next() { self.array[i].write(value); + self.len += 1; } else { self.len = i; return Err(self); @@ -502,7 +503,6 @@ impl [T; N] { where F: FnMut(T) -> U, { - use crate::mem::MaybeUninit; struct Guard { dst: *mut T, initialized: usize, From ddeb2c246b5c7addeeccb4f627b3328546a64244 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sun, 1 Nov 2020 20:07:46 +0100 Subject: [PATCH 15/16] fix tests --- library/core/tests/array.rs | 32 +------------------------------- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index fd8b698ea8e08..a3a13b94b6169 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -378,37 +378,7 @@ fn cell_allows_array_cycle() { #[test] fn array_collects() { let v = vec![1, 2, 3, 4, 5]; - let a: [i32; 5] = v - .clone() - .into_iter() - .collect::>>() - .unwrap(); + let a: [i32; 5] = v.clone().into_iter().collect::>().unwrap(); assert_eq!(v[..], a[..]); } - -#[test] -fn array_collect_drop_on_panic() { - use std::sync::atomic::{AtomicUsize, Ordering}; - use std::sync::Arc; - - #[derive(Clone)] - struct Foo(Arc); - - // count the number of eleemts that got dropped - impl Drop for Foo { - fn drop(&mut self) { - self.0.fetch_add(1, Ordering::SeqCst); - } - } - - let i = Arc::new(AtomicUsize::new(0)); - let foo = Foo(i.clone()); - - std::panic::catch_unwind(move || { - let _a: [Foo; 5] = from_iter(vec![foo.clone(), foo.clone(), foo.clone(), foo]); - }) - .unwrap_err(); - - assert_eq!(i.load(Ordering::SeqCst), 4); -} From ec0a26c4e6732ad1cc365251e6d912f0ae680999 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sun, 1 Nov 2020 22:09:52 +0100 Subject: [PATCH 16/16] fix FromIterator intra-doc link --- library/std/src/primitive_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 116fc1e49cfa2..0adf229721a52 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -492,7 +492,7 @@ mod prim_pointer {} /// Arrays of *any* size implement the following traits if the element type allows it: /// /// - [`Debug`] -/// - [`FromIterator`] +/// - [`iter::FromIterator`] /// - [`IntoIterator`] (implemented for `&[T; N]` and `&mut [T; N]`) /// - [`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] /// - [`Hash`]