From af424c1813eca41024da5290e064ead85f68dc0b Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Mon, 1 Feb 2021 10:31:05 +0100 Subject: [PATCH 1/4] Implement SourceIterator and InPlaceIterable for ResultShunt --- library/core/src/iter/adapters/mod.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 41a7b13232adf..f72e642620090 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -191,3 +191,26 @@ where self.try_fold(init, ok(fold)).unwrap() } } + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for ResultShunt<'_, I, E> +where + I: SourceIter, +{ + type Source = S; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut S { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +// SAFETY: ResultShunt::next calls I::find, which has to advance `iter` in order to +// return `Some(_)`. Since `iter` has type `I: InPlaceIterable` it's guaranteed that +// at least one item will be moved out from the underlying source. +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for ResultShunt<'_, I, E> where + I: Iterator> + InPlaceIterable +{ +} From 524b0c9c614d4691b2e21ace47fce4df15900701 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Mon, 1 Feb 2021 10:31:34 +0100 Subject: [PATCH 2/4] Add test for inplace collection of Result,_> --- library/core/tests/iter/mod.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs index 770b6f7601fa2..b88f2f2089d18 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -100,3 +100,29 @@ pub fn extend_for_unit() { } assert_eq!(x, 5); } + +#[test] +pub fn inplace_result_collect() { + let src = vec![0usize; 256]; + let srcptr = src.as_ptr(); + let sink = src.into_iter().map(|i| Ok(i)).collect::, ()>>().unwrap(); + let sinkptr = sink.as_ptr(); + assert_eq!(srcptr, sinkptr); + + let src: Vec = vec![0usize; 256]; + let srcptr = src.as_ptr(); + let iter = src + .into_iter() + .enumerate() + .map(|i| i.0 + i.1) + .zip(std::iter::repeat(1usize)) + .map(|(a, b)| a + b) + .map_while(Option::Some) + .peekable() + .skip(1) + .map(|e| std::num::NonZeroUsize::new(e)) + .map(|z| z.map(|u| u.get()).ok_or(())); + let sink = iter.collect::, _>>().unwrap(); + let sinkptr = sink.as_ptr(); + assert_eq!(srcptr, sinkptr as *const usize); +} From c6c8f3bf12bdeba01ba16eaacc5808e5321302f8 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Mon, 1 Feb 2021 17:16:54 +0100 Subject: [PATCH 3/4] Move test --- library/alloc/tests/vec.rs | 4 ++-- library/core/tests/iter/mod.rs | 26 -------------------------- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index e19406d7a0697..9ae333ce2c3e5 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -931,9 +931,9 @@ fn test_from_iter_specialization_with_iterator_adapters() { .map_while(Option::Some) .peekable() .skip(1) - .map(|e| std::num::NonZeroUsize::new(e)); + .map(|e| if e != 0 { Ok(e) } else { Err(()) }); assert_in_place_trait(&iter); - let sink = iter.collect::>(); + let sink = iter.collect::, _>>().unwrap(); let sinkptr = sink.as_ptr(); assert_eq!(srcptr, sinkptr as *const usize); } diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs index b88f2f2089d18..770b6f7601fa2 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -100,29 +100,3 @@ pub fn extend_for_unit() { } assert_eq!(x, 5); } - -#[test] -pub fn inplace_result_collect() { - let src = vec![0usize; 256]; - let srcptr = src.as_ptr(); - let sink = src.into_iter().map(|i| Ok(i)).collect::, ()>>().unwrap(); - let sinkptr = sink.as_ptr(); - assert_eq!(srcptr, sinkptr); - - let src: Vec = vec![0usize; 256]; - let srcptr = src.as_ptr(); - let iter = src - .into_iter() - .enumerate() - .map(|i| i.0 + i.1) - .zip(std::iter::repeat(1usize)) - .map(|(a, b)| a + b) - .map_while(Option::Some) - .peekable() - .skip(1) - .map(|e| std::num::NonZeroUsize::new(e)) - .map(|z| z.map(|u| u.get()).ok_or(())); - let sink = iter.collect::, _>>().unwrap(); - let sinkptr = sink.as_ptr(); - assert_eq!(srcptr, sinkptr as *const usize); -} From 2fb56cc123cc1111cff2803ab7df26a0f0941fae Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Wed, 3 Feb 2021 21:00:07 +0100 Subject: [PATCH 4/4] Update test to collect item with a different type than the original vec --- library/alloc/tests/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 9ae333ce2c3e5..9a0739a27595f 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -931,7 +931,7 @@ fn test_from_iter_specialization_with_iterator_adapters() { .map_while(Option::Some) .peekable() .skip(1) - .map(|e| if e != 0 { Ok(e) } else { Err(()) }); + .map(|e| if e != usize::MAX { Ok(std::num::NonZeroUsize::new(e)) } else { Err(()) }); assert_in_place_trait(&iter); let sink = iter.collect::, _>>().unwrap(); let sinkptr = sink.as_ptr();