Auto merge of #57830 - Centril:rollup, r=Centril

Rollup of 9 pull requests

Successful merges:

 - #57537 (Small perf improvement for fmt)
 - #57552 (Default images)
 - #57604 (Make `str` indexing generic on `SliceIndex`.)
 - #57667 (Fix memory leak in P::filter_map)
 - #57677 (const_eval: Predetermine the layout of all locals when pushing a stack frame)
 - #57791 (Add regression test for #54582)
 - #57798 (Corrected spelling inconsistency)
 - #57809 (Add powerpc64-unknown-freebsd)
 - #57813 (fix validation range printing when encountering undef)

Failed merges:

r? @ghost
diff --git a/src/libcore/benches/fmt.rs b/src/libcore/benches/fmt.rs
new file mode 100644
index 0000000..92f10c7
--- /dev/null
+++ b/src/libcore/benches/fmt.rs
@@ -0,0 +1,110 @@
+use std::io::{self, Write as IoWrite};
+use std::fmt::{self, Write as FmtWrite};
+use test::Bencher;
+
+#[bench]
+fn write_vec_value(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = Vec::new();
+        for _ in 0..1000 {
+            mem.write_all("abc".as_bytes()).unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_vec_ref(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = Vec::new();
+        let wr = &mut mem as &mut dyn io::Write;
+        for _ in 0..1000 {
+            wr.write_all("abc".as_bytes()).unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_vec_macro1(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = Vec::new();
+        let wr = &mut mem as &mut dyn io::Write;
+        for _ in 0..1000 {
+            write!(wr, "abc").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_vec_macro2(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = Vec::new();
+        let wr = &mut mem as &mut dyn io::Write;
+        for _ in 0..1000 {
+            write!(wr, "{}", "abc").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_vec_macro_debug(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = Vec::new();
+        let wr = &mut mem as &mut dyn io::Write;
+        for _ in 0..1000 {
+            write!(wr, "{:?}", "☃").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_str_value(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = String::new();
+        for _ in 0..1000 {
+            mem.write_str("abc").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_str_ref(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = String::new();
+        let wr = &mut mem as &mut dyn fmt::Write;
+        for _ in 0..1000 {
+            wr.write_str("abc").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_str_macro1(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = String::new();
+        for _ in 0..1000 {
+            write!(mem, "abc").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_str_macro2(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = String::new();
+        let wr = &mut mem as &mut dyn fmt::Write;
+        for _ in 0..1000 {
+            write!(wr, "{}", "abc").unwrap();
+        }
+    });
+}
+
+#[bench]
+fn write_str_macro_debug(bh: &mut Bencher) {
+    bh.iter(|| {
+        let mut mem = String::new();
+        let wr = &mut mem as &mut dyn fmt::Write;
+        for _ in 0..1000 {
+            write!(wr, "{:?}", "☃").unwrap();
+        }
+    });
+}
diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs
index 5b4971c..48572af 100644
--- a/src/libcore/benches/lib.rs
+++ b/src/libcore/benches/lib.rs
@@ -11,3 +11,4 @@
 mod num;
 mod ops;
 mod slice;
+mod fmt;
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 5221d6f..935579f 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -1006,28 +1006,30 @@
         curarg: args.args.iter(),
     };
 
-    let mut pieces = args.pieces.iter();
+    let mut idx = 0;
 
     match args.fmt {
         None => {
             // We can use default formatting parameters for all arguments.
-            for (arg, piece) in args.args.iter().zip(pieces.by_ref()) {
+            for (arg, piece) in args.args.iter().zip(args.pieces.iter()) {
                 formatter.buf.write_str(*piece)?;
                 (arg.formatter)(arg.value, &mut formatter)?;
+                idx += 1;
             }
         }
         Some(fmt) => {
             // Every spec has a corresponding argument that is preceded by
             // a string piece.
-            for (arg, piece) in fmt.iter().zip(pieces.by_ref()) {
+            for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {
                 formatter.buf.write_str(*piece)?;
                 formatter.run(arg)?;
+                idx += 1;
             }
         }
     }
 
     // There can be only one trailing string piece left.
-    if let Some(piece) = pieces.next() {
+    if let Some(piece) = args.pieces.get(idx) {
         formatter.buf.write_str(*piece)?;
     }
 
diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs
index 6cfa367..d4ed861 100644
--- a/src/libcore/ops/index.rs
+++ b/src/libcore/ops/index.rs
@@ -51,21 +51,6 @@
 /// ```
 #[lang = "index"]
 #[rustc_on_unimplemented(
-    on(
-        _Self="&str",
-        note="you can use `.chars().nth()` or `.bytes().nth()`
-see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
-    ),
-    on(
-        _Self="str",
-        note="you can use `.chars().nth()` or `.bytes().nth()`
-see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
-    ),
-    on(
-        _Self="std::string::String",
-        note="you can use `.chars().nth()` or `.bytes().nth()`
-see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
-    ),
     message="the type `{Self}` cannot be indexed by `{Idx}`",
     label="`{Self}` cannot be indexed by `{Idx}`",
 )]
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index df4d97e..9f9515e 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -2383,7 +2383,6 @@
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
 impl<T, I> ops::Index<I> for [T]
     where I: SliceIndex<[T]>
 {
@@ -2396,7 +2395,6 @@
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
 impl<T, I> ops::IndexMut<I> for [T]
     where I: SliceIndex<[T]>
 {
@@ -2447,7 +2445,19 @@
 
 /// A helper trait used for indexing operations.
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
-#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
+#[rustc_on_unimplemented(
+    on(
+        T = "str",
+        label = "string indices are ranges of `usize`",
+    ),
+    on(
+        all(any(T = "str", T = "&str", T = "std::string::String"), _Self="{integer}"),
+        note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+    ),
+    message = "the type `{T}` cannot be indexed by `{Self}`",
+    label = "slice indices are of type `usize` or ranges of `usize`",
+)]
 pub trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
     /// The output type returned by methods.
     #[stable(feature = "slice_get_slice", since = "1.28.0")]
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index bdde187..1ee8b77 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1621,190 +1621,26 @@
         }
     }
 
-    /// Implements substring slicing with syntax `&self[begin .. end]`.
-    ///
-    /// Returns a slice of the given string from the byte range
-    /// [`begin`..`end`).
-    ///
-    /// This operation is `O(1)`.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `begin` or `end` does not point to the starting
-    /// byte offset of a character (as defined by `is_char_boundary`).
-    /// Requires that `begin <= end` and `end <= len` where `len` is the
-    /// length of the string.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    /// assert_eq!(&s[0 .. 1], "L");
-    ///
-    /// assert_eq!(&s[1 .. 9], "öwe 老");
-    ///
-    /// // these will panic:
-    /// // byte 2 lies within `ö`:
-    /// // &s[2 ..3];
-    ///
-    /// // byte 8 lies within `老`
-    /// // &s[1 .. 8];
-    ///
-    /// // byte 100 is outside the string
-    /// // &s[3 .. 100];
-    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl ops::Index<ops::Range<usize>> for str {
-        type Output = str;
+    impl<I> ops::Index<I> for str
+    where
+        I: SliceIndex<str>,
+    {
+        type Output = I::Output;
+
         #[inline]
-        fn index(&self, index: ops::Range<usize>) -> &str {
+        fn index(&self, index: I) -> &I::Output {
             index.index(self)
         }
     }
 
-    /// Implements mutable substring slicing with syntax
-    /// `&mut self[begin .. end]`.
-    ///
-    /// Returns a mutable slice of the given string from the byte range
-    /// [`begin`..`end`).
-    ///
-    /// This operation is `O(1)`.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `begin` or `end` does not point to the starting
-    /// byte offset of a character (as defined by `is_char_boundary`).
-    /// Requires that `begin <= end` and `end <= len` where `len` is the
-    /// length of the string.
-    #[stable(feature = "derefmut_for_string", since = "1.3.0")]
-    impl ops::IndexMut<ops::Range<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
-            index.index_mut(self)
-        }
-    }
-
-    /// Implements substring slicing with syntax `&self[.. end]`.
-    ///
-    /// Returns a slice of the string from the beginning to byte offset
-    /// `end`.
-    ///
-    /// Equivalent to `&self[0 .. end]`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl ops::Index<ops::RangeTo<usize>> for str {
-        type Output = str;
-
+    impl<I> ops::IndexMut<I> for str
+    where
+        I: SliceIndex<str>,
+    {
         #[inline]
-        fn index(&self, index: ops::RangeTo<usize>) -> &str {
-            index.index(self)
-        }
-    }
-
-    /// Implements mutable substring slicing with syntax `&mut self[.. end]`.
-    ///
-    /// Returns a mutable slice of the string from the beginning to byte offset
-    /// `end`.
-    ///
-    /// Equivalent to `&mut self[0 .. end]`.
-    #[stable(feature = "derefmut_for_string", since = "1.3.0")]
-    impl ops::IndexMut<ops::RangeTo<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
-            index.index_mut(self)
-        }
-    }
-
-    /// Implements substring slicing with syntax `&self[begin ..]`.
-    ///
-    /// Returns a slice of the string from byte offset `begin`
-    /// to the end of the string.
-    ///
-    /// Equivalent to `&self[begin .. len]`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl ops::Index<ops::RangeFrom<usize>> for str {
-        type Output = str;
-
-        #[inline]
-        fn index(&self, index: ops::RangeFrom<usize>) -> &str {
-            index.index(self)
-        }
-    }
-
-    /// Implements mutable substring slicing with syntax `&mut self[begin ..]`.
-    ///
-    /// Returns a mutable slice of the string from byte offset `begin`
-    /// to the end of the string.
-    ///
-    /// Equivalent to `&mut self[begin .. len]`.
-    #[stable(feature = "derefmut_for_string", since = "1.3.0")]
-    impl ops::IndexMut<ops::RangeFrom<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
-            index.index_mut(self)
-        }
-    }
-
-    /// Implements substring slicing with syntax `&self[..]`.
-    ///
-    /// Returns a slice of the whole string. This operation can
-    /// never panic.
-    ///
-    /// Equivalent to `&self[0 .. len]`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl ops::Index<ops::RangeFull> for str {
-        type Output = str;
-
-        #[inline]
-        fn index(&self, _index: ops::RangeFull) -> &str {
-            self
-        }
-    }
-
-    /// Implements mutable substring slicing with syntax `&mut self[..]`.
-    ///
-    /// Returns a mutable slice of the whole string. This operation can
-    /// never panic.
-    ///
-    /// Equivalent to `&mut self[0 .. len]`.
-    #[stable(feature = "derefmut_for_string", since = "1.3.0")]
-    impl ops::IndexMut<ops::RangeFull> for str {
-        #[inline]
-        fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
-            self
-        }
-    }
-
-    #[stable(feature = "inclusive_range", since = "1.26.0")]
-    impl ops::Index<ops::RangeInclusive<usize>> for str {
-        type Output = str;
-
-        #[inline]
-        fn index(&self, index: ops::RangeInclusive<usize>) -> &str {
-            index.index(self)
-        }
-    }
-
-    #[stable(feature = "inclusive_range", since = "1.26.0")]
-    impl ops::Index<ops::RangeToInclusive<usize>> for str {
-        type Output = str;
-
-        #[inline]
-        fn index(&self, index: ops::RangeToInclusive<usize>) -> &str {
-            index.index(self)
-        }
-    }
-
-    #[stable(feature = "inclusive_range", since = "1.26.0")]
-    impl ops::IndexMut<ops::RangeInclusive<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut str {
-            index.index_mut(self)
-        }
-    }
-    #[stable(feature = "inclusive_range", since = "1.26.0")]
-    impl ops::IndexMut<ops::RangeToInclusive<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &mut str {
+        fn index_mut(&mut self, index: I) -> &mut I::Output {
             index.index_mut(self)
         }
     }
@@ -1815,6 +1651,18 @@
         panic!("attempted to index str up to maximum usize");
     }
 
+    /// Implements substring slicing with syntax `&self[..]` or `&mut self[..]`.
+    ///
+    /// Returns a slice of the whole string, i.e., returns `&self` or `&mut
+    /// self`. Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. Unlike
+    /// other indexing operations, this can never panic.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Prior to 1.20.0, these indexing operations were still supported by
+    /// direct implementation of `Index` and `IndexMut`.
+    ///
+    /// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`.
     #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     impl SliceIndex<str> for ops::RangeFull {
         type Output = str;
@@ -1844,6 +1692,41 @@
         }
     }
 
+    /// Implements substring slicing with syntax `&self[begin .. end]` or `&mut
+    /// self[begin .. end]`.
+    ///
+    /// Returns a slice of the given string from the byte range
+    /// [`begin`, `end`).
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Prior to 1.20.0, these indexing operations were still supported by
+    /// direct implementation of `Index` and `IndexMut`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `begin` or `end` does not point to the starting byte offset of
+    /// a character (as defined by `is_char_boundary`), if `begin > end`, or if
+    /// `end > len`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    /// assert_eq!(&s[0 .. 1], "L");
+    ///
+    /// assert_eq!(&s[1 .. 9], "öwe 老");
+    ///
+    /// // these will panic:
+    /// // byte 2 lies within `ö`:
+    /// // &s[2 ..3];
+    ///
+    /// // byte 8 lies within `老`
+    /// // &s[1 .. 8];
+    ///
+    /// // byte 100 is outside the string
+    /// // &s[3 .. 100];
+    /// ```
     #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     impl SliceIndex<str> for ops::Range<usize> {
         type Output = str;
@@ -1898,6 +1781,21 @@
         }
     }
 
