about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-10-06 16:32:46 +0000
committerbors <bors@rust-lang.org>2019-10-06 16:32:46 +0000
commit421bd77f42c2fe8a2596dbcc1580ec97fb89009f (patch)
tree7c0dc2e29403ff3bc579d3d422a4495d067ca751 /src/liballoc
parent9203ee7b56b9963e6b95a58fb43985a3d9a637f6 (diff)
parent47f89e7485ed7a76d8bfcbedcad07fd6b74fa927 (diff)
downloadrust-421bd77f42c2fe8a2596dbcc1580ec97fb89009f.tar.gz
rust-421bd77f42c2fe8a2596dbcc1580ec97fb89009f.zip
Auto merge of #64564 - jonas-schievink:cowardly-default, r=nikomatsakis
Deny specializing items not in the parent impl

Part of https://github.com/rust-lang/rust/issues/29661 (https://github.com/rust-lang/rfcs/pull/2532). At least sort of?

This was discussed in https://github.com/rust-lang/rust/pull/61812#discussion_r300504114 and is needed for that PR to make progress (fixing an unsoundness).

One annoyance with doing this is that it sometimes requires users to copy-paste a provided trait method into an impl just to mark it `default` (ie. there is no syntax to forward this impl method to the provided trait method).

cc @Centril and @arielb1
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/boxed.rs26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index b2789a535fe..9b5d9431ae2 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -871,11 +871,33 @@ impl<I: Iterator + ?Sized> Iterator for Box<I> {
     fn nth(&mut self, n: usize) -> Option<I::Item> {
         (**self).nth(n)
     }
+    fn last(self) -> Option<I::Item> {
+        BoxIter::last(self)
+    }
+}
+
+trait BoxIter {
+    type Item;
+    fn last(self) -> Option<Self::Item>;
+}
+
+impl<I: Iterator + ?Sized> BoxIter for Box<I> {
+    type Item = I::Item;
+    default fn last(self) -> Option<I::Item> {
+        #[inline]
+        fn some<T>(_: Option<T>, x: T) -> Option<T> {
+            Some(x)
+        }
+
+        self.fold(None, some)
+    }
 }
 
+/// Specialization for sized `I`s that uses `I`s implementation of `last()`
+/// instead of the default.
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<I: Iterator + Sized> Iterator for Box<I> {
-    fn last(self) -> Option<I::Item> where I: Sized {
+impl<I: Iterator> BoxIter for Box<I> {
+    fn last(self) -> Option<I::Item> {
         (*self).last()
     }
 }