about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/std/src/io/mod.rs27
-rw-r--r--library/std/src/lib.rs67
-rw-r--r--library/std/src/primitive_docs.rs8
-rw-r--r--library/std/src/sys/wasi/fs.rs8
-rw-r--r--library/std/src/time.rs8
-rw-r--r--src/librustc_ast_passes/ast_validation.rs2
-rw-r--r--src/librustc_codegen_llvm/back/write.rs1
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs16
-rw-r--r--src/librustc_codegen_ssa/common.rs3
-rw-r--r--src/librustc_error_codes/error_codes/E0751.md6
-rw-r--r--src/librustc_resolve/late/diagnostics.rs161
-rw-r--r--src/librustc_resolve/late/lifetimes.rs47
-rw-r--r--src/librustc_serialize/collection_impls.rs24
-rw-r--r--src/librustc_serialize/json.rs88
-rw-r--r--src/librustc_serialize/opaque.rs4
-rw-r--r--src/rustllvm/ArchiveWrapper.cpp1
-rw-r--r--src/rustllvm/PassWrapper.cpp2
-rw-r--r--src/rustllvm/RustWrapper.cpp2
-rw-r--r--src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr5
-rw-r--r--src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr5
-rw-r--r--src/test/ui/const-generics/defaults/needs-feature.min.stderr2
-rw-r--r--src/test/ui/error-codes/E0106.stderr9
-rw-r--r--src/test/ui/issues/issue-74739.rs14
-rw-r--r--src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr4
-rw-r--r--src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.rs16
-rw-r--r--src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr73
-rw-r--r--src/test/ui/suggestions/missing-lt-for-hrtb.rs15
-rw-r--r--src/test/ui/suggestions/missing-lt-for-hrtb.stderr63
28 files changed, 464 insertions, 217 deletions
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 9eb54c2cc00..e90ee5c285f 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1212,7 +1212,7 @@ impl Initializer {
 ///
 /// [`write`]: Self::write
 /// [`flush`]: Self::flush
-/// [`std::io`]: index.html
+/// [`std::io`]: self
 ///
 /// # Examples
 ///
@@ -1590,8 +1590,6 @@ pub trait Seek {
     /// # Errors
     ///
     /// Seeking to a negative offset is considered an error.
-    ///
-    /// [`SeekFrom::Start`]: enum.SeekFrom.html#variant.Start
     #[stable(feature = "rust1", since = "1.0.0")]
     fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
 
@@ -1678,8 +1676,6 @@ pub trait Seek {
 /// Enumeration of possible methods to seek within an I/O object.
 ///
 /// It is used by the [`Seek`] trait.
-///
-/// [`Seek`]: trait.Seek.html
 #[derive(Copy, PartialEq, Eq, Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum SeekFrom {
@@ -1759,11 +1755,9 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> R
 /// For example, [`File`] implements [`Read`], but not `BufRead`.
 /// [`BufReader`] to the rescue!
 ///
-/// [`BufReader`]: struct.BufReader.html
 /// [`File`]: crate::fs::File
 /// [`read_line`]: Self::read_line
 /// [`lines`]: Self::lines
-/// [`Read`]: trait.Read.html
 ///
 /// ```no_run
 /// use std::io::{self, BufReader};
@@ -1869,7 +1863,6 @@ pub trait BufRead: Read {
     /// present in `buf` and its length will have been adjusted appropriately.
     ///
     /// [`fill_buf`]: Self::fill_buf
-    /// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted
     ///
     /// # Examples
     ///
@@ -1877,8 +1870,6 @@ pub trait BufRead: Read {
     /// this example, we use [`Cursor`] to read all the bytes in a byte slice
     /// in hyphen delimited segments:
     ///
-    /// [`Cursor`]: struct.Cursor.html
-    ///
     /// ```
     /// use std::io::{self, BufRead};
     ///
@@ -1940,8 +1931,6 @@ pub trait BufRead: Read {
     /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
     /// this example, we use [`Cursor`] to read all the lines in a byte slice:
     ///
-    /// [`Cursor`]: struct.Cursor.html
-    ///
     /// ```
     /// use std::io::{self, BufRead};
     ///
@@ -1996,8 +1985,6 @@ pub trait BufRead: Read {
     /// this example, we use [`Cursor`] to iterate over all hyphen delimited
     /// segments in a byte slice
     ///
-    /// [`Cursor`]: struct.Cursor.html
-    ///
     /// ```
     /// use std::io::{self, BufRead};
     ///
@@ -2046,8 +2033,6 @@ pub trait BufRead: Read {
     /// # Errors
     ///
     /// Each line of the iterator has the same error semantics as [`BufRead::read_line`].
-    ///
-    /// [`BufRead::read_line`]: trait.BufRead.html#method.read_line
     #[stable(feature = "rust1", since = "1.0.0")]
     fn lines(self) -> Lines<Self>
     where
@@ -2062,7 +2047,7 @@ pub trait BufRead: Read {
 /// This struct is generally created by calling [`chain`] on a reader.
 /// Please see the documentation of [`chain`] for more details.
 ///
-/// [`chain`]: trait.Read.html#method.chain
+/// [`chain`]: Read::chain
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chain<T, U> {
     first: T,
@@ -2204,7 +2189,7 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
 /// This struct is generally created by calling [`take`] on a reader.
 /// Please see the documentation of [`take`] for more details.
 ///
-/// [`take`]: trait.Read.html#method.take
+/// [`take`]: Read::take
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Take<T> {
@@ -2403,7 +2388,7 @@ impl<T: BufRead> BufRead for Take<T> {
 /// This struct is generally created by calling [`bytes`] on a reader.
 /// Please see the documentation of [`bytes`] for more details.
 ///
-/// [`bytes`]: trait.Read.html#method.bytes
+/// [`bytes`]: Read::bytes
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Bytes<R> {
@@ -2433,7 +2418,7 @@ impl<R: Read> Iterator for Bytes<R> {
 /// This struct is generally created by calling [`split`] on a `BufRead`.
 /// Please see the documentation of [`split`] for more details.
 ///
-/// [`split`]: trait.BufRead.html#method.split
+/// [`split`]: BufRead::split
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Split<B> {
@@ -2465,7 +2450,7 @@ impl<B: BufRead> Iterator for Split<B> {
 /// This struct is generally created by calling [`lines`] on a `BufRead`.
 /// Please see the documentation of [`lines`] for more details.
 ///
-/// [`lines`]: trait.BufRead.html#method.lines
+/// [`lines`]: BufRead::lines
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Lines<B> {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index f0487e0dff1..1144a13b52c 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -22,7 +22,7 @@
 //! * [`std::*` modules](#modules)
 //! * [Primitive types](#primitives)
 //! * [Standard macros](#macros)
-//! * [The Rust Prelude](prelude/index.html)
+//! * [The Rust Prelude]
 //!
 //! If this is your first time, the documentation for the standard library is
 //! written to be casually perused. Clicking on interesting things should
@@ -63,8 +63,8 @@
 //! So for example there is a [page for the primitive type
 //! `i32`](primitive.i32.html) that lists all the methods that can be called on
 //! 32-bit integers (very useful), and there is a [page for the module
-//! `std::i32`](i32/index.html) that documents the constant values [`MIN`] and
-//! [`MAX`](i32/constant.MAX.html) (rarely useful).
+//! `std::i32`] that documents the constant values [`MIN`] and [`MAX`] (rarely
+//! useful).
 //!
 //! Note the documentation for the primitives [`str`] and [`[T]`][slice] (also
 //! called 'slice'). Many method calls on [`String`] and [`Vec<T>`] are actually
@@ -152,48 +152,35 @@
 //! contains further primitive shared memory types, including [`atomic`] and
 //! [`mpsc`], which contains the channel types for message passing.
 //!
-//! [I/O]: io/index.html
-//! [`MIN`]: i32/constant.MIN.html
-//! [TCP]: net/struct.TcpStream.html
-//! [The Rust Prelude]: prelude/index.html
-//! [UDP]: net/struct.UdpSocket.html
-//! [`Arc`]: sync/struct.Arc.html
-//! [owned slice]: boxed/index.html
-//! [`Cell`]: cell/struct.Cell.html
-//! [`FromStr`]: str/trait.FromStr.html
-//! [`HashMap<K, V>`]: collections/struct.HashMap.html
-//! [`Iterator`]: iter/trait.Iterator.html
-//! [`Mutex`]: sync/struct.Mutex.html
-//! [`Option<T>`]: option/enum.Option.html
-//! [`Rc`]: rc/struct.Rc.html
-//! [`RefCell`]: cell/struct.RefCell.html
-//! [`Result<T, E>`]: result/enum.Result.html
-//! [`String`]: string/struct.String.html
-//! [`Vec<T>`]: vec/struct.Vec.html
-//! [array]: primitive.array.html
-//! [slice]: primitive.slice.html
-//! [`atomic`]: sync/atomic/index.html
-//! [`collections`]: collections/index.html
+//! [I/O]: io
+//! [`MIN`]: i32::MIN
+//! [`MAX`]: i32::MAX
+//! [page for the module `std::i32`]: crate::i32
+//! [TCP]: net::TcpStream
+//! [The Rust Prelude]: prelude
+//! [UDP]: net::UdpSocket
+//! [`Arc`]: sync::Arc
+//! [owned slice]: boxed
+//! [`Cell`]: cell::Cell
+//! [`FromStr`]: str::FromStr
+//! [`HashMap<K, V>`]: collections::HashMap
+//! [`Mutex`]: sync::Mutex
+//! [`Option<T>`]: option::Option
+//! [`Rc`]: rc::Rc
+//! [`RefCell`]: cell::RefCell
+//! [`Result<T, E>`]: result::Result
+//! [`Vec<T>`]: vec::Vec
+//! [`atomic`]: sync::atomic
 //! [`for`]: ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
-//! [`format!`]: macro.format.html
-//! [`fs`]: fs/index.html
-//! [`io`]: io/index.html
-//! [`iter`]: iter/index.html
-//! [`mpsc`]: sync/mpsc/index.html
-//! [`net`]: net/index.html
-//! [`option`]: option/index.html
-//! [`result`]: result/index.html
-//! [`std::cmp`]: cmp/index.html
-//! [`std::slice`]: slice/index.html
-//! [`str`]: primitive.str.html
-//! [`sync`]: sync/index.html
-//! [`thread`]: thread/index.html
+//! [`mpsc`]: sync::mpsc
+//! [`std::cmp`]: cmp
+//! [`std::slice`]: slice
 //! [`use std::env`]: env/index.html
 //! [`use`]: ../book/ch07-02-defining-modules-to-control-scope-and-privacy.html
 //! [crates.io]: https://crates.io
 //! [deref-coercions]: ../book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
-//! [files]: fs/struct.File.html
-//! [multithreading]: thread/index.html
+//! [files]: fs::File
+//! [multithreading]: thread
 //! [other]: #what-is-in-the-standard-library-documentation
 //! [primitive types]: ../book/ch03-02-data-types.html
 //! [rust-discord]: https://discord.gg/rust-lang
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index f9c96b7c3d4..0d2aca6bbc3 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -768,7 +768,8 @@ mod prim_tuple {}
 ///
 /// This type can represent a wide range of decimal numbers, like `3.5`, `27`,
 /// `-113.75`, `0.0078125`, `34359738368`, `0`, `-1`. So unlike integer types
-/// (like `i32`), floating point types can represent non-integer numbers, too.
+/// (such as `i32`), floating point types can represent non-integer numbers,
+/// too.
 ///
 /// However, being able to represent this wide range of numbers comes at the
 /// cost of precision: floats can only represent some of the real numbers and
@@ -779,15 +780,12 @@ mod prim_tuple {}
 /// often discard insignificant digits: `println!("{}", 1.0f32 / 5.0f32)` will
 /// print `0.2`.
 ///
-/// The precision is better for numbers near 0 and worse for large numbers. For
-/// example, above 2<sup>24</sup>, not even all integers are representable.
-///
 /// Additionally, `f32` can represent a couple of special values:
 ///
 /// - `-0`: this is just due to how floats are encoded. It is semantically
 ///   equivalent to `0` and `-0.0 == 0.0` results in `true`.
 /// - [∞](#associatedconstant.INFINITY) and
-///   [-∞](#associatedconstant.NEG_INFINITY): these result from calculations
+///   [−∞](#associatedconstant.NEG_INFINITY): these result from calculations
 ///   like `1.0 / 0.0`.
 /// - [NaN (not a number)](#associatedconstant.NAN): this value results from
 ///   calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected
diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index 6782d845bb0..8408756f1b3 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -46,6 +46,7 @@ pub struct DirEntry {
 pub struct OpenOptions {
     read: bool,
     write: bool,
+    append: bool,
     dirflags: wasi::Lookupflags,
     fdflags: wasi::Fdflags,
     oflags: wasi::Oflags,
@@ -270,8 +271,9 @@ impl OpenOptions {
         }
     }
 
-    pub fn append(&mut self, set: bool) {
-        self.fdflag(wasi::FDFLAGS_APPEND, set);
+    pub fn append(&mut self, append: bool) {
+        self.append = append;
+        self.fdflag(wasi::FDFLAGS_APPEND, append);
     }
 
     pub fn dsync(&mut self, set: bool) {
@@ -321,7 +323,7 @@ impl OpenOptions {
             base |= wasi::RIGHTS_FD_READ;
             base |= wasi::RIGHTS_FD_READDIR;
         }
-        if self.write {
+        if self.write || self.append {
             base |= wasi::RIGHTS_FD_WRITE;
             base |= wasi::RIGHTS_FD_DATASYNC;
             base |= wasi::RIGHTS_FD_ALLOCATE;
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 969c442884d..02161ecb4c8 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -359,9 +359,7 @@ impl Add<Duration> for Instant {
     /// # Panics
     ///
     /// This function may panic if the resulting point in time cannot be represented by the
-    /// underlying data structure. See [`checked_add`] for a version without panic.
-    ///
-    /// [`checked_add`]: Instant::checked_add
+    /// underlying data structure. See [`Instant::checked_add`] for a version without panic.
     fn add(self, other: Duration) -> Instant {
         self.checked_add(other).expect("overflow when adding duration to instant")
     }
@@ -525,9 +523,7 @@ impl Add<Duration> for SystemTime {
     /// # Panics
     ///
     /// This function may panic if the resulting point in time cannot be represented by the
-    /// underlying data structure. See [`checked_add`] for a version without panic.
-    ///
-    /// [`checked_add`]: SystemTime::checked_add
+    /// underlying data structure. See [`SystemTime::checked_add`] for a version without panic.
     fn add(self, dur: Duration) -> SystemTime {
         self.checked_add(dur).expect("overflow when adding duration to instant")
     }
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index 244377dfa1d..3c2a063cf24 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -777,7 +777,7 @@ fn validate_generic_param_order<'a>(
                 if sess.features_untracked().const_generics {
                     ", then consts and types"
                 } else if sess.features_untracked().min_const_generics {
-                    ", then consts, then types"
+                    ", then types, then consts"
                 } else {
                     ", then types"
                 },
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 54271d3dd04..1a5794d1133 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -975,7 +975,6 @@ pub unsafe fn with_llvm_pmb(
         (llvm::CodeGenOptLevel::Default, ..) => {
             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
         }
-        (llvm::CodeGenOptLevel::Other, ..) => bug!("CodeGenOptLevel::Other selected"),
     }
 
     f(builder);
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index eb7dc827f93..f094ad86894 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -337,9 +337,6 @@ impl AtomicOrdering {
 #[derive(Copy, Clone)]
 #[repr(C)]
 pub enum SynchronizationScope {
-    // FIXME: figure out if this variant is needed at all.
-    #[allow(dead_code)]
-    Other,
     SingleThread,
     CrossThread,
 }
@@ -347,7 +344,6 @@ pub enum SynchronizationScope {
 impl SynchronizationScope {
     pub fn from_generic(sc: rustc_codegen_ssa::common::SynchronizationScope) -> Self {
         match sc {
-            rustc_codegen_ssa::common::SynchronizationScope::Other => SynchronizationScope::Other,
             rustc_codegen_ssa::common::SynchronizationScope::SingleThread => {
                 SynchronizationScope::SingleThread
             }
@@ -362,9 +358,6 @@ impl SynchronizationScope {
 #[derive(Copy, Clone)]
 #[repr(C)]
 pub enum FileType {
-    // FIXME: figure out if this variant is needed at all.
-    #[allow(dead_code)]
-    Other,
     AssemblyFile,
     ObjectFile,
 }
@@ -391,9 +384,6 @@ pub enum MetadataType {
 #[derive(Copy, Clone)]
 #[repr(C)]
 pub enum AsmDialect {
-    // FIXME: figure out if this variant is needed at all.
-    #[allow(dead_code)]
-    Other,
     Att,
     Intel,
 }
@@ -411,9 +401,6 @@ impl AsmDialect {
 #[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
 pub enum CodeGenOptLevel {
-    // FIXME: figure out if this variant is needed at all.
-    #[allow(dead_code)]
-    Other,
     None,
     Less,
     Default,
@@ -513,9 +500,6 @@ pub enum DiagnosticLevel {
 #[derive(Copy, Clone)]
 #[repr(C)]
 pub enum ArchiveKind {
-    // FIXME: figure out if this variant is needed at all.
-    #[allow(dead_code)]
-    Other,
     K_GNU,
     K_BSD,
     K_DARWIN,
diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs
index 432b2f3bdc3..e04ed531bbf 100644
--- a/src/librustc_codegen_ssa/common.rs
+++ b/src/librustc_codegen_ssa/common.rs
@@ -72,9 +72,6 @@ pub enum AtomicOrdering {
 }
 
 pub enum SynchronizationScope {
-    // FIXME: figure out if this variant is needed at all.
-    #[allow(dead_code)]
-    Other,
     SingleThread,
     CrossThread,
 }
diff --git a/src/librustc_error_codes/error_codes/E0751.md b/src/librustc_error_codes/error_codes/E0751.md
index 809b888d92a..8794f7868f3 100644
--- a/src/librustc_error_codes/error_codes/E0751.md
+++ b/src/librustc_error_codes/error_codes/E0751.md
@@ -5,8 +5,8 @@ Erroneous code example:
 ```compile_fail,E0751
 trait MyTrait {}
 impl MyTrait for i32 { }
-impl !MyTrait for i32 { }
+impl !MyTrait for i32 { } // error!
 ```
 
-Negative implementations are a promise that the trait will never be
-implemented for the given types.
+Negative implementations are a promise that the trait will never be implemented
+for the given types. Therefore, both cannot exists at the same time.
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index f0ea325d2ab..a7d36974057 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -16,8 +16,8 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::PrimTy;
 use rustc_session::config::nightly_options;
 use rustc_span::hygiene::MacroKind;
-use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::{BytePos, Span};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{BytePos, Span, DUMMY_SP};
 
 use log::debug;
 
@@ -33,6 +33,7 @@ enum AssocSuggestion {
 crate enum MissingLifetimeSpot<'tcx> {
     Generics(&'tcx hir::Generics<'tcx>),
     HigherRanked { span: Span, span_type: ForLifetimeSpanType },
+    Static,
 }
 
 crate enum ForLifetimeSpanType {
@@ -1195,6 +1196,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                             https://doc.rust-lang.org/nomicon/hrtb.html",
                     );
                 }
+                _ => {}
             }
         }
         if nightly_options::is_nightly_build()
@@ -1253,7 +1255,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
         err: &mut DiagnosticBuilder<'_>,
         span: Span,
         count: usize,
-        lifetime_names: &FxHashSet<Ident>,
+        lifetime_names: &FxHashSet<Symbol>,
+        lifetime_spans: Vec<Span>,
         params: &[ElisionFailureInfo],
     ) {
         let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok();
@@ -1267,11 +1270,60 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
             ),
         );
 
-        let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| {
+        let suggest_existing = |err: &mut DiagnosticBuilder<'_>,
+                                name: &str,
+                                formatter: &dyn Fn(&str) -> String| {
+            if let Some(MissingLifetimeSpot::HigherRanked { span: for_span, span_type }) =
+                self.missing_named_lifetime_spots.iter().rev().next()
+            {
+                // When we have `struct S<'a>(&'a dyn Fn(&X) -> &X);` we want to not only suggest
+                // using `'a`, but also introduce the concept of HRLTs by suggesting
+                // `struct S<'a>(&'a dyn for<'b> Fn(&X) -> &'b X);`. (#72404)
+                let mut introduce_suggestion = vec![];
+
+                let a_to_z_repeat_n = |n| {
+                    (b'a'..=b'z').map(move |c| {
+                        let mut s = '\''.to_string();
+                        s.extend(std::iter::repeat(char::from(c)).take(n));
+                        s
+                    })
+                };
+
+                // If all single char lifetime names are present, we wrap around and double the chars.
+                let lt_name = (1..)
+                    .flat_map(a_to_z_repeat_n)
+                    .find(|lt| !lifetime_names.contains(&Symbol::intern(&lt)))
+                    .unwrap();
+                let msg = format!(
+                    "consider making the {} lifetime-generic with a new `{}` lifetime",
+                    span_type.descr(),
+                    lt_name,
+                );
+                err.note(
+                    "for more information on higher-ranked polymorphism, visit \
+                    https://doc.rust-lang.org/nomicon/hrtb.html",
+                );
+                let for_sugg = span_type.suggestion(&lt_name);
+                for param in params {
+                    if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) {
+                        if snippet.starts_with('&') && !snippet.starts_with("&'") {
+                            introduce_suggestion
+                                .push((param.span, format!("&{} {}", lt_name, &snippet[1..])));
+                        } else if snippet.starts_with("&'_ ") {
+                            introduce_suggestion
+                                .push((param.span, format!("&{} {}", lt_name, &snippet[4..])));
+                        }
+                    }
+                }
+                introduce_suggestion.push((*for_span, for_sugg.to_string()));
+                introduce_suggestion.push((span, formatter(&lt_name)));
+                err.multipart_suggestion(&msg, introduce_suggestion, Applicability::MaybeIncorrect);
+            }
+
             err.span_suggestion_verbose(
                 span,
                 &format!("consider using the `{}` lifetime", lifetime_names.iter().next().unwrap()),
-                sugg,
+                formatter(name),
                 Applicability::MaybeIncorrect,
             );
         };
@@ -1282,6 +1334,15 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                 let should_break;
                 introduce_suggestion.push(match missing {
                     MissingLifetimeSpot::Generics(generics) => {
+                        if generics.span == DUMMY_SP {
+                            // Account for malformed generics in the HIR. This shouldn't happen,
+                            // but if we make a mistake elsewhere, mainly by keeping something in
+                            // `missing_named_lifetime_spots` that we shouldn't, like associated
+                            // `const`s or making a mistake in the AST lowering we would provide
+                            // non-sensical suggestions. Guard against that by skipping these.
+                            // (#74264)
+                            continue;
+                        }
                         msg = "consider introducing a named lifetime parameter".to_string();
                         should_break = true;
                         if let Some(param) = generics.params.iter().find(|p| match p.kind {
@@ -1308,6 +1369,42 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                         );
                         (*span, span_type.suggestion("'a"))
                     }
+                    MissingLifetimeSpot::Static => {
+                        let (span, sugg) = match snippet.as_deref() {
+                            Some("&") => (span.shrink_to_hi(), "'static ".to_owned()),
+                            Some("'_") => (span, "'static".to_owned()),
+                            Some(snippet) if !snippet.ends_with('>') => {
+                                if snippet == "" {
+                                    (
+                                        span,
+                                        std::iter::repeat("'static")
+                                            .take(count)
+                                            .collect::<Vec<_>>()
+                                            .join(", "),
+                                    )
+                                } else {
+                                    (
+                                        span.shrink_to_hi(),
+                                        format!(
+                                            "<{}>",
+                                            std::iter::repeat("'static")
+                                                .take(count)
+                                                .collect::<Vec<_>>()
+                                                .join(", ")
+                                        ),
+                                    )
+                                }
+                            }
+                            _ => continue,
+                        };
+                        err.span_suggestion_verbose(
+                            span,
+                            "consider using the `'static` lifetime",
+                            sugg.to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                        continue;
+                    }
                 });
                 for param in params {
                     if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) {
@@ -1328,19 +1425,19 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
             }
         };
 
-        match (lifetime_names.len(), lifetime_names.iter().next(), snippet.as_deref()) {
-            (1, Some(name), Some("&")) => {
-                suggest_existing(err, format!("&{} ", name));
+        let lifetime_names: Vec<_> = lifetime_names.into_iter().collect();
+        match (&lifetime_names[..], snippet.as_deref()) {
+            ([name], Some("&")) => {
+                suggest_existing(err, &name.as_str()[..], &|name| format!("&{} ", name));
             }
-            (1, Some(name), Some("'_")) => {
-                suggest_existing(err, name.to_string());
+            ([name], Some("'_")) => {
+                suggest_existing(err, &name.as_str()[..], &|n| n.to_string());
             }
-            (1, Some(name), Some("")) => {
-                suggest_existing(err, format!("{}, ", name).repeat(count));
+            ([name], Some("")) => {
+                suggest_existing(err, &name.as_str()[..], &|n| format!("{}, ", n).repeat(count));
             }
-            (1, Some(name), Some(snippet)) if !snippet.ends_with('>') => {
-                suggest_existing(
-                    err,
+            ([name], Some(snippet)) if !snippet.ends_with('>') => {
+                let f = |name: &str| {
                     format!(
                         "{}<{}>",
                         snippet,
@@ -1348,21 +1445,37 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                             .take(count)
                             .collect::<Vec<_>>()
                             .join(", ")
-                    ),
-                );
+                    )
+                };
+                suggest_existing(err, &name.as_str()[..], &f);
             }
-            (0, _, Some("&")) if count == 1 => {
+            ([], Some("&")) if count == 1 => {
                 suggest_new(err, "&'a ");
             }
-            (0, _, Some("'_")) if count == 1 => {
+            ([], Some("'_")) if count == 1 => {
                 suggest_new(err, "'a");
             }
-            (0, _, Some(snippet)) if !snippet.ends_with('>') && count == 1 => {
-                suggest_new(err, &format!("{}<'a>", snippet));
+            ([], Some(snippet)) if !snippet.ends_with('>') => {
+                if snippet == "" {
+                    // This happens when we have `type Bar<'a> = Foo<T>` where we point at the space
+                    // before `T`. We will suggest `type Bar<'a> = Foo<'a, T>`.
+                    suggest_new(
+                        err,
+                        &std::iter::repeat("'a, ").take(count).collect::<Vec<_>>().join(""),
+                    );
+                } else {
+                    suggest_new(
+                        err,
+                        &format!(
+                            "{}<{}>",
+                            snippet,
+                            std::iter::repeat("'a").take(count).collect::<Vec<_>>().join(", ")
+                        ),
+                    );
+                }
             }
-            (n, ..) if n > 1 => {
-                let spans: Vec<Span> = lifetime_names.iter().map(|lt| lt.span).collect();
-                err.span_note(spans, "these named lifetimes are available to use");
+            (lts, ..) if lts.len() > 1 => {
+                err.span_note(lifetime_spans, "these named lifetimes are available to use");
                 if Some("") == snippet.as_deref() {
                     // This happens when we have `Foo<T>` where we point at the space before `T`,
                     // but this can be confusing so we give a suggestion with placeholders.
diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs
index 0b881b089de..2046419d984 100644
--- a/src/librustc_resolve/late/lifetimes.rs
+++ b/src/librustc_resolve/late/lifetimes.rs
@@ -711,9 +711,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         use self::hir::TraitItemKind::*;
-        self.missing_named_lifetime_spots.push((&trait_item.generics).into());
         match trait_item.kind {
             Fn(ref sig, _) => {
+                self.missing_named_lifetime_spots.push((&trait_item.generics).into());
                 let tcx = self.tcx;
                 self.visit_early_late(
                     Some(tcx.hir().get_parent_item(trait_item.hir_id)),
@@ -721,8 +721,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     &trait_item.generics,
                     |this| intravisit::walk_trait_item(this, trait_item),
                 );
+                self.missing_named_lifetime_spots.pop();
             }
             Type(bounds, ref ty) => {
+                self.missing_named_lifetime_spots.push((&trait_item.generics).into());
                 let generics = &trait_item.generics;
                 let mut index = self.next_early_index();
                 debug!("visit_ty: index = {}", index);
@@ -757,31 +759,35 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         this.visit_ty(ty);
                     }
                 });
+                self.missing_named_lifetime_spots.pop();
             }
             Const(_, _) => {
                 // Only methods and types support generics.
                 assert!(trait_item.generics.params.is_empty());
+                self.missing_named_lifetime_spots.push(MissingLifetimeSpot::Static);
                 intravisit::walk_trait_item(self, trait_item);
+                self.missing_named_lifetime_spots.pop();
             }
         }
-        self.missing_named_lifetime_spots.pop();
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         use self::hir::ImplItemKind::*;
-        self.missing_named_lifetime_spots.push((&impl_item.generics).into());
         match impl_item.kind {
             Fn(ref sig, _) => {
+                self.missing_named_lifetime_spots.push((&impl_item.generics).into());
                 let tcx = self.tcx;
                 self.visit_early_late(
                     Some(tcx.hir().get_parent_item(impl_item.hir_id)),
                     &sig.decl,
                     &impl_item.generics,
                     |this| intravisit::walk_impl_item(this, impl_item),
-                )
+                );
+                self.missing_named_lifetime_spots.pop();
             }
             TyAlias(ref ty) => {
                 let generics = &impl_item.generics;
+                self.missing_named_lifetime_spots.push(generics.into());
                 let mut index = self.next_early_index();
                 let mut non_lifetime_count = 0;
                 debug!("visit_ty: index = {}", index);
@@ -810,14 +816,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     this.visit_generics(generics);
                     this.visit_ty(ty);
                 });
+                self.missing_named_lifetime_spots.pop();
             }
             Const(_, _) => {
                 // Only methods and types support generics.
                 assert!(impl_item.generics.params.is_empty());
+                self.missing_named_lifetime_spots.push(MissingLifetimeSpot::Static);
                 intravisit::walk_impl_item(self, impl_item);
+                self.missing_named_lifetime_spots.pop();
             }
         }
-        self.missing_named_lifetime_spots.pop();
     }
 
     fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
@@ -2315,6 +2323,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         let mut late_depth = 0;
         let mut scope = self.scope;
         let mut lifetime_names = FxHashSet::default();
+        let mut lifetime_spans = vec![];
         let error = loop {
             match *scope {
                 // Do not assign any resolution, it will be inferred.
@@ -2326,7 +2335,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     // collect named lifetimes for suggestions
                     for name in lifetimes.keys() {
                         if let hir::ParamName::Plain(name) = name {
-                            lifetime_names.insert(*name);
+                            lifetime_names.insert(name.name);
+                            lifetime_spans.push(name.span);
                         }
                     }
                     late_depth += 1;
@@ -2344,12 +2354,24 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                         }
                         Elide::Exact(l) => l.shifted(late_depth),
                         Elide::Error(ref e) => {
-                            if let Scope::Binder { ref lifetimes, .. } = s {
-                                // collect named lifetimes for suggestions
-                                for name in lifetimes.keys() {
-                                    if let hir::ParamName::Plain(name) = name {
-                                        lifetime_names.insert(*name);
+                            let mut scope = s;
+                            loop {
+                                match scope {
+                                    Scope::Binder { ref lifetimes, s, .. } => {
+                                        // Collect named lifetimes for suggestions.
+                                        for name in lifetimes.keys() {
+                                            if let hir::ParamName::Plain(name) = name {
+                                                lifetime_names.insert(name.name);
+                                                lifetime_spans.push(name.span);
+                                            }
+                                        }
+                                        scope = s;
+                                    }
+                                    Scope::ObjectLifetimeDefault { ref s, .. }
+                                    | Scope::Elision { ref s, .. } => {
+                                        scope = s;
                                     }
+                                    _ => break,
                                 }
                             }
                             break Some(e);
@@ -2373,7 +2395,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         if let Some(params) = error {
             // If there's no lifetime available, suggest `'static`.
             if self.report_elision_failure(&mut err, params) && lifetime_names.is_empty() {
-                lifetime_names.insert(Ident::with_dummy_span(kw::StaticLifetime));
+                lifetime_names.insert(kw::StaticLifetime);
             }
         }
         self.add_missing_lifetime_specifiers_label(
@@ -2381,6 +2403,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             span,
             lifetime_refs.len(),
             &lifetime_names,
+            lifetime_spans,
             error.map(|p| &p[..]).unwrap_or(&[]),
         );
         err.emit();
diff --git a/src/librustc_serialize/collection_impls.rs b/src/librustc_serialize/collection_impls.rs
index c602de37b14..49b8094abd0 100644
--- a/src/librustc_serialize/collection_impls.rs
+++ b/src/librustc_serialize/collection_impls.rs
@@ -86,11 +86,9 @@ where
 {
     fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
         e.emit_map(self.len(), |e| {
-            let mut i = 0;
-            for (key, val) in self {
+            for (i, (key, val)) in self.iter().enumerate() {
                 e.emit_map_elt_key(i, |e| key.encode(e))?;
                 e.emit_map_elt_val(i, |e| val.encode(e))?;
-                i += 1;
             }
             Ok(())
         })
@@ -121,10 +119,8 @@ where
 {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
-            let mut i = 0;
-            for e in self {
+            for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?;
-                i += 1;
             }
             Ok(())
         })
@@ -154,11 +150,9 @@ where
 {
     fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
         e.emit_map(self.len(), |e| {
-            let mut i = 0;
-            for (key, val) in self {
+            for (i, (key, val)) in self.iter().enumerate() {
                 e.emit_map_elt_key(i, |e| key.encode(e))?;
                 e.emit_map_elt_val(i, |e| val.encode(e))?;
-                i += 1;
             }
             Ok(())
         })
@@ -192,10 +186,8 @@ where
 {
     fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
         s.emit_seq(self.len(), |s| {
-            let mut i = 0;
-            for e in self {
+            for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?;
-                i += 1;
             }
             Ok(())
         })
@@ -227,11 +219,9 @@ where
 {
     fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
         e.emit_map(self.len(), |e| {
-            let mut i = 0;
-            for (key, val) in self {
+            for (i, (key, val)) in self.iter().enumerate() {
                 e.emit_map_elt_key(i, |e| key.encode(e))?;
                 e.emit_map_elt_val(i, |e| val.encode(e))?;
-                i += 1;
             }
             Ok(())
         })
@@ -265,10 +255,8 @@ where
 {
     fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
         s.emit_seq(self.len(), |s| {
-            let mut i = 0;
-            for e in self {
+            for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?;
-                i += 1;
             }
             Ok(())
         })
diff --git a/src/librustc_serialize/json.rs b/src/librustc_serialize/json.rs
index 820ebdc9baa..ab7f6975325 100644
--- a/src/librustc_serialize/json.rs
+++ b/src/librustc_serialize/json.rs
@@ -78,19 +78,17 @@
 //!     data_vector: Vec<u8>,
 //! }
 //!
-//! fn main() {
-//!     let object = TestStruct {
-//!         data_int: 1,
-//!         data_str: "homura".to_string(),
-//!         data_vector: vec![2,3,4,5],
-//!     };
+//! let object = TestStruct {
+//!     data_int: 1,
+//!     data_str: "homura".to_string(),
+//!     data_vector: vec![2,3,4,5],
+//! };
 //!
-//!     // Serialize using `json::encode`
-//!     let encoded = json::encode(&object).unwrap();
+//! // Serialize using `json::encode`
+//! let encoded = json::encode(&object).unwrap();
 //!
-//!     // Deserialize using `json::decode`
-//!     let decoded: TestStruct = json::decode(&encoded[..]).unwrap();
-//! }
+//! // Deserialize using `json::decode`
+//! let decoded: TestStruct = json::decode(&encoded[..]).unwrap();
 //! ```
 //!
 //! ## Using the `ToJson` trait
@@ -125,16 +123,14 @@
 //!     val: Json,
 //! }
 //!
-//! fn main() {
-//!     let num = ComplexNum { a: 0.0001, b: 12.539 };
-//!     let data: String = json::encode(&ComplexNumRecord{
-//!         uid: 1,
-//!         dsc: "test".to_string(),
-//!         val: num.to_json(),
-//!     }).unwrap();
-//!     println!("data: {}", data);
-//!     // data: {"uid":1,"dsc":"test","val":"0.0001+12.539i"};
-//! }
+//! let num = ComplexNum { a: 0.0001, b: 12.539 };
+//! let data: String = json::encode(&ComplexNumRecord{
+//!     uid: 1,
+//!     dsc: "test".to_string(),
+//!     val: num.to_json(),
+//! }).unwrap();
+//! println!("data: {}", data);
+//! // data: {"uid":1,"dsc":"test","val":"0.0001+12.539i"};
 //! ```
 //!
 //! ### Verbose example of `ToJson` usage
@@ -164,19 +160,17 @@
 //!     }
 //! }
 //!
-//! fn main() {
-//!     // Serialize using `ToJson`
-//!     let input_data = TestStruct {
-//!         data_int: 1,
-//!         data_str: "madoka".to_string(),
-//!         data_vector: vec![2,3,4,5],
-//!     };
-//!     let json_obj: Json = input_data.to_json();
-//!     let json_str: String = json_obj.to_string();
+//! // Serialize using `ToJson`
+//! let input_data = TestStruct {
+//!     data_int: 1,
+//!     data_str: "madoka".to_string(),
+//!     data_vector: vec![2,3,4,5],
+//! };
+//! let json_obj: Json = input_data.to_json();
+//! let json_str: String = json_obj.to_string();
 //!
-//!     // Deserialize like before
-//!     let decoded: TestStruct = json::decode(&json_str).unwrap();
-//! }
+//! // Deserialize like before
+//! let decoded: TestStruct = json::decode(&json_str).unwrap();
 //! ```
 
 use self::DecoderError::*;
@@ -1269,34 +1263,22 @@ impl Json {
 
     /// Returns `true` if the Json value is a `Number`.
     pub fn is_number(&self) -> bool {
-        match *self {
-            Json::I64(_) | Json::U64(_) | Json::F64(_) => true,
-            _ => false,
-        }
+        matches!(*self, Json::I64(_) | Json::U64(_) | Json::F64(_))
     }
 
     /// Returns `true` if the Json value is a `i64`.
     pub fn is_i64(&self) -> bool {
-        match *self {
-            Json::I64(_) => true,
-            _ => false,
-        }
+        matches!(*self, Json::I64(_))
     }
 
     /// Returns `true` if the Json value is a `u64`.
     pub fn is_u64(&self) -> bool {
-        match *self {
-            Json::U64(_) => true,
-            _ => false,
-        }
+        matches!(*self, Json::U64(_))
     }
 
     /// Returns `true` if the Json value is a `f64`.
     pub fn is_f64(&self) -> bool {
-        match *self {
-            Json::F64(_) => true,
-            _ => false,
-        }
+        matches!(*self, Json::F64(_))
     }
 
     /// If the Json value is a number, returns or cast it to a `i64`;
@@ -1416,6 +1398,7 @@ enum ParserState {
 /// structure of the JSON stream.
 ///
 /// An example is `foo.bar[3].x`.
+#[derive(Default)]
 pub struct Stack {
     stack: Vec<InternalStackElement>,
     str_buffer: Vec<u8>,
@@ -1442,7 +1425,7 @@ enum InternalStackElement {
 
 impl Stack {
     pub fn new() -> Stack {
-        Stack { stack: Vec::new(), str_buffer: Vec::new() }
+        Self::default()
     }
 
     /// Returns The number of elements in the Stack.
@@ -1547,10 +1530,7 @@ impl Stack {
 
     // Used by Parser to test whether the top-most element is an index.
     fn last_is_index(&self) -> bool {
-        match self.stack.last() {
-            Some(InternalIndex(_)) => true,
-            _ => false,
-        }
+        matches!(self.stack.last(), Some(InternalIndex(_)))
     }
 
     // Used by Parser to increment the index of the top-most element.
diff --git a/src/librustc_serialize/opaque.rs b/src/librustc_serialize/opaque.rs
index 39f3abb7527..fa4423e261d 100644
--- a/src/librustc_serialize/opaque.rs
+++ b/src/librustc_serialize/opaque.rs
@@ -118,13 +118,13 @@ impl serialize::Encoder for Encoder {
 
     #[inline]
     fn emit_f64(&mut self, v: f64) -> EncodeResult {
-        let as_u64: u64 = unsafe { ::std::mem::transmute(v) };
+        let as_u64: u64 = v.to_bits();
         self.emit_u64(as_u64)
     }
 
     #[inline]
     fn emit_f32(&mut self, v: f32) -> EncodeResult {
-        let as_u32: u32 = unsafe { ::std::mem::transmute(v) };
+        let as_u32: u32 = v.to_bits();
         self.emit_u32(as_u32)
     }
 
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index 93704638f83..9ce614fda57 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -35,7 +35,6 @@ struct RustArchiveIterator {
 };
 
 enum class LLVMRustArchiveKind {
-  Other,
   GNU,
   BSD,
   DARWIN,
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 41b14714842..76fe5e7f769 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -311,7 +311,6 @@ static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) {
 }
 
 enum class LLVMRustCodeGenOptLevel {
-  Other,
   None,
   Less,
   Default,
@@ -597,7 +596,6 @@ extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
 }
 
 enum class LLVMRustFileType {
-  Other,
   AssemblyFile,
   ObjectFile,
 };
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 667bf4a2ded..9d90b0dfe07 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -366,7 +366,6 @@ LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
 }
 
 enum class LLVMRustSynchronizationScope {
-  Other,
   SingleThread,
   CrossThread,
 };
@@ -389,7 +388,6 @@ LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
 }
 
 enum class LLVMRustAsmDialect {
-  Other,
   Att,
   Intel,
 };
diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr
index 00f44129cc8..6c68cc7bc61 100644
--- a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr
+++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr
@@ -5,6 +5,11 @@ LL | fn elision<T: Fn() -> &i32>() {
    |                       ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+   |
+LL | fn elision<T: for<'a> Fn() -> &'a i32>() {
+   |               ^^^^^^^         ^^^
 help: consider using the `'static` lifetime
    |
 LL | fn elision<T: Fn() -> &'static i32>() {
diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr
index a5242707c71..93d2f8e7911 100644
--- a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr
+++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr
@@ -5,6 +5,11 @@ LL | fn elision(_: fn() -> &i32) {
    |                       ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the type lifetime-generic with a new `'a` lifetime
+   |
+LL | fn elision(_: for<'a> fn() -> &'a i32) {
+   |               ^^^^^^^         ^^^
 help: consider using the `'static` lifetime
    |
 LL | fn elision(_: fn() -> &'static i32) {
diff --git a/src/test/ui/const-generics/defaults/needs-feature.min.stderr b/src/test/ui/const-generics/defaults/needs-feature.min.stderr
index d57190ea3bb..7058327fdce 100644
--- a/src/test/ui/const-generics/defaults/needs-feature.min.stderr
+++ b/src/test/ui/const-generics/defaults/needs-feature.min.stderr
@@ -2,7 +2,7 @@ error: type parameters must be declared prior to const parameters
   --> $DIR/needs-feature.rs:10:26
    |
 LL | struct A<const N: usize, T=u32>(T);
-   |         -----------------^----- help: reorder the parameters: lifetimes, then consts, then types: `<T, const N: usize>`
+   |         -----------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr
index a23bcbfd71a..ac70e887626 100644
--- a/src/test/ui/error-codes/E0106.stderr
+++ b/src/test/ui/error-codes/E0106.stderr
@@ -51,6 +51,15 @@ error[E0106]: missing lifetime specifiers
    |
 LL |     buzz: Buzz,
    |           ^^^^ expected 2 lifetime parameters
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | struct Quux<'a> {
+LL |     baz: Baz,
+LL |
+LL |
+LL |     buzz: Buzz<'a, 'a>,
+   |
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/issues/issue-74739.rs b/src/test/ui/issues/issue-74739.rs
new file mode 100644
index 00000000000..03622358ae1
--- /dev/null
+++ b/src/test/ui/issues/issue-74739.rs
@@ -0,0 +1,14 @@
+// compile-flags: -O
+// run-pass
+
+struct Foo {
+    x: i32,
+}
+
+pub fn main() {
+    let mut foo = Foo { x: 42 };
+    let x = &mut foo.x;
+    *x = 13;
+    let y = foo;
+    assert_eq!(y.x, 13); // used to print 42 due to mir-opt bug
+}
diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
index da3056eac90..d260addef48 100644
--- a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
+++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
@@ -6,8 +6,8 @@ LL |     type Item = IteratorChunk<T, S>;
    |
 help: consider introducing a named lifetime parameter
    |
-LL |     type Item<'a> = IteratorChunk<<'a>T, S>;
-   |              ^^^^                 ^^^^
+LL |     type Item<'a> = IteratorChunk<'a, T, S>;
+   |              ^^^^                 ^^^
 
 error: `impl` item signature doesn't match `trait` item signature
   --> $DIR/issue-74918-missing-lifetime.rs:11:5
diff --git a/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.rs b/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.rs
new file mode 100644
index 00000000000..38332627f4c
--- /dev/null
+++ b/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.rs
@@ -0,0 +1,16 @@
+trait ZstAssert: Sized {
+    const A: &str = ""; //~ ERROR missing lifetime specifier
+    const B: S = S { s: &() }; //~ ERROR missing lifetime specifier
+    const C: &'_ str = ""; //~ ERROR missing lifetime specifier
+    const D: T = T { a: &(), b: &() }; //~ ERROR missing lifetime specifier
+}
+
+struct S<'a> {
+    s: &'a (),
+}
+struct T<'a, 'b> {
+    a: &'a (),
+    b: &'b (),
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr b/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr
new file mode 100644
index 00000000000..b20778ce208
--- /dev/null
+++ b/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr
@@ -0,0 +1,73 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lifetime-in-assoc-const-type.rs:2:14
+   |
+LL |     const A: &str = "";
+   |              ^ expected named lifetime parameter
+   |
+help: consider using the `'static` lifetime
+   |
+LL |     const A: &'static str = "";
+   |               ^^^^^^^
+help: consider introducing a named lifetime parameter
+   |
+LL | trait ZstAssert<'a>: Sized {
+LL |     const A: &'a str = "";
+   |
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lifetime-in-assoc-const-type.rs:3:14
+   |
+LL |     const B: S = S { s: &() };
+   |              ^ expected named lifetime parameter
+   |
+help: consider using the `'static` lifetime
+   |
+LL |     const B: S<'static> = S { s: &() };
+   |               ^^^^^^^^^
+help: consider introducing a named lifetime parameter
+   |
+LL | trait ZstAssert<'a>: Sized {
+LL |     const A: &str = "";
+LL |     const B: S<'a> = S { s: &() };
+   |
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lifetime-in-assoc-const-type.rs:4:15
+   |
+LL |     const C: &'_ str = "";
+   |               ^^ expected named lifetime parameter
+   |
+help: consider using the `'static` lifetime
+   |
+LL |     const C: &'static str = "";
+   |               ^^^^^^^
+help: consider introducing a named lifetime parameter
+   |
+LL | trait ZstAssert<'a>: Sized {
+LL |     const A: &str = "";
+LL |     const B: S = S { s: &() };
+LL |     const C: &'a str = "";
+   |
+
+error[E0106]: missing lifetime specifiers
+  --> $DIR/missing-lifetime-in-assoc-const-type.rs:5:14
+   |
+LL |     const D: T = T { a: &(), b: &() };
+   |              ^ expected 2 lifetime parameters
+   |
+help: consider using the `'static` lifetime
+   |
+LL |     const D: T<'static, 'static> = T { a: &(), b: &() };
+   |               ^^^^^^^^^^^^^^^^^^
+help: consider introducing a named lifetime parameter
+   |
+LL | trait ZstAssert<'a>: Sized {
+LL |     const A: &str = "";
+LL |     const B: S = S { s: &() };
+LL |     const C: &'_ str = "";
+LL |     const D: T<'a, 'a> = T { a: &(), b: &() };
+   |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/suggestions/missing-lt-for-hrtb.rs b/src/test/ui/suggestions/missing-lt-for-hrtb.rs
new file mode 100644
index 00000000000..a90a90122ad
--- /dev/null
+++ b/src/test/ui/suggestions/missing-lt-for-hrtb.rs
@@ -0,0 +1,15 @@
+struct X<'a>(&'a ());
+struct S<'a>(&'a dyn Fn(&X) -> &X);
+//~^ ERROR missing lifetime specifier
+//~| ERROR missing lifetime specifier
+struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
+//~^ ERROR missing lifetime specifier
+//~| ERROR missing lifetime specifier
+
+fn main() {
+    let x = S(&|x| {
+        println!("hi");
+        x
+    });
+    x.0(&X(&()));
+}
diff --git a/src/test/ui/suggestions/missing-lt-for-hrtb.stderr b/src/test/ui/suggestions/missing-lt-for-hrtb.stderr
new file mode 100644
index 00000000000..2cb63500e48
--- /dev/null
+++ b/src/test/ui/suggestions/missing-lt-for-hrtb.stderr
@@ -0,0 +1,63 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lt-for-hrtb.rs:2:32
+   |
+LL | struct S<'a>(&'a dyn Fn(&X) -> &X);
+   |                         --     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL | struct S<'a>(&'a dyn for<'b> Fn(&'b X) -> &'b X);
+   |                      ^^^^^^^    ^^^^^     ^^^
+help: consider using the `'a` lifetime
+   |
+LL | struct S<'a>(&'a dyn Fn(&X) -> &'a X);
+   |                                ^^^
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lt-for-hrtb.rs:2:33
+   |
+LL | struct S<'a>(&'a dyn Fn(&X) -> &X);
+   |                         --      ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL | struct S<'a>(&'a dyn for<'b> Fn(&'b X) -> &X<'b>);
+   |                      ^^^^^^^    ^^^^^      ^^^^^
+help: consider using the `'a` lifetime
+   |
+LL | struct S<'a>(&'a dyn Fn(&X) -> &X<'a>);
+   |                                 ^^^^^
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lt-for-hrtb.rs:5:40
+   |
+LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
+   |                                 --     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from
+note: these named lifetimes are available to use
+  --> $DIR/missing-lt-for-hrtb.rs:5:10
+   |
+LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
+   |          ^^              ^^
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lt-for-hrtb.rs:5:41
+   |
+LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
+   |                                 --      ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from
+note: these named lifetimes are available to use
+  --> $DIR/missing-lt-for-hrtb.rs:5:10
+   |
+LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
+   |          ^^              ^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0106`.