+    /// Implements substring slicing with syntax `&self[.. end]` or `&mut
+    /// self[.. end]`.
+    ///
+    /// Returns a slice of the given string from the byte range [`0`, `end`).
+    /// Equivalent to `&self[0 .. end]` or `&mut self[0 .. end]`.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Prior to 1.20.0, these indexing operations were still supported by
+    /// direct implementation of `Index` and `IndexMut`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `end` does not point to the starting byte offset of a
+    /// character (as defined by `is_char_boundary`), or if `end > len`.
     #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     impl SliceIndex<str> for ops::RangeTo<usize> {
         type Output = str;
@@ -1943,6 +1841,22 @@
         }
     }
 
+    /// Implements substring slicing with syntax `&self[begin ..]` or `&mut
+    /// self[begin ..]`.
+    ///
+    /// Returns a slice of the given string from the byte range [`begin`,
+    /// `len`). Equivalent to `&self[begin .. len]` or `&mut self[begin ..
+    /// len]`.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Prior to 1.20.0, these indexing operations were still supported by
+    /// direct implementation of `Index` and `IndexMut`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `begin` does not point to the starting byte offset of
+    /// a character (as defined by `is_char_boundary`), or if `begin >= len`.
     #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     impl SliceIndex<str> for ops::RangeFrom<usize> {
         type Output = str;
