diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index ffae3b5c7894f..96923ea47f39b 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -984,7 +984,7 @@ impl<T> Vec<T> {
             // bounds check above succeeds there must be a last element (which
             // can be self[index] itself).
             let last = ptr::read(self.as_ptr().add(len - 1));
-            let hole: *mut T = self.as_mut_ptr().add(index);
+            let hole = self.as_mut_ptr().add(index);
             self.set_len(len - 1);
             ptr::replace(hole, last)
         }
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 449aac85bc773..477cb24d6be67 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -153,6 +153,9 @@ pub fn spin_loop_hint() {
 ///
 /// This type has the same in-memory representation as a [`bool`].
 ///
+/// **Note**: This type is only available on platforms that support atomic
+/// loads and stores of `u8`.
+///
 /// [`bool`]: ../../../std/primitive.bool.html
 #[cfg(target_has_atomic_load_store = "8")]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -178,6 +181,9 @@ unsafe impl Sync for AtomicBool {}
 /// A raw pointer type which can be safely shared between threads.
 ///
 /// This type has the same in-memory representation as a `*mut T`.
+///
+/// **Note**: This type is only available on platforms that support atomic
+/// loads and stores of pointers. Its size depends on the target pointer's size.
 #[cfg(target_has_atomic_load_store = "ptr")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(target_pointer_width = "16", repr(C, align(2)))]
@@ -447,6 +453,9 @@ impl AtomicBool {
     /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
     /// using [`Release`] makes the load part [`Relaxed`].
     ///
+    /// **Note:** This method is only available on platforms that support atomic
+    /// operations on `u8`.
+    ///
     /// [`Ordering`]: enum.Ordering.html
     /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
     /// [`Release`]: enum.Ordering.html#variant.Release
@@ -481,6 +490,9 @@ impl AtomicBool {
     /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
     /// happens, and using [`Release`] makes the load part [`Relaxed`].
     ///
+    /// **Note:** This method is only available on platforms that support atomic
+    /// operations on `u8`.
+    ///
     /// [`Ordering`]: enum.Ordering.html
     /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
     /// [`Release`]: enum.Ordering.html#variant.Release
@@ -524,6 +536,8 @@ impl AtomicBool {
     /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]
     /// and must be equivalent to or weaker than the success ordering.
     ///
+    /// **Note:** This method is only available on platforms that support atomic
+    /// operations on `u8`.
     ///
     /// [`bool`]: ../../../std/primitive.bool.html
     /// [`Ordering`]: enum.Ordering.html
@@ -586,6 +600,9 @@ impl AtomicBool {
     /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]
     /// and must be equivalent to or weaker than the success ordering.
     ///
+    /// **Note:** This method is only available on platforms that support atomic
+    /// operations on `u8`.
+    ///
     /// [`bool`]: ../../../std/primitive.bool.html
     /// [`compare_exchange`]: #method.compare_exchange
     /// [`Ordering`]: enum.Ordering.html
@@ -646,6 +663,9 @@ impl AtomicBool {
     /// [`Release`]: enum.Ordering.html#variant.Release
     /// [`Acquire`]: enum.Ordering.html#variant.Acquire
     ///
+    /// **Note:** This method is only available on platforms that support atomic
+    /// operations on `u8`.
+    ///
     /// # Examples
     ///
     /// ```
@@ -683,6 +703,9 @@ impl AtomicBool {
     /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
     /// using [`Release`] makes the load part [`Relaxed`].
     ///
+    /// **Note:** This method is only available on platforms that support atomic
+    /// operations on `u8`.
+    ///
     /// [`Ordering`]: enum.Ordering.html
     /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
     /// [`Release`]: enum.Ordering.html#variant.Release
@@ -737,6 +760,9 @@ impl AtomicBool {
     /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
     /// using [`Release`] makes the load part [`Relaxed`].
     ///
+    /// **Note:** This method is only available on platforms that support atomic
+    /// operations on `u8`.
+    ///
     /// [`Ordering`]: enum.Ordering.html
     /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
     /// [`Release`]: enum.Ordering.html#variant.Release
@@ -779,6 +805,9 @@ impl AtomicBool {
     /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
     /// using [`Release`] makes the load part [`Relaxed`].
     ///
+    /// **Note:** This method is only available on platforms that support atomic
+    /// operations on `u8`.
+    ///
     /// [`Ordering`]: enum.Ordering.html
     /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
     /// [`Release`]: enum.Ordering.html#variant.Release
@@ -981,6 +1010,9 @@ impl<T> AtomicPtr<T> {
     /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
     /// using [`Release`] makes the load part [`Relaxed`].
     ///
+    /// **Note:** This method is only available on platforms that support atomic
+    /// operations on pointers.
+    ///
     /// [`Ordering`]: enum.Ordering.html
     /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
     /// [`Release`]: enum.Ordering.html#variant.Release
@@ -1017,6 +1049,9 @@ impl<T> AtomicPtr<T> {
     /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
     /// happens, and using [`Release`] makes the load part [`Relaxed`].
     ///
+    /// **Note:** This method is only available on platforms that support atomic
+    /// operations on pointers.
+    ///
     /// [`Ordering`]: enum.Ordering.html
     /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
     /// [`Release`]: enum.Ordering.html#variant.Release
@@ -1058,6 +1093,9 @@ impl<T> AtomicPtr<T> {
     /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]
     /// and must be equivalent to or weaker than the success ordering.
     ///
+    /// **Note:** This method is only available on platforms that support atomic
+    /// operations on pointers.
+    ///
     /// [`Ordering`]: enum.Ordering.html
     /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
     /// [`Release`]: enum.Ordering.html#variant.Release
@@ -1118,6 +1156,9 @@ impl<T> AtomicPtr<T> {
     /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]
     /// and must be equivalent to or weaker than the success ordering.
     ///
+    /// **Note:** This method is only available on platforms that support atomic
+    /// operations on pointers.
+    ///
     /// [`compare_exchange`]: #method.compare_exchange
     /// [`Ordering`]: enum.Ordering.html
     /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
@@ -1223,6 +1264,13 @@ macro_rules! atomic_int {
         /// non-atomic types as well as information about the portability of
         /// this type, please see the [module-level documentation].
         ///
+        /// **Note:** This type is only available on platforms that support
+        /// atomic loads and stores of [`
+        #[doc = $s_int_type]
+        /// `](
+        #[doc = $int_ref]
+        /// ).
+        ///
         /// [module-level documentation]: index.html
         #[$stable]
         #[repr(C, align($align))]
@@ -1408,6 +1456,9 @@ of this operation. All ordering modes are possible. Note that using
 [`Acquire`] makes the store part of this operation [`Relaxed`], and
 using [`Release`] makes the load part [`Relaxed`].
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 [`Ordering`]: enum.Ordering.html
 [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 [`Release`]: enum.Ordering.html#variant.Release
@@ -1444,6 +1495,9 @@ might fail and hence just perform an `Acquire` load, but not have `Release` sema
 Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
 happens, and using [`Release`] makes the load part [`Relaxed`].
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 [`Ordering`]: enum.Ordering.html
 [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 [`Release`]: enum.Ordering.html#variant.Release
@@ -1496,6 +1550,9 @@ of this operation [`Relaxed`], and using [`Release`] makes the successful load
 [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]
 and must be equivalent to or weaker than the success ordering.
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 [`Ordering`]: enum.Ordering.html
 [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 [`Release`]: enum.Ordering.html#variant.Release
@@ -1558,6 +1615,9 @@ and must be equivalent to or weaker than the success ordering.
 [`Acquire`]: enum.Ordering.html#variant.Acquire
 [`SeqCst`]: enum.Ordering.html#variant.SeqCst
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 # Examples
 
 ```
@@ -1599,6 +1659,9 @@ of this operation. All ordering modes are possible. Note that using
 [`Acquire`] makes the store part of this operation [`Relaxed`], and
 using [`Release`] makes the load part [`Relaxed`].
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 [`Ordering`]: enum.Ordering.html
 [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 [`Release`]: enum.Ordering.html#variant.Release
@@ -1632,6 +1695,9 @@ of this operation. All ordering modes are possible. Note that using
 [`Acquire`] makes the store part of this operation [`Relaxed`], and
 using [`Release`] makes the load part [`Relaxed`].
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 [`Ordering`]: enum.Ordering.html
 [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 [`Release`]: enum.Ordering.html#variant.Release
@@ -1668,6 +1734,9 @@ of this operation. All ordering modes are possible. Note that using
 [`Acquire`] makes the store part of this operation [`Relaxed`], and
 using [`Release`] makes the load part [`Relaxed`].
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 [`Ordering`]: enum.Ordering.html
 [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 [`Release`]: enum.Ordering.html#variant.Release
@@ -1704,6 +1773,9 @@ of this operation. All ordering modes are possible. Note that using
 [`Acquire`] makes the store part of this operation [`Relaxed`], and
 using [`Release`] makes the load part [`Relaxed`].
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 [`Ordering`]: enum.Ordering.html
 [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 [`Release`]: enum.Ordering.html#variant.Release
@@ -1741,6 +1813,9 @@ of this operation. All ordering modes are possible. Note that using
 [`Acquire`] makes the store part of this operation [`Relaxed`], and
 using [`Release`] makes the load part [`Relaxed`].
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 [`Ordering`]: enum.Ordering.html
 [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 [`Release`]: enum.Ordering.html#variant.Release
@@ -1777,6 +1852,9 @@ of this operation. All ordering modes are possible. Note that using
 [`Acquire`] makes the store part of this operation [`Relaxed`], and
 using [`Release`] makes the load part [`Relaxed`].
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 [`Ordering`]: enum.Ordering.html
 [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 [`Release`]: enum.Ordering.html#variant.Release
@@ -1819,6 +1897,9 @@ of this operation [`Relaxed`], and using [`Release`] makes the final successful
 [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]
 and must be equivalent to or weaker than the success ordering.
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 [`bool`]: ../../../std/primitive.bool.html
 [`compare_exchange`]: #method.compare_exchange
 [`Ordering`]: enum.Ordering.html
@@ -1870,6 +1951,9 @@ of this operation. All ordering modes are possible. Note that using
 [`Acquire`] makes the store part of this operation [`Relaxed`], and
 using [`Release`] makes the load part [`Relaxed`].
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 [`Ordering`]: enum.Ordering.html
 [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 [`Release`]: enum.Ordering.html#variant.Release
@@ -1917,6 +2001,9 @@ of this operation. All ordering modes are possible. Note that using
 [`Acquire`] makes the store part of this operation [`Relaxed`], and
 using [`Release`] makes the load part [`Relaxed`].
 
+**Note**: This method is only available on platforms that support atomic
+operations on [`", $s_int_type, "`](", $int_ref, ").
+
 [`Ordering`]: enum.Ordering.html
 [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 [`Release`]: enum.Ordering.html#variant.Release
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index fa0f29acc7433..61692280d2a77 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -357,7 +357,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
                 | TerminatorKind::Unreachable
                 | TerminatorKind::SwitchInt { .. }
                 | TerminatorKind::Yield { .. }
-                | TerminatorKind::FalseEdges { .. }
+                | TerminatorKind::FalseEdge { .. }
                 | TerminatorKind::FalseUnwind { .. }
                 | TerminatorKind::InlineAsm { .. } => { /* nothing to do */ }
                 TerminatorKind::Call { cleanup: unwind, .. }
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 6c18e753d790b..30a84c4e47b03 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -1030,7 +1030,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             mir::TerminatorKind::GeneratorDrop | mir::TerminatorKind::Yield { .. } => {
                 bug!("generator ops in codegen")
             }
-            mir::TerminatorKind::FalseEdges { .. } | mir::TerminatorKind::FalseUnwind { .. } => {
+            mir::TerminatorKind::FalseEdge { .. } | mir::TerminatorKind::FalseUnwind { .. } => {
                 bug!("borrowck false edges in codegen")
             }
 
diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs
index 3d2ddf12a0a1f..05e7c9a0c780d 100644
--- a/src/librustc_lint/levels.rs
+++ b/src/librustc_lint/levels.rs
@@ -214,9 +214,9 @@ impl<'s> LintLevelsBuilder<'s> {
                 match store.check_lint_name(&name.as_str(), tool_name) {
                     CheckLintNameResult::Ok(ids) => {
                         let src = LintSource::Node(name, li.span(), reason);
-                        for id in ids {
-                            self.check_gated_lint(*id, attr.span);
-                            specs.insert(*id, (level, src));
+                        for &id in ids {
+                            self.check_gated_lint(id, attr.span);
+                            specs.insert(id, (level, src));
                         }
                     }
 
@@ -386,17 +386,18 @@ impl<'s> LintLevelsBuilder<'s> {
         BuilderPush { prev, changed: prev != self.cur }
     }
 
-    fn check_gated_lint(&self, id: LintId, span: Span) {
-        if id == LintId::of(builtin::UNSAFE_OP_IN_UNSAFE_FN)
-            && !self.sess.features_untracked().unsafe_block_in_unsafe_fn
-        {
-            feature_err(
-                &self.sess.parse_sess,
-                sym::unsafe_block_in_unsafe_fn,
-                span,
-                "the `unsafe_op_in_unsafe_fn` lint is unstable",
-            )
-            .emit();
+    /// Checks if the lint is gated on a feature that is not enabled.
+    fn check_gated_lint(&self, lint_id: LintId, span: Span) {
+        if let Some(feature) = lint_id.lint.feature_gate {
+            if !self.sess.features_untracked().enabled(feature) {
+                feature_err(
+                    &self.sess.parse_sess,
+                    feature,
+                    span,
+                    &format!("the `{}` lint is unstable", lint_id.lint.name_lower()),
+                )
+                .emit();
+            }
         }
     }
 
diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs
index 904424462bfe7..98973f1b6fb7d 100644
--- a/src/librustc_middle/mir/mod.rs
+++ b/src/librustc_middle/mir/mod.rs
@@ -1160,7 +1160,7 @@ pub enum TerminatorKind<'tcx> {
 
     /// A block where control flow only ever takes one real path, but borrowck
     /// needs to be more conservative.
-    FalseEdges {
+    FalseEdge {
         /// The target normal control flow will take.
         real_target: BasicBlock,
         /// A block control flow could conceptually jump to, but won't in
@@ -1314,7 +1314,7 @@ impl<'tcx> TerminatorKind<'tcx> {
                 Some(t).into_iter().chain(slice::from_ref(u))
             }
             SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]),
-            FalseEdges { ref real_target, ref imaginary_target } => {
+            FalseEdge { ref real_target, ref imaginary_target } => {
                 Some(real_target).into_iter().chain(slice::from_ref(imaginary_target))
             }
         }
@@ -1348,7 +1348,7 @@ impl<'tcx> TerminatorKind<'tcx> {
                 Some(t).into_iter().chain(slice::from_mut(u))
             }
             SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets[..]),
-            FalseEdges { ref mut real_target, ref mut imaginary_target } => {
+            FalseEdge { ref mut real_target, ref mut imaginary_target } => {
                 Some(real_target).into_iter().chain(slice::from_mut(imaginary_target))
             }
         }
@@ -1364,7 +1364,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::InlineAsm { .. } => None,
             TerminatorKind::Call { cleanup: ref unwind, .. }
             | TerminatorKind::Assert { cleanup: ref unwind, .. }
@@ -1384,7 +1384,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::InlineAsm { .. } => None,
             TerminatorKind::Call { cleanup: ref mut unwind, .. }
             | TerminatorKind::Assert { cleanup: ref mut unwind, .. }
@@ -1598,7 +1598,7 @@ impl<'tcx> TerminatorKind<'tcx> {
                 msg.fmt_assert_args(fmt)?;
                 write!(fmt, ")")
             }
-            FalseEdges { .. } => write!(fmt, "falseEdges"),
+            FalseEdge { .. } => write!(fmt, "falseEdge"),
             FalseUnwind { .. } => write!(fmt, "falseUnwind"),
             InlineAsm { template, ref operands, options, .. } => {
                 write!(fmt, "asm!(\"{}\"", InlineAsmTemplatePiece::to_string(template))?;
@@ -1683,7 +1683,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             }
             Assert { cleanup: None, .. } => vec!["".into()],
             Assert { .. } => vec!["success".into(), "unwind".into()],
-            FalseEdges { .. } => vec!["real".into(), "imaginary".into()],
+            FalseEdge { .. } => vec!["real".into(), "imaginary".into()],
             FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
             FalseUnwind { unwind: None, .. } => vec!["real".into()],
             InlineAsm { destination: Some(_), .. } => vec!["".into()],
diff --git a/src/librustc_middle/mir/type_foldable.rs b/src/librustc_middle/mir/type_foldable.rs
index 918133ba54210..97c6d6bf5f40b 100644
--- a/src/librustc_middle/mir/type_foldable.rs
+++ b/src/librustc_middle/mir/type_foldable.rs
@@ -74,8 +74,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
             Abort => Abort,
             Return => Return,
             Unreachable => Unreachable,
-            FalseEdges { real_target, imaginary_target } => {
-                FalseEdges { real_target, imaginary_target }
+            FalseEdge { real_target, imaginary_target } => {
+                FalseEdge { real_target, imaginary_target }
             }
             FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
             InlineAsm { template, ref operands, options, line_spans, destination } => InlineAsm {
@@ -134,7 +134,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
             | Return
             | GeneratorDrop
             | Unreachable
-            | FalseEdges { .. }
+            | FalseEdge { .. }
             | FalseUnwind { .. } => false,
         }
     }
diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs
index 351dc33dbe355..9f886cbc9fb5b 100644
--- a/src/librustc_middle/mir/visit.rs
+++ b/src/librustc_middle/mir/visit.rs
@@ -429,7 +429,7 @@ macro_rules! make_mir_visitor {
                     TerminatorKind::Abort |
                     TerminatorKind::GeneratorDrop |
                     TerminatorKind::Unreachable |
-                    TerminatorKind::FalseEdges { .. } |
+                    TerminatorKind::FalseEdge { .. } |
                     TerminatorKind::FalseUnwind { .. } => {
                     }
 
diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs
index 9c23ee74413cb..77d16458383d1 100644
--- a/src/librustc_mir/borrow_check/invalidation.rs
+++ b/src/librustc_mir/borrow_check/invalidation.rs
@@ -215,7 +215,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
             TerminatorKind::Goto { target: _ }
             | TerminatorKind::Abort
             | TerminatorKind::Unreachable
-            | TerminatorKind::FalseEdges { real_target: _, imaginary_target: _ }
+            | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
             | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {
                 // no data used, thus irrelevant to borrowck
             }
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index d17c111d0c42c..736cda83ca512 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -770,7 +770,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
             | TerminatorKind::Resume
             | TerminatorKind::Return
             | TerminatorKind::GeneratorDrop
-            | TerminatorKind::FalseEdges { real_target: _, imaginary_target: _ }
+            | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
             | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {
                 // no data used, thus irrelevant to borrowck
             }
@@ -814,7 +814,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
             | TerminatorKind::Call { .. }
             | TerminatorKind::Drop { .. }
             | TerminatorKind::DropAndReplace { .. }
-            | TerminatorKind::FalseEdges { real_target: _, imaginary_target: _ }
+            | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
             | TerminatorKind::FalseUnwind { real_target: _, unwind: _ }
             | TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index 377a0b6f25cab..e2255d170f9c9 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -1547,7 +1547,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
-            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::InlineAsm { .. } => {
                 // no checks needed for these
@@ -1843,7 +1843,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     self.assert_iscleanup(body, block_data, cleanup, true);
                 }
             }
-            TerminatorKind::FalseEdges { real_target, imaginary_target } => {
+            TerminatorKind::FalseEdge { real_target, imaginary_target } => {
                 self.assert_iscleanup(body, block_data, real_target, is_cleanup);
                 self.assert_iscleanup(body, block_data, imaginary_target, is_cleanup);
             }
diff --git a/src/librustc_mir/dataflow/framework/direction.rs b/src/librustc_mir/dataflow/framework/direction.rs
index 9e2a28853e151..da4ad9b6168ed 100644
--- a/src/librustc_mir/dataflow/framework/direction.rs
+++ b/src/librustc_mir/dataflow/framework/direction.rs
@@ -453,7 +453,7 @@ impl Direction for Forward {
                 propagate(target, exit_state);
             }
 
-            FalseEdges { real_target, imaginary_target } => {
+            FalseEdge { real_target, imaginary_target } => {
                 propagate(real_target, exit_state);
                 propagate(imaginary_target, exit_state);
             }
diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
index 9905265741534..608237087732e 100644
--- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs
+++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
@@ -203,7 +203,7 @@ where
             TerminatorKind::Abort
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Call { .. }
-            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Goto { .. }
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 4749d74684547..c0ab356756acf 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -365,7 +365,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             | TerminatorKind::Resume
             | TerminatorKind::Abort
             | TerminatorKind::GeneratorDrop
-            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::Unreachable => {}
 
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 3db16a71bab15..4a63884be4c4d 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -129,7 +129,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
             // These should never occur for MIR we actually run.
             DropAndReplace { .. }
-            | FalseEdges { .. }
+            | FalseEdge { .. }
             | FalseUnwind { .. }
             | Yield { .. }
             | GeneratorDrop => span_bug!(
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 297b899ef0bd6..f3d3666b99f9f 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -649,7 +649,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             | mir::TerminatorKind::Assert { .. } => {}
             mir::TerminatorKind::GeneratorDrop
             | mir::TerminatorKind::Yield { .. }
-            | mir::TerminatorKind::FalseEdges { .. }
+            | mir::TerminatorKind::FalseEdge { .. }
             | mir::TerminatorKind::FalseUnwind { .. } => bug!(),
         }
 
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index 1137c813470be..ab87d70da7da3 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -609,7 +609,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
             // instead.
             TerminatorKind::Abort
             | TerminatorKind::Assert { .. }
-            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Goto { .. }
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index e32bccc85ee6f..7dbb2ebad8b99 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -76,7 +76,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
             | TerminatorKind::Abort
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
-            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. } => {
                 // safe (at least as emitted during MIR construction)
             }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 92000e6411354..0ff60cbd55d3c 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -1013,7 +1013,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
             | TerminatorKind::DropAndReplace { .. }
             | TerminatorKind::Yield { .. }
             | TerminatorKind::GeneratorDrop
-            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::InlineAsm { .. } => {}
             // Every argument in our function calls can be const propagated.
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 461b13c4f6382..3509a9a5653c8 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -669,40 +669,33 @@ fn compute_storage_conflicts(
     storage_conflicts
 }
 
-fn compute_layout<'tcx>(
+/// Validates the typeck view of the generator against the actual set of types retained between
+/// yield points.
+fn sanitize_witness<'tcx>(
     tcx: TyCtxt<'tcx>,
-    source: MirSource<'tcx>,
+    body: &Body<'tcx>,
+    did: DefId,
+    witness: Ty<'tcx>,
     upvars: &Vec<Ty<'tcx>>,
-    interior: Ty<'tcx>,
-    always_live_locals: &storage::AlwaysLiveLocals,
-    movable: bool,
-    body: &mut Body<'tcx>,
-) -> (
-    FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
-    GeneratorLayout<'tcx>,
-    IndexVec<BasicBlock, Option<BitSet<Local>>>,
+    retained: &BitSet<Local>,
 ) {
-    // Use a liveness analysis to compute locals which are live across a suspension point
-    let LivenessInfo {
-        live_locals,
-        live_locals_at_suspension_points,
-        storage_conflicts,
-        storage_liveness,
-    } = locals_live_across_suspend_points(tcx, body, source, always_live_locals, movable);
-
-    // Erase regions from the types passed in from typeck so we can compare them with
-    // MIR types
     let allowed_upvars = tcx.erase_regions(upvars);
-    let allowed = match interior.kind {
+    let allowed = match witness.kind {
         ty::GeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
-        _ => bug!(),
+        _ => {
+            tcx.sess.delay_span_bug(
+                body.span,
+                &format!("unexpected generator witness type {:?}", witness.kind),
+            );
+            return;
+        }
     };
 
-    let param_env = tcx.param_env(source.def_id());
+    let param_env = tcx.param_env(did);
 
     for (local, decl) in body.local_decls.iter_enumerated() {
-        // Ignore locals which are internal or not live
-        if !live_locals.contains(local) || decl.internal {
+        // Ignore locals which are internal or not retained between yields.
+        if !retained.contains(local) || decl.internal {
             continue;
         }
         let decl_ty = tcx.normalize_erasing_regions(param_env, decl.ty);
@@ -715,10 +708,34 @@ fn compute_layout<'tcx>(
                 "Broken MIR: generator contains type {} in MIR, \
                        but typeck only knows about {}",
                 decl.ty,
-                interior
+                witness,
             );
         }
     }
+}
+
+fn compute_layout<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    source: MirSource<'tcx>,
+    upvars: &Vec<Ty<'tcx>>,
+    interior: Ty<'tcx>,
+    always_live_locals: &storage::AlwaysLiveLocals,
+    movable: bool,
+    body: &mut Body<'tcx>,
+) -> (
+    FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
+    GeneratorLayout<'tcx>,
+    IndexVec<BasicBlock, Option<BitSet<Local>>>,
+) {
+    // Use a liveness analysis to compute locals which are live across a suspension point
+    let LivenessInfo {
+        live_locals,
+        live_locals_at_suspension_points,
+        storage_conflicts,
+        storage_liveness,
+    } = locals_live_across_suspend_points(tcx, body, source, always_live_locals, movable);
+
+    sanitize_witness(tcx, body, source.def_id(), interior, upvars, &live_locals);
 
     // Gather live local types and their indices.
     let mut locals = IndexVec::<GeneratorSavedLocal, _>::new();
@@ -971,7 +988,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
-            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::InlineAsm { .. } => {}
 
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 35d55c4cb9b6d..47aa4fbf60c03 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -791,7 +791,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
             }
             TerminatorKind::Abort => {}
             TerminatorKind::Unreachable => {}
-            TerminatorKind::FalseEdges { ref mut real_target, ref mut imaginary_target } => {
+            TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => {
                 *real_target = self.update_target(*real_target);
                 *imaginary_target = self.update_target(*imaginary_target);
             }
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 5615aa84eecd7..5c78307d882fc 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -342,7 +342,7 @@ fn check_terminator(
 ) -> McfResult {
     let span = terminator.source_info.span;
     match &terminator.kind {
-        TerminatorKind::FalseEdges { .. }
+        TerminatorKind::FalseEdge { .. }
         | TerminatorKind::FalseUnwind { .. }
         | TerminatorKind::Goto { .. }
         | TerminatorKind::Return
diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs
index 69c0163b649d6..bf63bf24447a4 100644
--- a/src/librustc_mir/transform/remove_noop_landing_pads.rs
+++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs
@@ -65,7 +65,7 @@ impl RemoveNoopLandingPads {
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. } => {
                 terminator.successors().all(|&succ| nop_landing_pads.contains(succ))
             }
diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs
index 38e7f9d8ae45b..4c30a0946bccf 100644
--- a/src/librustc_mir/transform/simplify_branches.rs
+++ b/src/librustc_mir/transform/simplify_branches.rs
@@ -53,7 +53,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches {
                 } if (c.literal.try_eval_bool(tcx, param_env) == Some(true)) == expected => {
                     TerminatorKind::Goto { target }
                 }
-                TerminatorKind::FalseEdges { real_target, .. } => {
+                TerminatorKind::FalseEdge { real_target, .. } => {
                     TerminatorKind::Goto { target: real_target }
                 }
                 TerminatorKind::FalseUnwind { real_target, .. } => {
diff --git a/src/librustc_mir/transform/validate.rs b/src/librustc_mir/transform/validate.rs
index 7d301b2f49648..1433d39abfbba 100644
--- a/src/librustc_mir/transform/validate.rs
+++ b/src/librustc_mir/transform/validate.rs
@@ -159,7 +159,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     self.check_bb(location, *drop);
                 }
             }
-            TerminatorKind::FalseEdges { real_target, imaginary_target } => {
+            TerminatorKind::FalseEdge { real_target, imaginary_target } => {
                 self.check_bb(location, *real_target);
                 self.check_bb(location, *imaginary_target);
             }
diff --git a/src/librustc_mir_build/build/matches/util.rs b/src/librustc_mir_build/build/matches/util.rs
index a97ddeb060012..7d89a93129b1b 100644
--- a/src/librustc_mir_build/build/matches/util.rs
+++ b/src/librustc_mir_build/build/matches/util.rs
@@ -85,7 +85,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 self.cfg.terminate(
                     from_block,
                     source_info,
-                    TerminatorKind::FalseEdges { real_target, imaginary_target: target },
+                    TerminatorKind::FalseEdge { real_target, imaginary_target: target },
                 );
             }
             _ => self.cfg.goto(from_block, source_info, real_target),
diff --git a/src/librustc_mir_build/lints.rs b/src/librustc_mir_build/lints.rs
index dbafc98fb50f1..ac5d128a1baa2 100644
--- a/src/librustc_mir_build/lints.rs
+++ b/src/librustc_mir_build/lints.rs
@@ -128,7 +128,7 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> {
             | TerminatorKind::Call { .. }
             | TerminatorKind::Drop { .. }
             | TerminatorKind::DropAndReplace { .. }
-            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. } => ControlFlow::Continue,
@@ -153,7 +153,7 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> {
             TerminatorKind::Call { ref func, .. } => self.is_recursive_call(func),
 
             TerminatorKind::FalseUnwind { unwind: Some(imaginary_target), .. }
-            | TerminatorKind::FalseEdges { imaginary_target, .. } => imaginary_target == target,
+            | TerminatorKind::FalseEdge { imaginary_target, .. } => imaginary_target == target,
 
             _ => false,
         }
diff --git a/src/librustc_session/lint.rs b/src/librustc_session/lint.rs
index 8a66fac1e3634..ffb4579309075 100644
--- a/src/librustc_session/lint.rs
+++ b/src/librustc_session/lint.rs
@@ -85,6 +85,9 @@ pub struct Lint {
     pub future_incompatible: Option<FutureIncompatibleInfo>,
 
     pub is_plugin: bool,
+
+    /// `Some` if this lint is feature gated, otherwise `None`.
+    pub feature_gate: Option<Symbol>,
 }
 
 /// Extra information for a future incompatibility lint.
@@ -107,6 +110,7 @@ impl Lint {
             is_plugin: false,
             report_in_external_macro: false,
             future_incompatible: None,
+            feature_gate: None,
         }
     }
 
@@ -276,7 +280,9 @@ macro_rules! declare_lint {
         );
     );
     ($vis: vis $NAME: ident, $Level: ident, $desc: expr,
-     $(@future_incompatible = $fi:expr;)? $($v:ident),*) => (
+     $(@future_incompatible = $fi:expr;)?
+     $(@feature_gate = $gate:expr;)?
+     $($v:ident),*) => (
         $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
             name: stringify!($NAME),
             default_level: $crate::lint::$Level,
@@ -285,6 +291,7 @@ macro_rules! declare_lint {
             is_plugin: false,
             $($v: true,)*
             $(future_incompatible: Some($fi),)*
+            $(feature_gate: Some($gate),)*
             ..$crate::lint::Lint::default_fields_for_macro()
         };
     );
@@ -328,6 +335,7 @@ macro_rules! declare_tool_lint {
             report_in_external_macro: $external,
             future_incompatible: None,
             is_plugin: true,
+            feature_gate: None,
         };
     );
 }
diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs
index 7112ac35b082b..bb0d6e1a47ead 100644
--- a/src/librustc_session/lint/builtin.rs
+++ b/src/librustc_session/lint/builtin.rs
@@ -7,6 +7,7 @@
 use crate::lint::FutureIncompatibleInfo;
 use crate::{declare_lint, declare_lint_pass};
 use rustc_span::edition::Edition;
+use rustc_span::symbol::sym;
 
 declare_lint! {
     pub ILL_FORMED_ATTRIBUTE_INPUT,
@@ -530,6 +531,7 @@ declare_lint! {
     pub UNSAFE_OP_IN_UNSAFE_FN,
     Allow,
     "unsafe operations in unsafe functions without an explicit unsafe block are deprecated",
+    @feature_gate = sym::unsafe_block_in_unsafe_fn;
 }
 
 declare_lint_pass! {
diff --git a/src/librustc_ty/needs_drop.rs b/src/librustc_ty/needs_drop.rs
index c54704e7877f1..439bec1702eae 100644
--- a/src/librustc_ty/needs_drop.rs
+++ b/src/librustc_ty/needs_drop.rs
@@ -99,7 +99,7 @@ where
                         }
                     }
 
-                    ty::Generator(_, substs, _) => {
+                    ty::Generator(def_id, substs, _) => {
                         let substs = substs.as_generator();
                         for upvar_ty in substs.upvar_tys() {
                             queue_type(self, upvar_ty);
@@ -108,7 +108,13 @@ where
                         let witness = substs.witness();
                         let interior_tys = match &witness.kind {
                             ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys),
-                            _ => bug!(),
+                            _ => {
+                                tcx.sess.delay_span_bug(
+                                    tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP),
+                                    &format!("unexpected generator witness type {:?}", witness),
+                                );
+                                return Some(Err(AlwaysRequiresDrop));
+                            }
                         };
 
                         for interior_ty in interior_tys {
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 06293a987124e..1690b946bb625 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -225,11 +225,6 @@ where
 {
     let warnings_lint_name = lint::builtin::WARNINGS.name;
 
-    // Whitelist feature-gated lints to avoid feature errors when trying to
-    // allow all lints.
-    // FIXME(#72694): handle feature-gated lints properly.
-    let unsafe_op_in_unsafe_fn_name = rustc_lint::builtin::UNSAFE_OP_IN_UNSAFE_FN.name;
-
     whitelisted_lints.push(warnings_lint_name.to_owned());
     whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());
 
@@ -241,7 +236,9 @@ where
 
     let lint_opts = lints()
         .filter_map(|lint| {
-            if lint.name == warnings_lint_name || lint.name == unsafe_op_in_unsafe_fn_name {
+            // Whitelist feature-gated lints to avoid feature errors when trying to
+            // allow all lints.
+            if lint.name == warnings_lint_name || lint.feature_gate.is_some() {
                 None
             } else {
                 filter_call(lint)
diff --git a/src/test/mir-opt/exponential-or/rustc.match_tuple.SimplifyCfg-initial.after.mir b/src/test/mir-opt/exponential-or/rustc.match_tuple.SimplifyCfg-initial.after.mir
index 03d258d8f7289..3c1c02da42ff8 100644
--- a/src/test/mir-opt/exponential-or/rustc.match_tuple.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/exponential-or/rustc.match_tuple.SimplifyCfg-initial.after.mir
@@ -87,7 +87,7 @@ fn match_tuple(_1: (u32, bool, std::option::Option<i32>, u32)) -> u32 {
     }
 
     bb8: {
-        falseEdges -> [real: bb9, imaginary: bb1]; // scope 0 at $DIR/exponential-or.rs:8:9: 8:79
+        falseEdge -> [real: bb9, imaginary: bb1]; // scope 0 at $DIR/exponential-or.rs:8:9: 8:79
     }
 
     bb9: {
diff --git a/src/test/mir-opt/issue-38669/rustc.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/issue-38669/rustc.main.SimplifyCfg-initial.after.mir
index fa7bd2563ae44..7b58dc1f624a5 100644
--- a/src/test/mir-opt/issue-38669/rustc.main.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/issue-38669/rustc.main.SimplifyCfg-initial.after.mir
@@ -41,7 +41,7 @@ fn main() -> () {
     }
 
     bb4: {
-        falseEdges -> [real: bb6, imaginary: bb5]; // scope 1 at $DIR/issue-38669.rs:7:9: 9:10
+        falseEdge -> [real: bb6, imaginary: bb5]; // scope 1 at $DIR/issue-38669.rs:7:9: 9:10
     }
 
     bb5: {
diff --git a/src/test/mir-opt/issue-49232/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue-49232/rustc.main.mir_map.0.mir
index abf33cce133dd..7299a683a9f0b 100644
--- a/src/test/mir-opt/issue-49232/rustc.main.mir_map.0.mir
+++ b/src/test/mir-opt/issue-49232/rustc.main.mir_map.0.mir
@@ -43,7 +43,7 @@ fn main() -> () {
     }
 
     bb5: {
-        falseEdges -> [real: bb7, imaginary: bb6]; // scope 0 at $DIR/issue-49232.rs:9:17: 9:22
+        falseEdge -> [real: bb7, imaginary: bb6]; // scope 0 at $DIR/issue-49232.rs:9:17: 9:22
     }
 
     bb6: {
diff --git a/src/test/mir-opt/loop_test/rustc.main.SimplifyCfg-qualify-consts.after.mir b/src/test/mir-opt/loop_test/rustc.main.SimplifyCfg-qualify-consts.after.mir
index 38e04a6399fc2..7046ebb793466 100644
--- a/src/test/mir-opt/loop_test/rustc.main.SimplifyCfg-qualify-consts.after.mir
+++ b/src/test/mir-opt/loop_test/rustc.main.SimplifyCfg-qualify-consts.after.mir
@@ -31,7 +31,7 @@ fn main() -> () {
     }
 
     bb2: {
-        falseEdges -> [real: bb4, imaginary: bb3]; // scope 0 at $DIR/loop_test.rs:10:5: 12:6
+        falseEdge -> [real: bb4, imaginary: bb3]; // scope 0 at $DIR/loop_test.rs:10:5: 12:6
     }
 
     bb3: {
diff --git a/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after.mir b/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after.mir
index 63974bda26038..1f6b2c982fee0 100644
--- a/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after.mir
@@ -39,7 +39,7 @@ fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 {
     }
 
     bb2: {
-        falseEdges -> [real: bb9, imaginary: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:16:9: 16:22
+        falseEdge -> [real: bb9, imaginary: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:16:9: 16:22
     }
 
     bb3: {
@@ -47,7 +47,7 @@ fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 {
     }
 
     bb4: {
-        falseEdges -> [real: bb18, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:16:25: 16:38
+        falseEdge -> [real: bb18, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:16:25: 16:38
     }
 
     bb5: {
@@ -55,7 +55,7 @@ fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 {
     }
 
     bb6: {
-        falseEdges -> [real: bb26, imaginary: bb7]; // scope 0 at $DIR/match-arm-scopes.rs:17:9: 17:21
+        falseEdge -> [real: bb26, imaginary: bb7]; // scope 0 at $DIR/match-arm-scopes.rs:17:9: 17:21
     }
 
     bb7: {
@@ -92,7 +92,7 @@ fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 {
     }
 
     bb10: {
-        falseEdges -> [real: bb12, imaginary: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
+        falseEdge -> [real: bb12, imaginary: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
     }
 
     bb11: {
@@ -145,7 +145,7 @@ fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 {
         StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:16:78: 16:79
         StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:78: 16:79
         StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:78: 16:79
-        falseEdges -> [real: bb3, imaginary: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
+        falseEdge -> [real: bb3, imaginary: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
     }
 
     bb18: {
@@ -163,7 +163,7 @@ fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 {
     }
 
     bb19: {
-        falseEdges -> [real: bb21, imaginary: bb20]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
+        falseEdge -> [real: bb21, imaginary: bb20]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
     }
 
     bb20: {
@@ -204,7 +204,7 @@ fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 {
         StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:16:78: 16:79
         StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:78: 16:79
         StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:78: 16:79
-        falseEdges -> [real: bb5, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
+        falseEdge -> [real: bb5, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
     }
 
     bb24: {
diff --git a/src/test/mir-opt/match_false_edges/rustc.full_tested_match.PromoteTemps.after.mir b/src/test/mir-opt/match_false_edges/rustc.full_tested_match.PromoteTemps.after.mir
index db888bc4b87b2..3e1dec697b76f 100644
--- a/src/test/mir-opt/match_false_edges/rustc.full_tested_match.PromoteTemps.after.mir
+++ b/src/test/mir-opt/match_false_edges/rustc.full_tested_match.PromoteTemps.after.mir
@@ -60,11 +60,11 @@ fn full_tested_match() -> () {
     }
 
     bb3: {
-        falseEdges -> [real: bb6, imaginary: bb4]; // scope 0 at $DIR/match_false_edges.rs:16:9: 16:16
+        falseEdge -> [real: bb6, imaginary: bb4]; // scope 0 at $DIR/match_false_edges.rs:16:9: 16:16
     }
 
     bb4: {
-        falseEdges -> [real: bb10, imaginary: bb2]; // scope 0 at $DIR/match_false_edges.rs:17:9: 17:16
+        falseEdge -> [real: bb10, imaginary: bb2]; // scope 0 at $DIR/match_false_edges.rs:17:9: 17:16
     }
 
     bb5: {
diff --git a/src/test/mir-opt/match_false_edges/rustc.full_tested_match2.PromoteTemps.before.mir b/src/test/mir-opt/match_false_edges/rustc.full_tested_match2.PromoteTemps.before.mir
index 96aa9e828d784..4e6dc6e13ff62 100644
--- a/src/test/mir-opt/match_false_edges/rustc.full_tested_match2.PromoteTemps.before.mir
+++ b/src/test/mir-opt/match_false_edges/rustc.full_tested_match2.PromoteTemps.before.mir
@@ -42,11 +42,11 @@ fn full_tested_match2() -> () {
     }
 
     bb2: {
-        falseEdges -> [real: bb10, imaginary: bb4]; // scope 0 at $DIR/match_false_edges.rs:28:9: 28:13
+        falseEdge -> [real: bb10, imaginary: bb4]; // scope 0 at $DIR/match_false_edges.rs:28:9: 28:13
     }
 
     bb3: {
-        falseEdges -> [real: bb6, imaginary: bb2]; // scope 0 at $DIR/match_false_edges.rs:27:9: 27:16
+        falseEdge -> [real: bb6, imaginary: bb2]; // scope 0 at $DIR/match_false_edges.rs:27:9: 27:16
     }
 
     bb4: {
@@ -112,7 +112,7 @@ fn full_tested_match2() -> () {
     bb9: {
         StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:27:37: 27:38
         StorageDead(_6);                 // scope 0 at $DIR/match_false_edges.rs:27:37: 27:38
-        falseEdges -> [real: bb4, imaginary: bb2]; // scope 0 at $DIR/match_false_edges.rs:27:20: 27:27
+        falseEdge -> [real: bb4, imaginary: bb2]; // scope 0 at $DIR/match_false_edges.rs:27:20: 27:27
     }
 
     bb10: {
diff --git a/src/test/mir-opt/match_false_edges/rustc.main.PromoteTemps.before.mir b/src/test/mir-opt/match_false_edges/rustc.main.PromoteTemps.before.mir
index 63a7c4bc43d7a..b54058ca73f6f 100644
--- a/src/test/mir-opt/match_false_edges/rustc.main.PromoteTemps.before.mir
+++ b/src/test/mir-opt/match_false_edges/rustc.main.PromoteTemps.before.mir
@@ -53,11 +53,11 @@ fn main() -> () {
     }
 
     bb2: {
-        falseEdges -> [real: bb10, imaginary: bb5]; // scope 0 at $DIR/match_false_edges.rs:37:9: 37:11
+        falseEdge -> [real: bb10, imaginary: bb5]; // scope 0 at $DIR/match_false_edges.rs:37:9: 37:11
     }
 
     bb3: {
-        falseEdges -> [real: bb6, imaginary: bb2]; // scope 0 at $DIR/match_false_edges.rs:36:9: 36:17
+        falseEdge -> [real: bb6, imaginary: bb2]; // scope 0 at $DIR/match_false_edges.rs:36:9: 36:17
     }
 
     bb4: {
@@ -75,7 +75,7 @@ fn main() -> () {
     }
 
     bb5: {
-        falseEdges -> [real: bb11, imaginary: bb4]; // scope 0 at $DIR/match_false_edges.rs:38:9: 38:16
+        falseEdge -> [real: bb11, imaginary: bb4]; // scope 0 at $DIR/match_false_edges.rs:38:9: 38:16
     }
 
     bb6: {
@@ -117,7 +117,7 @@ fn main() -> () {
     bb9: {
         StorageDead(_8);                 // scope 0 at $DIR/match_false_edges.rs:36:33: 36:34
         StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:36:33: 36:34
-        falseEdges -> [real: bb2, imaginary: bb2]; // scope 0 at $DIR/match_false_edges.rs:36:21: 36:28
+        falseEdge -> [real: bb2, imaginary: bb2]; // scope 0 at $DIR/match_false_edges.rs:36:21: 36:28
     }
 
     bb10: {
@@ -176,7 +176,7 @@ fn main() -> () {
     bb14: {
         StorageDead(_12);                // scope 0 at $DIR/match_false_edges.rs:38:34: 38:35
         StorageDead(_11);                // scope 0 at $DIR/match_false_edges.rs:38:34: 38:35
-        falseEdges -> [real: bb4, imaginary: bb4]; // scope 0 at $DIR/match_false_edges.rs:38:20: 38:29
+        falseEdge -> [real: bb4, imaginary: bb4]; // scope 0 at $DIR/match_false_edges.rs:38:20: 38:29
     }
 
     bb15: {
diff --git a/src/test/mir-opt/match_test/rustc.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/match_test/rustc.main.SimplifyCfg-initial.after.mir
index 9408248b25dd3..5996496406a9f 100644
--- a/src/test/mir-opt/match_test/rustc.main.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/match_test/rustc.main.SimplifyCfg-initial.after.mir
@@ -61,7 +61,7 @@ fn main() -> () {
     }
 
     bb2: {
-        falseEdges -> [real: bb9, imaginary: bb6]; // scope 2 at $DIR/match_test.rs:13:9: 13:14
+        falseEdge -> [real: bb9, imaginary: bb6]; // scope 2 at $DIR/match_test.rs:13:9: 13:14
     }
 
     bb3: {
@@ -98,7 +98,7 @@ fn main() -> () {
     }
 
     bb6: {
-        falseEdges -> [real: bb12, imaginary: bb8]; // scope 2 at $DIR/match_test.rs:14:9: 14:16
+        falseEdge -> [real: bb12, imaginary: bb8]; // scope 2 at $DIR/match_test.rs:14:9: 14:16
     }
 
     bb7: {
@@ -106,7 +106,7 @@ fn main() -> () {
     }
 
     bb8: {
-        falseEdges -> [real: bb13, imaginary: bb3]; // scope 2 at $DIR/match_test.rs:15:9: 15:11
+        falseEdge -> [real: bb13, imaginary: bb3]; // scope 2 at $DIR/match_test.rs:15:9: 15:11
     }
 
     bb9: {
@@ -131,7 +131,7 @@ fn main() -> () {
 
     bb11: {
         StorageDead(_9);                 // scope 2 at $DIR/match_test.rs:13:24: 13:25
-        falseEdges -> [real: bb3, imaginary: bb6]; // scope 2 at $DIR/match_test.rs:13:18: 13:19
+        falseEdge -> [real: bb3, imaginary: bb6]; // scope 2 at $DIR/match_test.rs:13:18: 13:19
     }
 
     bb12: {
diff --git a/src/test/mir-opt/nll/region-subtyping-basic/32bit/rustc.main.nll.0.mir b/src/test/mir-opt/nll/region-subtyping-basic/32bit/rustc.main.nll.0.mir
index 3e0867d9b09d9..e3f113fea2851 100644
--- a/src/test/mir-opt/nll/region-subtyping-basic/32bit/rustc.main.nll.0.mir
+++ b/src/test/mir-opt/nll/region-subtyping-basic/32bit/rustc.main.nll.0.mir
@@ -102,7 +102,7 @@ fn main() -> () {
     }
 
     bb3: {
-        falseEdges -> [real: bb5, imaginary: bb4]; // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        falseEdge -> [real: bb5, imaginary: bb4]; // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
     }
 
     bb4: {
diff --git a/src/test/mir-opt/nll/region-subtyping-basic/64bit/rustc.main.nll.0.mir b/src/test/mir-opt/nll/region-subtyping-basic/64bit/rustc.main.nll.0.mir
index 61db4dba58627..a69952ff07f34 100644
--- a/src/test/mir-opt/nll/region-subtyping-basic/64bit/rustc.main.nll.0.mir
+++ b/src/test/mir-opt/nll/region-subtyping-basic/64bit/rustc.main.nll.0.mir
@@ -102,7 +102,7 @@ fn main() -> () {
     }
 
     bb3: {
-        falseEdges -> [real: bb5, imaginary: bb4]; // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        falseEdge -> [real: bb5, imaginary: bb4]; // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
     }
 
     bb4: {
diff --git a/src/test/mir-opt/simple-match/32bit/rustc.match_bool.mir_map.0.mir b/src/test/mir-opt/simple-match/32bit/rustc.match_bool.mir_map.0.mir
index 3a7d6a7ca3c61..cc2738b5e50a3 100644
--- a/src/test/mir-opt/simple-match/32bit/rustc.match_bool.mir_map.0.mir
+++ b/src/test/mir-opt/simple-match/32bit/rustc.match_bool.mir_map.0.mir
@@ -14,7 +14,7 @@ fn match_bool(_1: bool) -> usize {
     }
 
     bb2: {
-        falseEdges -> [real: bb4, imaginary: bb3]; // scope 0 at $DIR/simple-match.rs:7:9: 7:13
+        falseEdge -> [real: bb4, imaginary: bb3]; // scope 0 at $DIR/simple-match.rs:7:9: 7:13
     }
 
     bb3: {
diff --git a/src/test/mir-opt/simple-match/64bit/rustc.match_bool.mir_map.0.mir b/src/test/mir-opt/simple-match/64bit/rustc.match_bool.mir_map.0.mir
index 170181177b26a..309041abef9be 100644
--- a/src/test/mir-opt/simple-match/64bit/rustc.match_bool.mir_map.0.mir
+++ b/src/test/mir-opt/simple-match/64bit/rustc.match_bool.mir_map.0.mir
@@ -14,7 +14,7 @@ fn match_bool(_1: bool) -> usize {
     }
 
     bb2: {
-        falseEdges -> [real: bb4, imaginary: bb3]; // scope 0 at $DIR/simple-match.rs:7:9: 7:13
+        falseEdge -> [real: bb4, imaginary: bb3]; // scope 0 at $DIR/simple-match.rs:7:9: 7:13
     }
 
     bb3: {
diff --git a/src/test/mir-opt/simplify_cfg/rustc.main.SimplifyCfg-initial.diff b/src/test/mir-opt/simplify_cfg/rustc.main.SimplifyCfg-initial.diff
index 0cc2258f46364..1ba05b1cb3881 100644
--- a/src/test/mir-opt/simplify_cfg/rustc.main.SimplifyCfg-initial.diff
+++ b/src/test/mir-opt/simplify_cfg/rustc.main.SimplifyCfg-initial.diff
@@ -45,9 +45,9 @@
       }
   
 -     bb6: {
--         falseEdges -> [real: bb8, imaginary: bb7]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
+-         falseEdge -> [real: bb8, imaginary: bb7]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
 +     bb4: {
-+         falseEdges -> [real: bb6, imaginary: bb5]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
++         falseEdge -> [real: bb6, imaginary: bb5]; // scope 0 at $DIR/simplify_cfg.rs:7:9: 9:10
       }
   
 -     bb7: {