about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorChristian Poveda <christianpoveda@protonmail.com>2019-07-04 01:45:29 -0500
committerChristian Poveda <christianpoveda@protonmail.com>2019-07-04 01:45:29 -0500
commite45bbaf48c9fb0439426967009d837f0fe4f74ce (patch)
treea887380eed192d6ea9b2f124574932bcc1297c34 /src/libcore
parente32b8eb00a94274e680d1ae63c429d5b7db65e99 (diff)
parentb43eb4235ac43c822d903ad26ed806f34cc1a14a (diff)
downloadrust-e45bbaf48c9fb0439426967009d837f0fe4f74ce.tar.gz
rust-e45bbaf48c9fb0439426967009d837f0fe4f74ce.zip
Fix merge conflicts
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/ascii.rs1
-rw-r--r--src/libcore/char/methods.rs6
-rw-r--r--src/libcore/convert.rs25
-rw-r--r--src/libcore/iter/traits/collect.rs2
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/marker.rs6
-rw-r--r--src/libcore/mem/mod.rs33
-rw-r--r--src/libcore/option.rs12
-rw-r--r--src/libcore/ptr/mod.rs32
-rw-r--r--src/libcore/raw.rs4
-rw-r--r--src/libcore/slice/mod.rs15
-rw-r--r--src/libcore/str/mod.rs47
-rw-r--r--src/libcore/tests/ascii.rs2
-rw-r--r--src/libcore/tests/fmt/mod.rs2
-rw-r--r--src/libcore/tests/pattern.rs2
-rw-r--r--src/libcore/tests/ptr.rs5
-rw-r--r--src/libcore/tests/slice.rs23
17 files changed, 127 insertions, 91 deletions
diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs
index c0ab364380f..e6a6fdde540 100644
--- a/src/libcore/ascii.rs
+++ b/src/libcore/ascii.rs
@@ -117,6 +117,7 @@ impl Iterator for EscapeDefault {
     type Item = u8;
     fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
     fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
+    fn last(mut self) -> Option<u8> { self.next_back() }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl DoubleEndedIterator for EscapeDefault {
diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs
index 722c4c80516..e843303380a 100644
--- a/src/libcore/char/methods.rs
+++ b/src/libcore/char/methods.rs
@@ -337,16 +337,16 @@ impl char {
     /// ```
     /// // as chars
     /// let eastern = '東';
-    /// let capitol = '京';
+    /// let capital = '京';
     ///
     /// // both can be represented as three bytes
     /// assert_eq!(3, eastern.len_utf8());
-    /// assert_eq!(3, capitol.len_utf8());
+    /// assert_eq!(3, capital.len_utf8());
     ///
     /// // as a &str, these two are encoded in UTF-8
     /// let tokyo = "東京";
     ///
-    /// let len = eastern.len_utf8() + capitol.len_utf8();
+    /// let len = eastern.len_utf8() + capital.len_utf8();
     ///
     /// // we can see that they take six bytes total...
     /// assert_eq!(6, tokyo.len());
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index a697b7bd6e5..c0de8e2ceb3 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -251,12 +251,12 @@ pub trait AsMut<T: ?Sized> {
 ///
 /// # Examples
 ///
-/// [`String`] implements `Into<Vec<u8>>`:
+/// [`String`] implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>`:
 ///
 /// In order to express that we want a generic function to take all arguments that can be
 /// converted to a specified type `T`, we can use a trait bound of [`Into`]`<T>`.
 /// For example: The function `is_hello` takes all arguments that can be converted into a
-/// `Vec<u8>`.
+/// [`Vec`]`<`[`u8`]`>`.
 ///
 /// ```
 /// fn is_hello<T: Into<Vec<u8>>>(s: T) {
@@ -274,6 +274,7 @@ pub trait AsMut<T: ?Sized> {
 /// [`String`]: ../../std/string/struct.String.html
 /// [`From`]: trait.From.html
 /// [`Into`]: trait.Into.html
+/// [`Vec`]: ../../std/vec/struct.Vec.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Into<T>: Sized {
     /// Performs the conversion.
@@ -410,12 +411,12 @@ pub trait TryInto<T>: Sized {
 ///
 /// This is useful when you are doing a type conversion that may
 /// trivially succeed but may also need special handling.
-/// For example, there is no way to convert an `i64` into an `i32`
-/// using the [`From`] trait, because an `i64` may contain a value
-/// that an `i32` cannot represent and so the conversion would lose data.
-/// This might be handled by truncating the `i64` to an `i32` (essentially
-/// giving the `i64`'s value modulo `i32::MAX`) or by simply returning
-/// `i32::MAX`, or by some other method.  The `From` trait is intended
+/// For example, there is no way to convert an [`i64`] into an [`i32`]
+/// using the [`From`] trait, because an [`i64`] may contain a value
+/// that an [`i32`] cannot represent and so the conversion would lose data.
+/// This might be handled by truncating the [`i64`] to an [`i32`] (essentially
+/// giving the [`i64`]'s value modulo [`i32::MAX`]) or by simply returning
+/// [`i32::MAX`], or by some other method.  The [`From`] trait is intended
 /// for perfect conversions, so the `TryFrom` trait informs the
 /// programmer when a type conversion could go bad and lets them
 /// decide how to handle it.
@@ -425,8 +426,8 @@ pub trait TryInto<T>: Sized {
 /// - `TryFrom<T> for U` implies [`TryInto`]`<U> for T`
 /// - [`try_from`] is reflexive, which means that `TryFrom<T> for T`
 /// is implemented and cannot fail -- the associated `Error` type for
-/// calling `T::try_from()` on a value of type `T` is `Infallible`.
-/// When the `!` type is stablized `Infallible` and `!` will be
+/// calling `T::try_from()` on a value of type `T` is [`Infallible`].
+/// When the [`!`] type is stablized [`Infallible`] and [`!`] will be
 /// equivalent.
 ///
 /// `TryFrom<T>` can be implemented as follows:
@@ -451,7 +452,7 @@ pub trait TryInto<T>: Sized {
 ///
 /// # Examples
 ///
-/// As described, [`i32`] implements `TryFrom<i64>`:
+/// As described, [`i32`] implements `TryFrom<`[`i64`]`>`:
 ///
 /// ```
 /// use std::convert::TryFrom;
@@ -474,6 +475,8 @@ pub trait TryInto<T>: Sized {
 ///
 /// [`try_from`]: trait.TryFrom.html#tymethod.try_from
 /// [`TryInto`]: trait.TryInto.html
+/// [`i32::MAX`]: ../../std/i32/constant.MAX.html
+/// [`!`]: ../../std/primitive.never.html
 #[stable(feature = "try_from", since = "1.34.0")]
 pub trait TryFrom<T>: Sized {
     /// The type returned in the event of a conversion error.
diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs
index cd61ab5c552..1865160bc3c 100644
--- a/src/libcore/iter/traits/collect.rs
+++ b/src/libcore/iter/traits/collect.rs
@@ -196,7 +196,7 @@ pub trait FromIterator<A>: Sized {
 /// ```rust
 /// fn collect_as_strings<T>(collection: T) -> Vec<String>
 ///     where T: IntoIterator,
-///           T::Item : std::fmt::Debug,
+///           T::Item: std::fmt::Debug,
 /// {
 ///     collection
 ///         .into_iter()
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 04c50329de3..d2d08a075b9 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -126,6 +126,7 @@
 #![feature(adx_target_feature)]
 #![feature(maybe_uninit_slice, maybe_uninit_array)]
 #![feature(external_doc)]
+#![feature(mem_take)]
 
 #[prelude_import]
 #[allow(unused)]
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 3f4ff7c2f43..d9757d78dce 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -73,9 +73,9 @@ impl<T: ?Sized> !Send for *mut T { }
 /// impl Foo for Impl { }
 /// impl Bar for Impl { }
 ///
-/// let x: &Foo = &Impl;    // OK
-/// // let y: &Bar = &Impl; // error: the trait `Bar` cannot
-///                         // be made into an object
+/// let x: &dyn Foo = &Impl;    // OK
+/// // let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot
+///                             // be made into an object
 /// ```
 ///
 /// [trait object]: ../../book/ch17-02-trait-objects.html
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs
index 770d1ca8e75..b31522db474 100644
--- a/src/libcore/mem/mod.rs
+++ b/src/libcore/mem/mod.rs
@@ -510,6 +510,8 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 /// A simple example:
 ///
 /// ```
+/// #![feature(mem_take)]
+///
 /// use std::mem;
 ///
 /// let mut v: Vec<i32> = vec![1, 2];
@@ -540,7 +542,8 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 /// `self`, allowing it to be returned:
 ///
 /// ```
-/// # #![allow(dead_code)]
+/// #![feature(mem_take)]
+///
 /// use std::mem;
 ///
 /// # struct Buffer<T> { buf: Vec<T> }
@@ -549,6 +552,12 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 ///         mem::take(&mut self.buf)
 ///     }
 /// }
+///
+/// let mut buffer = Buffer { buf: vec![0, 1] };
+/// assert_eq!(buffer.buf.len(), 2);
+///
+/// assert_eq!(buffer.get_and_reset(), vec![0, 1]);
+/// assert_eq!(buffer.buf.len(), 0);
 /// ```
 ///
 /// [`Clone`]: ../../std/clone/trait.Clone.html
@@ -583,17 +592,17 @@ pub fn take<T: Default>(dest: &mut T) -> T {
 /// struct Buffer<T> { buf: Vec<T> }
 ///
 /// impl<T> Buffer<T> {
-///     fn get_and_reset(&mut self) -> Vec<T> {
+///     fn replace_index(&mut self, i: usize, v: T) -> T {
 ///         // error: cannot move out of dereference of `&mut`-pointer
-///         let buf = self.buf;
-///         self.buf = Vec::new();
-///         buf
+///         let t = self.buf[i];
+///         self.buf[i] = v;
+///         t
 ///     }
 /// }
 /// ```
 ///
-/// Note that `T` does not necessarily implement [`Clone`], so it can't even clone and reset
-/// `self.buf`. But `replace` can be used to disassociate the original value of `self.buf` from
+/// Note that `T` does not necessarily implement [`Clone`], so we can't even clone `self.buf[i]` to
+/// avoid the move. But `replace` can be used to disassociate the original value at that index from
 /// `self`, allowing it to be returned:
 ///
 /// ```
@@ -602,10 +611,16 @@ pub fn take<T: Default>(dest: &mut T) -> T {
 ///
 /// # struct Buffer<T> { buf: Vec<T> }
 /// impl<T> Buffer<T> {
-///     fn get_and_reset(&mut self) -> Vec<T> {
-///         mem::replace(&mut self.buf, Vec::new())
+///     fn replace_index(&mut self, i: usize, v: T) -> T {
+///         mem::replace(&mut self.buf[i], v)
 ///     }
 /// }
+///
+/// let mut buffer = Buffer { buf: vec![0, 1] };
+/// assert_eq!(buffer.buf[0], 0);
+///
+/// assert_eq!(buffer.replace_index(0, 2), 0);
+/// assert_eq!(buffer.buf[0], 2);
 /// ```
 ///
 /// [`Clone`]: ../../std/clone/trait.Clone.html
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index eec4b149ddc..b27fd4098e1 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -777,15 +777,7 @@ impl<T> Option<T> {
     #[inline]
     #[stable(feature = "option_entry", since = "1.20.0")]
     pub fn get_or_insert(&mut self, v: T) -> &mut T {
-        match *self {
-            None => *self = Some(v),
-            _ => (),
-        }
-
-        match *self {
-            Some(ref mut v) => v,
-            None => unsafe { hint::unreachable_unchecked() },
-        }
+        self.get_or_insert_with(|| v)
     }
 
     /// Inserts a value computed from `f` into the option if it is [`None`], then
@@ -845,7 +837,7 @@ impl<T> Option<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn take(&mut self) -> Option<T> {
-        mem::replace(self, None)
+        mem::take(self)
     }
 
     /// Replaces the actual value in the option by the value given in parameter,
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index fccb00d768c..da781d7e9fe 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -100,7 +100,11 @@ pub use unique::Unique;
 ///   as the compiler doesn't need to prove that it's sound to elide the
 ///   copy.
 ///
+/// Unaligned values cannot be dropped in place, they must be copied to an aligned
+/// location first using [`ptr::read_unaligned`].
+///
 /// [`ptr::read`]: ../ptr/fn.read.html
+/// [`ptr::read_unaligned`]: ../ptr/fn.read_unaligned.html
 ///
 /// # Safety
 ///
@@ -108,8 +112,7 @@ pub use unique::Unique;
 ///
 /// * `to_drop` must be [valid] for reads.
 ///
-/// * `to_drop` must be properly aligned. See the example below for how to drop
-///   an unaligned pointer.
+/// * `to_drop` must be properly aligned.
 ///
 /// Additionally, if `T` is not [`Copy`], using the pointed-to value after
 /// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop =
@@ -153,31 +156,6 @@ pub use unique::Unique;
 /// assert!(weak.upgrade().is_none());
 /// ```
 ///
-/// Unaligned values cannot be dropped in place, they must be copied to an aligned
-/// location first:
-/// ```
-/// use std::ptr;
-/// use std::mem::{self, MaybeUninit};
-///
-/// unsafe fn drop_after_copy<T>(to_drop: *mut T) {
-///     let mut copy: MaybeUninit<T> = MaybeUninit::uninit();
-///     ptr::copy(to_drop, copy.as_mut_ptr(), 1);
-///     drop(copy.assume_init());
-/// }
-///
-/// #[repr(packed, C)]
-/// struct Packed {
-///     _padding: u8,
-///     unaligned: Vec<i32>,
-/// }
-///
-/// let mut p = Packed { _padding: 0, unaligned: vec![42] };
-/// unsafe {
-///     drop_after_copy(&mut p.unaligned as *mut _);
-///     mem::forget(p);
-/// }
-/// ```
-///
 /// Notice that the compiler performs this copy automatically when dropping packed structs,
 /// i.e., you do not usually have to worry about such issues unless you call `drop_in_place`
 /// manually.
diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs
index 155429b0e4f..75c329a7d6c 100644
--- a/src/libcore/raw.rs
+++ b/src/libcore/raw.rs
@@ -53,7 +53,7 @@
 /// let value: i32 = 123;
 ///
 /// // let the compiler make a trait object
-/// let object: &Foo = &value;
+/// let object: &dyn Foo = &value;
 ///
 /// // look at the raw representation
 /// let raw_object: raw::TraitObject = unsafe { mem::transmute(object) };
@@ -65,7 +65,7 @@
 ///
 /// // construct a new object, pointing to a different `i32`, being
 /// // careful to use the `i32` vtable from `object`
-/// let synthesized: &Foo = unsafe {
+/// let synthesized: &dyn Foo = unsafe {
 ///      mem::transmute(raw::TraitObject {
 ///          data: &other_value as *const _ as *mut (),
 ///          vtable: raw_object.vtable,
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index c6d44324ef5..fe48e2458cd 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -4453,6 +4453,21 @@ impl<'a, T> DoubleEndedIterator for ChunksExact<'a, T> {
             Some(snd)
         }
     }
+
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+        let len = self.len();
+        if n >= len {
+            self.v = &[];
+            None
+        } else {
+            let start = (len - 1 - n) * self.chunk_size;
+            let end = start + self.chunk_size;
+            let nth_back = &self.v[start..end];
+            self.v = &self.v[..start];
+            Some(nth_back)
+        }
+    }
 }
 
 #[stable(feature = "chunks_exact", since = "1.31.0")]
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 34f2d8917ea..b027e6bc051 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1333,6 +1333,11 @@ impl<'a> Iterator for Lines<'a> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.0.size_hint()
     }
+
+    #[inline]
+    fn last(mut self) -> Option<&'a str> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -3716,10 +3721,10 @@ impl str {
     ///
     /// # Text directionality
     ///
-    /// A string is a sequence of bytes. 'Left' in this context means the first
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _right_ side, not the left.
+    /// A string is a sequence of bytes. `start` in this context means the first
+    /// position of that byte string; for a left-to-right language like English or
+    /// Russian, this will be left side, and for right-to-left languages like
+    /// like Arabic or Hebrew, this will be the right side.
     ///
     /// # Examples
     ///
@@ -3755,10 +3760,10 @@ impl str {
     ///
     /// # Text directionality
     ///
-    /// A string is a sequence of bytes. 'Right' in this context means the last
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _left_ side, not the right.
+    /// A string is a sequence of bytes. `end` in this context means the last
+    /// position of that byte string; for a left-to-right language like English or
+    /// Russian, this will be right side, and for right-to-left languages like
+    /// like Arabic or Hebrew, this will be the left side.
     ///
     /// # Examples
     ///
@@ -3804,10 +3809,10 @@ impl str {
     ///
     /// # Text directionality
     ///
-    /// A string is a sequence of bytes. `start` in this context means the first
-    /// position of that byte string; for a left-to-right language like English or
-    /// Russian, this will be left side, and for right-to-left languages like
-    /// like Arabic or Hebrew, this will be the right side.
+    /// A string is a sequence of bytes. 'Left' in this context means the first
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _right_ side, not the left.
     ///
     /// # Examples
     ///
@@ -3840,10 +3845,10 @@ impl str {
     ///
     /// # Text directionality
     ///
-    /// A string is a sequence of bytes. `end` in this context means the last
-    /// position of that byte string; for a left-to-right language like English or
-    /// Russian, this will be right side, and for right-to-left languages like
-    /// like Arabic or Hebrew, this will be the left side.
+    /// A string is a sequence of bytes. 'Right' in this context means the last
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _left_ side, not the right.
     ///
     /// # Examples
     ///
@@ -4241,6 +4246,11 @@ impl<'a> Iterator for SplitWhitespace<'a> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
+
+    #[inline]
+    fn last(mut self) -> Option<&'a str> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "split_whitespace", since = "1.1.0")]
@@ -4267,6 +4277,11 @@ impl<'a> Iterator for SplitAsciiWhitespace<'a> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
+
+    #[inline]
+    fn last(mut self) -> Option<&'a str> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
diff --git a/src/libcore/tests/ascii.rs b/src/libcore/tests/ascii.rs
index ec98e0464c9..439ed0c81c8 100644
--- a/src/libcore/tests/ascii.rs
+++ b/src/libcore/tests/ascii.rs
@@ -151,7 +151,7 @@ macro_rules! assert_none {
                            stringify!($what), b);
                 }
             }
-        )*
+        )+
     }};
     ($what:ident, $($str:tt),+,) => (assert_none!($what,$($str),+))
 }
diff --git a/src/libcore/tests/fmt/mod.rs b/src/libcore/tests/fmt/mod.rs
index df1deeaeb97..d86e21cf40b 100644
--- a/src/libcore/tests/fmt/mod.rs
+++ b/src/libcore/tests/fmt/mod.rs
@@ -3,7 +3,6 @@ mod float;
 mod num;
 
 #[test]
-#[cfg(not(miri))] // Miri cannot print pointers
 fn test_format_flags() {
     // No residual flags left by pointer formatting
     let p = "".as_ptr();
@@ -13,7 +12,6 @@ fn test_format_flags() {
 }
 
 #[test]
-#[cfg(not(miri))] // Miri cannot print pointers
 fn test_pointer_formats_data_pointer() {
     let b: &[u8] = b"";
     let s: &str = "";
diff --git a/src/libcore/tests/pattern.rs b/src/libcore/tests/pattern.rs
index b78ed021077..06c3a78c169 100644
--- a/src/libcore/tests/pattern.rs
+++ b/src/libcore/tests/pattern.rs
@@ -5,7 +5,7 @@ use std::str::pattern::*;
 macro_rules! search_asserts {
     ($haystack:expr, $needle:expr, $testname:expr, [$($func:ident),*], $result:expr) => {
         let mut searcher = $needle.into_searcher($haystack);
-        let arr = [$( Step::from(searcher.$func()) ),+];
+        let arr = [$( Step::from(searcher.$func()) ),*];
         assert_eq!(&arr[..], &$result, $testname);
     }
 }
diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs
index 03fe1fe5a7c..569b3197d09 100644
--- a/src/libcore/tests/ptr.rs
+++ b/src/libcore/tests/ptr.rs
@@ -253,7 +253,6 @@ fn test_unsized_nonnull() {
 
 #[test]
 #[allow(warnings)]
-#[cfg(not(miri))] // Miri cannot hash pointers
 // Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
 // ABI, or even point to an actual executable code, because the function itself is never invoked.
 #[no_mangle]
@@ -293,7 +292,7 @@ fn write_unaligned_drop() {
 }
 
 #[test]
-#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
+#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
 fn align_offset_zst() {
     // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
     // all, because no amount of elements will align the pointer.
@@ -308,7 +307,7 @@ fn align_offset_zst() {
 }
 
 #[test]
-#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
+#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
 fn align_offset_stride1() {
     // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
     // number of bytes.
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 03e65d2fe0b..42ec9d451f7 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -276,6 +276,25 @@ fn test_chunks_exact_nth() {
 }
 
 #[test]
+fn test_chunks_exact_nth_back() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let mut c = v.chunks_exact(2);
+    assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
+    assert_eq!(c.next().unwrap(), &[0, 1]);
+    assert_eq!(c.next(), None);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let mut c2 = v2.chunks_exact(3);
+    assert_eq!(c2.nth_back(0).unwrap(), &[0, 1, 2]);
+    assert_eq!(c2.next(), None);
+    assert_eq!(c2.next_back(), None);
+
+    let v3: &[i32] = &[0, 1, 2, 3, 4];
+    let mut c3 = v3.chunks_exact(10);
+    assert_eq!(c3.nth_back(0), None);
+}
+
+#[test]
 fn test_chunks_exact_last() {
     let v: &[i32] = &[0, 1, 2, 3, 4, 5];
     let c = v.chunks_exact(2);
@@ -1396,7 +1415,7 @@ pub mod memchr {
 }
 
 #[test]
-#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
+#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
 fn test_align_to_simple() {
     let bytes = [1u8, 2, 3, 4, 5, 6, 7];
     let (prefix, aligned, suffix) = unsafe { bytes.align_to::<u16>() };
@@ -1420,7 +1439,7 @@ fn test_align_to_zst() {
 }
 
 #[test]
-#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
+#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
 fn test_align_to_non_trivial() {
     #[repr(align(8))] struct U64(u64, u64);
     #[repr(align(8))] struct U64U64U32(u64, u64, u32);