@@ -1990,6 +1904,22 @@
         }
     }
 
+    /// Implements substring slicing with syntax `&self[begin ..= end]` or `&mut
+    /// self[begin ..= end]`.
+    ///
+    /// Returns a slice of the given string from the byte range
+    /// [`begin`, `end`]. Equivalent to `&self [begin .. end + 1]` or `&mut
+    /// self[begin .. end + 1]`, except if `end` has the maximum value for
+    /// `usize`.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `begin` does not point to the starting byte offset of
+    /// a character (as defined by `is_char_boundary`), if `end` does not point
+    /// to the ending byte offset of a character (`end + 1` is either a starting
+    /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`.
     #[stable(feature = "inclusive_range", since = "1.26.0")]
     impl SliceIndex<str> for ops::RangeInclusive<usize> {
         type Output = str;
@@ -2023,8 +1953,20 @@
         }
     }
 
-
-
+    /// Implements substring slicing with syntax `&self[..= end]` or `&mut
+    /// self[..= end]`.
+    ///
+    /// Returns a slice of the given string from the byte range [0, `end`].
+    /// Equivalent to `&self [0 .. end + 1]`, except if `end` has the maximum
+    /// value for `usize`.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `end` does not point to the ending byte offset of a character
+    /// (`end + 1` is either a starting byte offset as defined by
+    /// `is_char_boundary`, or equal to `len`), or if `end >= len`.
     #[stable(feature = "inclusive_range", since = "1.26.0")]
     impl SliceIndex<str> for ops::RangeToInclusive<usize> {
         type Output = str;
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index 32ae878..da440cd 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -72,6 +72,15 @@
     ArgumentNamed(&'a str),
 }
 
+impl Position<'_> {
+    pub fn index(&self) -> Option<usize> {
+        match self {
+            ArgumentIs(i) | ArgumentImplicitlyIs(i) => Some(*i),
+            _ => None,
+        }
+    }
+}
+
 /// Enum of alignments which are supported.
 #[derive(Copy, Clone, PartialEq)]
 pub enum Alignment {
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index f7af135..905a3ce 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1931,7 +1931,7 @@
 
     fn lower_parenthesized_parameter_data(
         &mut self,
-        data: &ParenthesisedArgs,
+        data: &ParenthesizedArgs,
     ) -> (hir::GenericArgs, bool) {
         // Switch to `PassThrough` mode for anonymous lifetimes: this
         // means that we permit things like `&Ref<T>`, where `Ref` has
@@ -1941,7 +1941,7 @@
         self.with_anonymous_lifetime_mode(
             AnonymousLifetimeMode::PassThrough,
             |this| {
-                let &ParenthesisedArgs { ref inputs, ref output, span } = data;
+                let &ParenthesizedArgs { ref inputs, ref output, span } = data;
                 let inputs = inputs
                     .iter()
                     .map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed()))
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index f5f4048..105856f 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -72,6 +72,7 @@
     ecx.stack.push(interpret::Frame {
         block: mir::START_BLOCK,
         locals: IndexVec::new(),
+        local_layouts: IndexVec::new(),
         instance,
         span,
         mir,
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 19362b6..b2d3328 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -1,3 +1,4 @@
+use std::cell::Cell;
 use std::fmt::Write;
 use std::mem;
 
@@ -76,6 +77,7 @@
     /// `None` represents a local that is currently dead, while a live local
     /// can either directly contain `Scalar` or refer to some part of an `Allocation`.
     pub locals: IndexVec<mir::Local, LocalValue<Tag>>,
+    pub local_layouts: IndexVec<mir::Local, Cell<Option<TyLayout<'tcx>>>>,
 
     ////////////////////////////////////////////////////////////////////////////////
     // Current position within the function
@@ -290,9 +292,15 @@
         frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
         local: mir::Local
     ) -> EvalResult<'tcx, TyLayout<'tcx>> {
-        let local_ty = frame.mir.local_decls[local].ty;
-        let local_ty = self.monomorphize(local_ty, frame.instance.substs);
-        self.layout_of(local_ty)
+        let cell = &frame.local_layouts[local];
+        if cell.get().is_none() {
+            let local_ty = frame.mir.local_decls[local].ty;
+            let local_ty = self.monomorphize(local_ty, frame.instance.substs);
+            let layout = self.layout_of(local_ty)?;
+            cell.set(Some(layout));
+        }
+
+        Ok(cell.get().unwrap())
     }
 
     pub fn str_to_immediate(&mut self, s: &str) -> EvalResult<'tcx, Immediate<M::PointerTag>> {
@@ -426,6 +434,7 @@
             // empty local array, we fill it in below, after we are inside the stack frame and
             // all methods actually know about the frame
             locals: IndexVec::new(),
+            local_layouts: IndexVec::from_elem_n(Default::default(), mir.local_decls.len()),
             span,
             instance,
             stmt: 0,
@@ -464,11 +473,11 @@
                 },
             }
             // Finally, properly initialize all those that still have the dummy value
-            for (local, decl) in locals.iter_mut().zip(mir.local_decls.iter()) {
+            for (idx, local) in locals.iter_enumerated_mut() {
                 match *local {
                     LocalValue::Live(_) => {
                         // This needs to be peoperly initialized.
-                        let layout = self.layout_of(self.monomorphize(decl.ty, instance.substs))?;
+                        let layout = self.layout_of_local(self.frame(), idx)?;
                         *local = LocalValue::Live(self.uninit_operand(layout)?);
                     }
                     LocalValue::Dead => {
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 04e0955..b264848 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -457,36 +457,30 @@
     }
 
     /// This is used by [priroda](https://github.com/oli-obk/priroda) to get an OpTy from a local
-    ///
-    /// When you know the layout of the local in advance, you can pass it as last argument
-    pub fn access_local(
+    fn access_local(
         &self,
         frame: &super::Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
         local: mir::Local,
-        layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         assert_ne!(local, mir::RETURN_PLACE);
         let op = *frame.locals[local].access()?;
-        let layout = from_known_layout(layout,
-                    || self.layout_of_local(frame, local))?;
+        let layout = self.layout_of_local(frame, local)?;
         Ok(OpTy { op, layout })
     }
 
     // Evaluate a place with the goal of reading from it.  This lets us sometimes
-    // avoid allocations.  If you already know the layout, you can pass it in
-    // to avoid looking it up again.
+    // avoid allocations.
     fn eval_place_to_op(
         &self,
         mir_place: &mir::Place<'tcx>,
-        layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
         let op = match *mir_place {
             Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
-            Local(local) => self.access_local(self.frame(), local, layout)?,
+            Local(local) => self.access_local(self.frame(), local)?,
 
             Projection(ref proj) => {
-                let op = self.eval_place_to_op(&proj.base, None)?;
+                let op = self.eval_place_to_op(&proj.base)?;
                 self.operand_projection(op, &proj.elem)?
             }
 
@@ -510,7 +504,7 @@
             // FIXME: do some more logic on `move` to invalidate the old location
             Copy(ref place) |
             Move(ref place) =>
-                self.eval_place_to_op(place, layout)?,
+                self.eval_place_to_op(place)?,
 
             Constant(ref constant) => {
                 let layout = from_known_layout(layout, || {
diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs
index f9ce7b4..5310526 100644
--- a/src/librustc_mir/interpret/snapshot.rs
+++ b/src/librustc_mir/interpret/snapshot.rs
@@ -314,13 +314,14 @@
     stmt: usize,
 }
 
-impl_stable_hash_for!(impl<'tcx, 'mir: 'tcx> for struct Frame<'mir, 'tcx> {
+impl_stable_hash_for!(impl<'mir, 'tcx: 'mir> for struct Frame<'mir, 'tcx> {
     mir,
     instance,
     span,
     return_to_block,
     return_place -> (return_place.as_ref().map(|r| &**r)),
     locals,
+    local_layouts -> _,
     block,
     stmt,
     extra,
@@ -339,6 +340,7 @@
             return_to_block,
             return_place,
             locals,
+            local_layouts: _,
             block,
             stmt,
             extra: _,
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index a5fb445..8f5a5bf 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -449,8 +449,13 @@
         }
         // At least one value is excluded. Get the bits.
         let value = try_validation!(value.not_undef(),
-            value, self.path,
-            format!("something in the range {:?}", layout.valid_range));
+            value,
+            self.path,
+            format!(
+                "something {}",
+                wrapping_range_format(&layout.valid_range, max_hi),
+            )
+        );
         let bits = match value {
             Scalar::Ptr(ptr) => {
                 if lo == 1 && hi == max_hi {
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 3a21ca1..e47da3c 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -367,6 +367,7 @@
 
     ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
     ("i686-unknown-freebsd", i686_unknown_freebsd),
+    ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
     ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
 
     ("i686-unknown-dragonfly", i686_unknown_dragonfly),
diff --git a/src/librustc_target/spec/powerpc64_unknown_freebsd.rs b/src/librustc_target/spec/powerpc64_unknown_freebsd.rs
new file mode 100644
index 0000000..cc7b87b
--- /dev/null
+++ b/src/librustc_target/spec/powerpc64_unknown_freebsd.rs
@@ -0,0 +1,22 @@
+use spec::{LinkerFlavor, Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::freebsd_base::opts();
+    base.cpu = "ppc64".to_string();
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
+    base.max_atomic_width = Some(64);
+
+    Ok(Target {
+        llvm_target: "powerpc64-unknown-freebsd".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64".to_string(),
+        arch: "powerpc64".to_string(),
+        target_os: "freebsd".to_string(),
+        target_env: String::new(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 987cec6..c34dcbb 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -177,7 +177,10 @@
     root_path = page.root_path,
     css_class = page.css_class,
     logo      = if layout.logo.is_empty() {
-        String::new()
+        format!("<a href='{}{}/index.html'>\
+                 <img src='{static_root_path}rust-logo{suffix}.png' alt='logo' width='100'></a>",
+                static_root_path=static_root_path,
+                suffix=page.resource_suffix)
     } else {
         format!("<a href='{}{}/index.html'>\
                  <img src='{}' alt='logo' width='100'></a>",
@@ -188,7 +191,9 @@
     description = page.description,
     keywords = page.keywords,
     favicon   = if layout.favicon.is_empty() {
-        String::new()
+        format!(r#"<link rel="shortcut icon" href="{static_root_path}favicon{suffix}.ico">"#,
+                static_root_path=static_root_path,
+                suffix=page.resource_suffix)
     } else {
         format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
     },
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index ad1659b..86fb514 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -789,6 +789,14 @@
         themes.insert(theme.to_owned());
     }
 
+    if (*cx.shared).layout.logo.is_empty() {
+        write(cx.dst.join(&format!("rust-logo{}.png", cx.shared.resource_suffix)),
+              static_files::RUST_LOGO)?;
+    }
+    if (*cx.shared).layout.favicon.is_empty() {
+        write(cx.dst.join(&format!("favicon{}.ico", cx.shared.resource_suffix)),
+              static_files::RUST_FAVICON)?;
+    }
     write(cx.dst.join(&format!("brush{}.svg", cx.shared.resource_suffix)),
           static_files::BRUSH_SVG)?;
     write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)),
@@ -2068,8 +2076,6 @@
         themes.push(PathBuf::from("settings.css"));
         let mut layout = self.shared.layout.clone();
         layout.krate = String::new();
-        layout.logo = String::new();
-        layout.favicon = String::new();
         try_err!(layout::render(&mut w, &layout,
                                 &page, &sidebar, &settings,
                                 self.shared.css_file_extension.is_some(),
diff --git a/src/librustdoc/html/static/favicon.ico b/src/librustdoc/html/static/favicon.ico
new file mode 100644
index 0000000..b8ad237
--- /dev/null
+++ b/src/librustdoc/html/static/favicon.ico
Binary files differ
diff --git a/src/librustdoc/html/static/rust-logo.png b/src/librustdoc/html/static/rust-logo.png
new file mode 100644
index 0000000..74b4bd6
--- /dev/null
+++ b/src/librustdoc/html/static/rust-logo.png
Binary files differ
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index f340590..a1d8cfa 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -51,6 +51,11 @@
 /// The contents of `LICENSE-MIT.txt`, the text of the MIT License.
 pub static LICENSE_MIT: &'static [u8] = include_bytes!("static/LICENSE-MIT.txt");
 
+/// The contents of `rust-logo.png`, the default icon of the documentation.
+pub static RUST_LOGO: &'static [u8] = include_bytes!("static/rust-logo.png");
+/// The contents of `favicon.ico`, the default favicon of the documentation.
+pub static RUST_FAVICON: &'static [u8] = include_bytes!("static/favicon.ico");
+
 /// The built-in themes given to every documentation site.
 pub mod themes {
     /// The "light" theme, selected by default when no setting is available. Used as the basis for
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 405cf61..798f14d 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -136,7 +136,7 @@
     /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>`
     AngleBracketed(AngleBracketedArgs),
     /// The `(A,B)` and `C` in `Foo(A,B) -> C`
-    Parenthesized(ParenthesisedArgs),
+    Parenthesized(ParenthesizedArgs),
 }
 
 impl GenericArgs {
@@ -173,7 +173,7 @@
     }
 }
 
-impl Into<Option<P<GenericArgs>>> for ParenthesisedArgs {
+impl Into<Option<P<GenericArgs>>> for ParenthesizedArgs {
     fn into(self) -> Option<P<GenericArgs>> {
         Some(P(GenericArgs::Parenthesized(self)))
     }
@@ -181,7 +181,7 @@
 
 /// A path like `Foo(A,B) -> C`
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct ParenthesisedArgs {
+pub struct ParenthesizedArgs {
     /// Overall span
     pub span: Span,
 
@@ -192,7 +192,7 @@
     pub output: Option<P<Ty>>,
 }
 
-impl ParenthesisedArgs {
+impl ParenthesizedArgs {
     pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs {
         AngleBracketedArgs {
             span: self.span,
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index a4c3b38..fdcbbb9 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -207,8 +207,8 @@
         noop_fold_angle_bracketed_parameter_data(p, self)
     }
 
-    fn fold_parenthesized_parameter_data(&mut self, p: ParenthesisedArgs)
-                                         -> ParenthesisedArgs
+    fn fold_parenthesized_parameter_data(&mut self, p: ParenthesizedArgs)
+                                         -> ParenthesizedArgs
     {
         noop_fold_parenthesized_parameter_data(p, self)
     }
@@ -504,12 +504,12 @@
     }
 }
 
-pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesisedArgs,
+pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedArgs,
                                                          fld: &mut T)
-                                                         -> ParenthesisedArgs
+                                                         -> ParenthesizedArgs
 {
-    let ParenthesisedArgs { inputs, output, span } = data;
-    ParenthesisedArgs {
+    let ParenthesizedArgs { inputs, output, span } = data;
+    ParenthesizedArgs {
         inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
         output: output.map(|ty| fld.fold_ty(ty)),
         span: fld.new_span(span)
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 439eec5..09ea099 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1,5 +1,5 @@
 use rustc_target::spec::abi::{self, Abi};
-use ast::{AngleBracketedArgs, ParenthesisedArgs, AttrStyle, BareFnTy};
+use ast::{AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy};
 use ast::{GenericBound, TraitBoundModifier};
 use ast::Unsafety;
 use ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind};
@@ -2203,7 +2203,7 @@
                 } else {
                     None
                 };
-                ParenthesisedArgs { inputs, output, span }.into()
+                ParenthesizedArgs { inputs, output, span }.into()
             };
 
             PathSegment { ident, args, id: ast::DUMMY_NODE_ID }
diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs
index bb1744e..3effe53 100644
--- a/src/libsyntax/ptr.rs
+++ b/src/libsyntax/ptr.rs
@@ -101,6 +101,7 @@
                 // Recreate self from the raw pointer.
                 Some(P { ptr: Box::from_raw(p) })
             } else {
+                drop(Box::from_raw(p));
                 None
             }
         }
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 3e3bca7..215df42 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -493,7 +493,10 @@
 
                 let fill = arg.format.fill.unwrap_or(' ');
 
-                if *arg != simple_arg || fill != ' ' {
+                let pos_simple =
+                    arg.position.index() == simple_arg.position.index();
+
+                if !pos_simple || arg.format != simple_arg.format || fill != ' ' {
                     self.all_pieces_simple = false;
                 }
 
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs
index 7fbcab8..3e0b094 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.rs
+++ b/src/test/ui/consts/const-eval/ub-nonnull.rs
@@ -13,6 +13,13 @@
 const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
 //~^ ERROR it is undefined behavior to use this value
 
+union Transmute {
+    uninit: (),
+    out: NonZeroU8,
+}
+const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
+//~^ ERROR it is undefined behavior to use this value
+
 // Also test other uses of rustc_layout_scalar_valid_range_start
 
 #[rustc_layout_scalar_valid_range_start(10)]
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr
index 5f8e0c7..6230712 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr
@@ -23,7 +23,15 @@
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:21:1
+  --> $DIR/ub-nonnull.rs:20:1
+   |
+LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected something greater or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-nonnull.rs:28:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
@@ -31,13 +39,13 @@
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:27:1
+  --> $DIR/ub-nonnull.rs:34:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/index-help.stderr b/src/test/ui/index-help.stderr
index c8b23d8..4c585a9 100644
--- a/src/test/ui/index-help.stderr
+++ b/src/test/ui/index-help.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `i32: std::slice::SliceIndex<[{integer}]>` is not satisfied
+error[E0277]: the type `[{integer}]` cannot be indexed by `i32`
   --> $DIR/index-help.rs:3:5
    |
 LL |     x[0i32]; //~ ERROR E0277
diff --git a/src/test/ui/indexing-requires-a-uint.rs b/src/test/ui/indexing-requires-a-uint.rs
index 2db3c58..dbe9b44 100644
--- a/src/test/ui/indexing-requires-a-uint.rs
+++ b/src/test/ui/indexing-requires-a-uint.rs
@@ -3,7 +3,7 @@
 
 fn main() {
     fn bar<T>(_: T) {}
-    [0][0u8]; //~ ERROR: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not satisfied
+    [0][0u8]; //~ ERROR: the type `[{integer}]` cannot be indexed by `u8`
 
     [0][0]; // should infer to be a usize
 
diff --git a/src/test/ui/indexing-requires-a-uint.stderr b/src/test/ui/indexing-requires-a-uint.stderr
index 767f1af..363c3d0 100644
--- a/src/test/ui/indexing-requires-a-uint.stderr
+++ b/src/test/ui/indexing-requires-a-uint.stderr
@@ -1,7 +1,7 @@
-error[E0277]: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not satisfied
+error[E0277]: the type `[{integer}]` cannot be indexed by `u8`
   --> $DIR/indexing-requires-a-uint.rs:6:5
    |
-LL |     [0][0u8]; //~ ERROR: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not satisfied
+LL |     [0][0u8]; //~ ERROR: the type `[{integer}]` cannot be indexed by `u8`
    |     ^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `u8`
diff --git a/src/test/ui/integral-indexing.rs b/src/test/ui/integral-indexing.rs
index 7bdbc45..f076dfc 100644
--- a/src/test/ui/integral-indexing.rs
+++ b/src/test/ui/integral-indexing.rs
@@ -3,14 +3,14 @@
     let s: String = "abcdef".to_string();
     v[3_usize];
     v[3];
-    v[3u8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
-    v[3i8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
-    v[3u32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
-    v[3i32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+    v[3u8];  //~ERROR : the type `[isize]` cannot be indexed by `u8`
+    v[3i8];  //~ERROR : the type `[isize]` cannot be indexed by `i8`
+    v[3u32]; //~ERROR : the type `[isize]` cannot be indexed by `u32`
+    v[3i32]; //~ERROR : the type `[isize]` cannot be indexed by `i32`
     s.as_bytes()[3_usize];
     s.as_bytes()[3];
-    s.as_bytes()[3u8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
-    s.as_bytes()[3i8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
-    s.as_bytes()[3u32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
-    s.as_bytes()[3i32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+    s.as_bytes()[3u8];  //~ERROR : the type `[u8]` cannot be indexed by `u8`
+    s.as_bytes()[3i8];  //~ERROR : the type `[u8]` cannot be indexed by `i8`
+    s.as_bytes()[3u32]; //~ERROR : the type `[u8]` cannot be indexed by `u32`
+    s.as_bytes()[3i32]; //~ERROR : the type `[u8]` cannot be indexed by `i32`
 }
diff --git a/src/test/ui/integral-indexing.stderr b/src/test/ui/integral-indexing.stderr
index 7f2dddc..efbad86 100644
--- a/src/test/ui/integral-indexing.stderr
+++ b/src/test/ui/integral-indexing.stderr
@@ -1,70 +1,70 @@
-error[E0277]: the trait bound `u8: std::slice::SliceIndex<[isize]>` is not satisfied
+error[E0277]: the type `[isize]` cannot be indexed by `u8`
   --> $DIR/integral-indexing.rs:6:5
    |
-LL |     v[3u8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+LL |     v[3u8];  //~ERROR : the type `[isize]` cannot be indexed by `u8`
    |     ^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `u8`
    = note: required because of the requirements on the impl of `std::ops::Index<u8>` for `std::vec::Vec<isize>`
 
-error[E0277]: the trait bound `i8: std::slice::SliceIndex<[isize]>` is not satisfied
+error[E0277]: the type `[isize]` cannot be indexed by `i8`
   --> $DIR/integral-indexing.rs:7:5
    |
-LL |     v[3i8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+LL |     v[3i8];  //~ERROR : the type `[isize]` cannot be indexed by `i8`
    |     ^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `i8`
    = note: required because of the requirements on the impl of `std::ops::Index<i8>` for `std::vec::Vec<isize>`
 
-error[E0277]: the trait bound `u32: std::slice::SliceIndex<[isize]>` is not satisfied
+error[E0277]: the type `[isize]` cannot be indexed by `u32`
   --> $DIR/integral-indexing.rs:8:5
    |
-LL |     v[3u32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+LL |     v[3u32]; //~ERROR : the type `[isize]` cannot be indexed by `u32`
    |     ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `u32`
    = note: required because of the requirements on the impl of `std::ops::Index<u32>` for `std::vec::Vec<isize>`
 
-error[E0277]: the trait bound `i32: std::slice::SliceIndex<[isize]>` is not satisfied
+error[E0277]: the type `[isize]` cannot be indexed by `i32`
   --> $DIR/integral-indexing.rs:9:5
    |
-LL |     v[3i32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+LL |     v[3i32]; //~ERROR : the type `[isize]` cannot be indexed by `i32`
    |     ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `i32`
    = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `std::vec::Vec<isize>`
 
-error[E0277]: the trait bound `u8: std::slice::SliceIndex<[u8]>` is not satisfied
+error[E0277]: the type `[u8]` cannot be indexed by `u8`
   --> $DIR/integral-indexing.rs:12:5
    |
-LL |     s.as_bytes()[3u8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+LL |     s.as_bytes()[3u8];  //~ERROR : the type `[u8]` cannot be indexed by `u8`
    |     ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `u8`
    = note: required because of the requirements on the impl of `std::ops::Index<u8>` for `[u8]`
 
-error[E0277]: the trait bound `i8: std::slice::SliceIndex<[u8]>` is not satisfied
+error[E0277]: the type `[u8]` cannot be indexed by `i8`
   --> $DIR/integral-indexing.rs:13:5
    |
-LL |     s.as_bytes()[3i8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+LL |     s.as_bytes()[3i8];  //~ERROR : the type `[u8]` cannot be indexed by `i8`
    |     ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `i8`
    = note: required because of the requirements on the impl of `std::ops::Index<i8>` for `[u8]`
 
-error[E0277]: the trait bound `u32: std::slice::SliceIndex<[u8]>` is not satisfied
+error[E0277]: the type `[u8]` cannot be indexed by `u32`
   --> $DIR/integral-indexing.rs:14:5
    |
-LL |     s.as_bytes()[3u32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+LL |     s.as_bytes()[3u32]; //~ERROR : the type `[u8]` cannot be indexed by `u32`
    |     ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `u32`
    = note: required because of the requirements on the impl of `std::ops::Index<u32>` for `[u8]`
 
-error[E0277]: the trait bound `i32: std::slice::SliceIndex<[u8]>` is not satisfied
+error[E0277]: the type `[u8]` cannot be indexed by `i32`
   --> $DIR/integral-indexing.rs:15:5
    |
-LL |     s.as_bytes()[3i32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+LL |     s.as_bytes()[3i32]; //~ERROR : the type `[u8]` cannot be indexed by `i32`
    |     ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `i32`
diff --git a/src/test/ui/issues/issue-54582.rs b/src/test/ui/issues/issue-54582.rs
new file mode 100644
index 0000000..c2dbf36
--- /dev/null
+++ b/src/test/ui/issues/issue-54582.rs
@@ -0,0 +1,16 @@
+// run-pass
+
+pub trait Stage: Sync {}
+
+pub enum Enum {
+    A,
+    B,
+}
+
+impl Stage for Enum {}
+
+pub static ARRAY: [(&Stage, &str); 1] = [
+    (&Enum::A, ""),
+];
+
+fn main() {}
diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr
index 3a32e13..7b45d84 100644
--- a/src/test/ui/on-unimplemented/slice-index.stderr
+++ b/src/test/ui/on-unimplemented/slice-index.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `i32: std::slice::SliceIndex<[i32]>` is not satisfied
+error[E0277]: the type `[i32]` cannot be indexed by `i32`
   --> $DIR/slice-index.rs:11:5
    |
 LL |     x[1i32]; //~ ERROR E0277
@@ -7,7 +7,7 @@
    = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32`
    = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `[i32]`
 
-error[E0277]: the trait bound `std::ops::RangeTo<i32>: std::slice::SliceIndex<[i32]>` is not satisfied
+error[E0277]: the type `[i32]` cannot be indexed by `std::ops::RangeTo<i32>`
   --> $DIR/slice-index.rs:12:5
    |
 LL |     x[..1i32]; //~ ERROR E0277
diff --git a/src/test/ui/parenthesised-deref-suggestion.rs b/src/test/ui/parenthesized-deref-suggestion.rs
similarity index 100%
rename from src/test/ui/parenthesised-deref-suggestion.rs
rename to src/test/ui/parenthesized-deref-suggestion.rs
diff --git a/src/test/ui/parenthesised-deref-suggestion.stderr b/src/test/ui/parenthesized-deref-suggestion.stderr
similarity index 88%
rename from src/test/ui/parenthesised-deref-suggestion.stderr
rename to src/test/ui/parenthesized-deref-suggestion.stderr
index 71a2bf6..fd9b0e8 100644
--- a/src/test/ui/parenthesised-deref-suggestion.stderr
+++ b/src/test/ui/parenthesized-deref-suggestion.stderr
@@ -1,5 +1,5 @@
 error[E0609]: no field `opts` on type `*const Session`
-  --> $DIR/parenthesised-deref-suggestion.rs:7:30
+  --> $DIR/parenthesized-deref-suggestion.rs:7:30
    |
 LL |     (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session`
    |                              ^^^^
@@ -9,7 +9,7 @@
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0609]: no field `0` on type `[u32; 1]`
-  --> $DIR/parenthesised-deref-suggestion.rs:10:21
+  --> $DIR/parenthesized-deref-suggestion.rs:10:21
    |
 LL |     (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]`
    |     ----------------^
diff --git a/src/test/ui/str/str-idx.rs b/src/test/ui/str/str-idx.rs
index 2ea8049..1b32ed5 100644
--- a/src/test/ui/str/str-idx.rs
+++ b/src/test/ui/str/str-idx.rs
@@ -1,4 +1,7 @@
 pub fn main() {
     let s: &str = "hello";
-    let c: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _ = s.get(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _ = s.get_unchecked(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _: u8 = s['c']; //~ ERROR the type `str` cannot be indexed by `char`
 }
diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr
index 71b1747..99df85d 100644
--- a/src/test/ui/str/str-idx.stderr
+++ b/src/test/ui/str/str-idx.stderr
@@ -1,13 +1,43 @@
 error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-idx.rs:3:17
    |
-LL |     let c: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
-   |                 ^^^^ `str` cannot be indexed by `{integer}`
+LL |     let _: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
+   |                 ^^^^ string indices are ranges of `usize`
    |
-   = help: the trait `std::ops::Index<{integer}>` is not implemented for `str`
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+   = note: required because of the requirements on the impl of `std::ops::Index<{integer}>` for `str`
+
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-idx.rs:4:15
+   |
+LL |     let _ = s.get(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+   |               ^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
 
-error: aborting due to previous error
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-idx.rs:5:15
+   |
+LL |     let _ = s.get_unchecked(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+   |               ^^^^^^^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+
+error[E0277]: the type `str` cannot be indexed by `char`
+  --> $DIR/str-idx.rs:6:17
+   |
+LL |     let _: u8 = s['c']; //~ ERROR the type `str` cannot be indexed by `char`
+   |                 ^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `char`
+   = note: required because of the requirements on the impl of `std::ops::Index<char>` for `str`
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/str/str-mut-idx.rs b/src/test/ui/str/str-mut-idx.rs
index cebbbc3..575a9ea 100644
--- a/src/test/ui/str/str-mut-idx.rs
+++ b/src/test/ui/str/str-mut-idx.rs
@@ -5,7 +5,13 @@
     //~^ ERROR the size for values of type
     //~| ERROR the size for values of type
     s[1usize] = bot();
-    //~^ ERROR the type `str` cannot be mutably indexed by `usize`
+    //~^ ERROR the type `str` cannot be indexed by `usize`
+    s.get_mut(1);
+    //~^ ERROR the type `str` cannot be indexed by `{integer}`
+    s.get_unchecked_mut(1);
+    //~^ ERROR the type `str` cannot be indexed by `{integer}`
+    s['c'];
+    //~^ ERROR the type `str` cannot be indexed by `char`
 }
 
 pub fn main() {}
diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr
index a1212c5..beb2272 100644
--- a/src/test/ui/str/str-mut-idx.stderr
+++ b/src/test/ui/str/str-mut-idx.stderr
@@ -22,16 +22,44 @@
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: the left-hand-side of an assignment must have a statically known size
 
-error[E0277]: the type `str` cannot be mutably indexed by `usize`
+error[E0277]: the type `str` cannot be indexed by `usize`
   --> $DIR/str-mut-idx.rs:7:5
    |
 LL |     s[1usize] = bot();
-   |     ^^^^^^^^^ `str` cannot be mutably indexed by `usize`
+   |     ^^^^^^^^^ string indices are ranges of `usize`
    |
-   = help: the trait `std::ops::IndexMut<usize>` is not implemented for `str`
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `usize`
+   = note: required because of the requirements on the impl of `std::ops::Index<usize>` for `str`
+
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-mut-idx.rs:9:7
+   |
+LL |     s.get_mut(1);
+   |       ^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
 
-error: aborting due to 3 previous errors
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-mut-idx.rs:11:7
+   |
+LL |     s.get_unchecked_mut(1);
+   |       ^^^^^^^^^^^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+
+error[E0277]: the type `str` cannot be indexed by `char`
+  --> $DIR/str-mut-idx.rs:13:5
+   |
+LL |     s['c'];
+   |     ^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `char`
+   = note: required because of the requirements on the impl of `std::ops::Index<char>` for `str`
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0277`.