Auto merge of #57821 - RalfJung:miri, r=oli-obk

update miri

r? @oli-obk
diff --git a/src/doc/unstable-book/src/library-features/is-sorted.md b/src/doc/unstable-book/src/library-features/is-sorted.md
new file mode 100644
index 0000000..e3b7dc3
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/is-sorted.md
@@ -0,0 +1,11 @@
+# `is_sorted`
+
+The tracking issue for this feature is: [#53485]
+
+[#53485]: https://github.com/rust-lang/rust/issues/53485
+
+------------------------
+
+Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`;
+add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to
+`Iterator`.
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index 0ad29af..ac21586 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -2605,6 +2605,95 @@
             }
         }
     }
+
+    /// Checks if the elements of this iterator are sorted.
+    ///
+    /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the
+    /// iterator yields exactly zero or one element, `true` is returned.
+    ///
+    /// Note that if `Self::Item` is only `PartialOrd`, but not `Ord`, the above definition
+    /// implies that this function returns `false` if any two consecutive items are not
+    /// comparable.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_sorted)]
+    ///
+    /// assert!([1, 2, 2, 9].iter().is_sorted());
+    /// assert!(![1, 3, 2, 4].iter().is_sorted());
+    /// assert!([0].iter().is_sorted());
+    /// assert!(std::iter::empty::<i32>().is_sorted());
+    /// assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted());
+    /// ```
+    #[inline]
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    fn is_sorted(self) -> bool
+    where
+        Self: Sized,
+        Self::Item: PartialOrd,
+    {
+        self.is_sorted_by(|a, b| a.partial_cmp(b))
+    }
+
+    /// Checks if the elements of this iterator are sorted using the given comparator function.
+    ///
+    /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare`
+    /// function to determine the ordering of two elements. Apart from that, it's equivalent to
+    /// [`is_sorted`]; see its documentation for more information.
+    ///
+    /// [`is_sorted`]: trait.Iterator.html#method.is_sorted
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    fn is_sorted_by<F>(mut self, mut compare: F) -> bool
+    where
+        Self: Sized,
+        F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>
+    {
+        let mut last = match self.next() {
+            Some(e) => e,
+            None => return true,
+        };
+
+        while let Some(curr) = self.next() {
+            if compare(&last, &curr)
+                .map(|o| o == Ordering::Greater)
+                .unwrap_or(true)
+            {
+                return false;
+            }
+            last = curr;
+        }
+
+        true
+    }
+
+    /// Checks if the elements of this iterator are sorted using the given key extraction
+    /// function.
+    ///
+    /// Instead of comparing the iterator's elements directly, this function compares the keys of
+    /// the elements, as determined by `f`. Apart from that, it's equivalent to [`is_sorted`]; see
+    /// its documentation for more information.
+    ///
+    /// [`is_sorted`]: trait.Iterator.html#method.is_sorted
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_sorted)]
+    ///
+    /// assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len()));
+    /// assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+    /// ```
+    #[inline]
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    fn is_sorted_by_key<F, K>(self, mut f: F) -> bool
+    where
+        Self: Sized,
+        F: FnMut(&Self::Item) -> K,
+        K: PartialOrd
+    {
+        self.is_sorted_by(|a, b| f(a).partial_cmp(&f(b)))
+    }
 }
 
 /// Select an element from an iterator based on the given "projection"
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 33c0da8..df32cfa 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -79,6 +79,7 @@
 #![feature(extern_types)]
 #![feature(fundamental)]
 #![feature(intrinsics)]
+#![feature(is_sorted)]
 #![feature(iter_once_with)]
 #![feature(lang_items)]
 #![feature(link_llvm_intrinsics)]
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 6827364..41caa17 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -10,9 +10,9 @@
 use str::FromStr;
 
 macro_rules! impl_nonzero_fmt {
-    ( ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
+    ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
         $(
-            #[stable(feature = "nonzero", since = "1.28.0")]
+            #[$stability]
             impl fmt::$Trait for $Ty {
                 #[inline]
                 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -31,7 +31,7 @@
 }
 
 macro_rules! nonzero_integers {
-    ( $( $Ty: ident($Int: ty); )+ ) => {
+    ( $( #[$stability: meta] $Ty: ident($Int: ty); )+ ) => {
         $(
             doc_comment! {
                 concat!("An integer that is known not to equal zero.
@@ -41,10 +41,10 @@
 
 ```rust
 use std::mem::size_of;
-assert_eq!(size_of::<Option<std::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int),
+assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int),
 ">());
 ```"),
-                #[stable(feature = "nonzero", since = "1.28.0")]
+                #[$stability]
                 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
                 #[repr(transparent)]
                 #[rustc_layout_scalar_valid_range_start(1)]
@@ -57,14 +57,14 @@
                 /// # Safety
                 ///
                 /// The value must not be zero.
-                #[stable(feature = "nonzero", since = "1.28.0")]
+                #[$stability]
                 #[inline]
                 pub const unsafe fn new_unchecked(n: $Int) -> Self {
                     $Ty(n)
                 }
 
                 /// Create a non-zero if the given value is not zero.
-                #[stable(feature = "nonzero", since = "1.28.0")]
+                #[$stability]
                 #[inline]
                 pub fn new(n: $Int) -> Option<Self> {
                     if n != 0 {
@@ -75,7 +75,7 @@
                 }
 
                 /// Returns the value as a primitive type.
-                #[stable(feature = "nonzero", since = "1.28.0")]
+                #[$stability]
                 #[inline]
                 pub const fn get(self) -> $Int {
                     self.0
@@ -91,19 +91,25 @@
             }
 
             impl_nonzero_fmt! {
-                (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty
+                #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty
             }
         )+
     }
 }
 
 nonzero_integers! {
-    NonZeroU8(u8);
-    NonZeroU16(u16);
-    NonZeroU32(u32);
-    NonZeroU64(u64);
-    NonZeroU128(u128);
-    NonZeroUsize(usize);
+    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8);
+    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16);
+    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32);
+    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64);
+    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128);
+    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
 }
 
 /// Provides intentionally-wrapped arithmetic on `T`.
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 7fdc2ac..df4d97e 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -1783,7 +1783,7 @@
     /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
     /// a[1..5].rotate_left(1);
     /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
-   /// ```
+    /// ```
     #[stable(feature = "slice_rotate", since = "1.26.0")]
     pub fn rotate_left(&mut self, mid: usize) {
         assert!(mid <= self.len());
@@ -2250,6 +2250,77 @@
              from_raw_parts_mut(mut_ptr.add(rest.len() - ts_len), ts_len))
         }
     }
+
+    /// Checks if the elements of this slice are sorted.
+    ///
+    /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the
+    /// slice yields exactly zero or one element, `true` is returned.
+    ///
+    /// Note that if `Self::Item` is only `PartialOrd`, but not `Ord`, the above definition
+    /// implies that this function returns `false` if any two consecutive items are not
+    /// comparable.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_sorted)]
+    /// let empty: [i32; 0] = [];
+    ///
+    /// assert!([1, 2, 2, 9].is_sorted());
+    /// assert!(![1, 3, 2, 4].is_sorted());
+    /// assert!([0].is_sorted());
+    /// assert!(empty.is_sorted());
+    /// assert!(![0.0, 1.0, std::f32::NAN].is_sorted());
+    /// ```
+    #[inline]
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    pub fn is_sorted(&self) -> bool
+    where
+        T: PartialOrd,
+    {
+        self.is_sorted_by(|a, b| a.partial_cmp(b))
+    }
+
+    /// Checks if the elements of this slice are sorted using the given comparator function.
+    ///
+    /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare`
+    /// function to determine the ordering of two elements. Apart from that, it's equivalent to
+    /// [`is_sorted`]; see its documentation for more information.
+    ///
+    /// [`is_sorted`]: #method.is_sorted
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    pub fn is_sorted_by<F>(&self, mut compare: F) -> bool
+    where
+        F: FnMut(&T, &T) -> Option<Ordering>
+    {
+        self.iter().is_sorted_by(|a, b| compare(*a, *b))
+    }
+
+    /// Checks if the elements of this slice are sorted using the given key extraction function.
+    ///
+    /// Instead of comparing the slice's elements directly, this function compares the keys of the
+    /// elements, as determined by `f`. Apart from that, it's equivalent to [`is_sorted`]; see its
+    /// documentation for more information.
+    ///
+    /// [`is_sorted`]: #method.is_sorted
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_sorted)]
+    ///
+    /// assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
+    /// assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+    /// ```
+    #[inline]
+    #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    pub fn is_sorted_by_key<F, K>(&self, mut f: F) -> bool
+    where
+        F: FnMut(&T) -> K,
+        K: PartialOrd
+    {
+        self.is_sorted_by(|a, b| f(a).partial_cmp(&f(b)))
+    }
 }
 
 #[lang = "slice_u8"]
@@ -2773,7 +2844,13 @@
 
 // The shared definition of the `Iter` and `IterMut` iterators
 macro_rules! iterator {
-    (struct $name:ident -> $ptr:ty, $elem:ty, $raw_mut:tt, $( $mut_:tt )*) => {
+    (
+        struct $name:ident -> $ptr:ty,
+        $elem:ty,
+        $raw_mut:tt,
+        {$( $mut_:tt )*},
+        {$($extra:tt)*}
+    ) => {
         impl<'a, T> $name<'a, T> {
             // Helper function for creating a slice from the iterator.
             #[inline(always)]
@@ -2950,6 +3027,8 @@
                         i
                     })
             }
+
+            $($extra)*
         }
 
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -3087,7 +3166,17 @@
     }
 }
 
-iterator!{struct Iter -> *const T, &'a T, const, /* no mut */}
+iterator!{struct Iter -> *const T, &'a T, const, {/* no mut */}, {
+    fn is_sorted_by<F>(self, mut compare: F) -> bool
+    where
+        Self: Sized,
+        F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>,
+    {
+        self.as_slice().windows(2).all(|w| {
+            compare(&&w[0], &&w[1]).map(|o| o != Ordering::Greater).unwrap_or(false)
+        })
+    }
+}}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for Iter<'_, T> {
@@ -3188,7 +3277,7 @@
     }
 }
 
-iterator!{struct IterMut -> *mut T, &'a mut T, mut, mut}
+iterator!{struct IterMut -> *mut T, &'a mut T, mut, {mut}, {}}
 
 /// An internal abstraction over the splitting iterators, so that
 /// splitn, splitn_mut etc can be implemented once.
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 3944bc7..0fa9974 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -2235,3 +2235,16 @@
     assert_eq!((0..10).flat_map(f).flat_map(g).sum::<usize>(),
                 (0..10).flat_map(|x| f(x).flat_map(g)).sum::<usize>());
 }
+
+#[test]
+fn test_is_sorted() {
+    assert!([1, 2, 2, 9].iter().is_sorted());
+    assert!(![1, 3, 2].iter().is_sorted());
+    assert!([0].iter().is_sorted());
+    assert!(std::iter::empty::<i32>().is_sorted());
+    assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted());
+    assert!([-2, -1, 0, 3].iter().is_sorted());
+    assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+    assert!(!["c", "bb", "aaa"].iter().is_sorted());
+    assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len()));
+}
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index a9b8dec..3e8549f 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -10,6 +10,7 @@
 #![feature(flt2dec)]
 #![feature(fmt_internals)]
 #![feature(hashmap_internals)]
+#![feature(is_sorted)]
 #![feature(iter_copied)]
 #![feature(iter_nth_back)]
 #![feature(iter_once_with)]
diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs
index c813bf2..4532568 100644
--- a/src/libcore/tests/nonzero.rs
+++ b/src/libcore/tests/nonzero.rs
@@ -1,4 +1,4 @@
-use core::num::NonZeroU32;
+use core::num::{NonZeroU32, NonZeroI32};
 use core::option::Option;
 use core::option::Option::{Some, None};
 use std::mem::size_of;
@@ -13,6 +13,7 @@
 #[test]
 fn test_size_nonzero_in_option() {
     assert_eq!(size_of::<NonZeroU32>(), size_of::<Option<NonZeroU32>>());
+    assert_eq!(size_of::<NonZeroI32>(), size_of::<Option<NonZeroI32>>());
 }
 
 #[test]
@@ -118,3 +119,10 @@
     let num: u32 = nz.into();
     assert_eq!(num, 1u32);
 }
+
+#[test]
+fn test_from_signed_nonzero() {
+    let nz = NonZeroI32::new(1).unwrap();
+    let num: i32 = nz.into();
+    assert_eq!(num, 1i32);
+}
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 2c96efb..e210e83 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -1317,3 +1317,18 @@
     // 2 is greater than 1, so this range is invalid.
     bytes.copy_within(2..1, 0);
 }
+
+#[test]
+fn test_is_sorted() {
+    let empty: [i32; 0] = [];
+
+    assert!([1, 2, 2, 9].is_sorted());
+    assert!(![1, 3, 2].is_sorted());
+    assert!([0].is_sorted());
+    assert!(empty.is_sorted());
+    assert!(![0.0, 1.0, std::f32::NAN].is_sorted());
+    assert!([-2, -1, 0, 3].is_sorted());
+    assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+    assert!(!["c", "bb", "aaa"].is_sorted());
+    assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
+}
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index d9ca37c..c3e4f0c 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -455,11 +455,20 @@
             Node::AnonConst(_) => {
                 BodyOwnerKind::Const
             }
+            Node::Variant(&Spanned { node: VariantKind { data: VariantData::Tuple(..), .. }, .. }) |
+            Node::StructCtor(..) |
+            Node::Item(&Item { node: ItemKind::Fn(..), .. }) |
+            Node::TraitItem(&TraitItem { node: TraitItemKind::Method(..), .. }) |
+            Node::ImplItem(&ImplItem { node: ImplItemKind::Method(..), .. }) => {
+                BodyOwnerKind::Fn
+            }
             Node::Item(&Item { node: ItemKind::Static(_, m, _), .. }) => {
                 BodyOwnerKind::Static(m)
             }
-            // Default to function if it's not a constant or static.
-            _ => BodyOwnerKind::Fn
+            Node::Expr(&Expr { node: ExprKind::Closure(..), .. }) => {
+                BodyOwnerKind::Closure
+            }
+            node => bug!("{:#?} is not a body node", node),
         }
     }
 
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 65d9d5a..b58b1d3 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1270,6 +1270,9 @@
     /// Functions and methods.
     Fn,
 
+    /// Closures
+    Closure,
+
     /// Constants and associated constants.
     Const,
 
@@ -1277,6 +1280,15 @@
     Static(Mutability),
 }
 
+impl BodyOwnerKind {
+    pub fn is_fn_or_closure(self) -> bool {
+        match self {
+            BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
+            BodyOwnerKind::Const | BodyOwnerKind::Static(_) => false,
+        }
+    }
+}
+
 /// A constant (expression) that's not an item or associated item,
 /// but needs its own `DefId` for type-checking, const-eval, etc.
 /// These are usually found nested inside types (e.g., array lengths)
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 819dd8a..31f91a1 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -1268,8 +1268,8 @@
 
         // The body of the every fn is a root scope.
         self.cx.parent = self.cx.var_parent;
-        if let hir::BodyOwnerKind::Fn = self.tcx.hir().body_owner_kind(owner_id) {
-            self.visit_expr(&body.value);
+        if self.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() {
+            self.visit_expr(&body.value)
         } else {
             // Only functions have an outer terminating (drop) scope, while
             // temporaries in constant initializers may be 'static, but only
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 367a7ea..1c92e2d 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -471,7 +471,7 @@
     }
 
     fn report_similar_impl_candidates(&self,
-                                      mut impl_candidates: Vec<ty::TraitRef<'tcx>>,
+                                      impl_candidates: Vec<ty::TraitRef<'tcx>>,
                                       err: &mut DiagnosticBuilder<'_>)
     {
         if impl_candidates.is_empty() {
@@ -497,14 +497,18 @@
         });
 
         // Sort impl candidates so that ordering is consistent for UI tests.
-        let normalized_impl_candidates = &mut impl_candidates[0..end]
+        let mut normalized_impl_candidates = impl_candidates
             .iter()
             .map(normalize)
             .collect::<Vec<String>>();
+
+        // Sort before taking the `..end` range,
+        // because the ordering of `impl_candidates` may not be deterministic:
+        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
         normalized_impl_candidates.sort();
 
         err.help(&format!("the following implementations were found:{}{}",
-                          normalized_impl_candidates.join(""),
+                          normalized_impl_candidates[..end].join(""),
                           if len > 5 {
                               format!("\nand {} others", len - 4)
                           } else {
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 4563224..9d49814 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -163,10 +163,7 @@
         |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
     ));
 
-    let locals_are_invalidated_at_exit = match tcx.hir().body_owner_kind(id) {
-            hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false,
-            hir::BodyOwnerKind::Fn => true,
-    };
+    let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure();
     let borrow_set = Rc::new(BorrowSet::build(
             tcx, mir, locals_are_invalidated_at_exit, &mdpe.move_data));
 
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index c63d45c..0a214e6 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -476,6 +476,7 @@
         let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id);
 
         match tcx.hir().body_owner_kind(self.mir_node_id) {
+            BodyOwnerKind::Closure |
             BodyOwnerKind::Fn => {
                 let defining_ty = if self.mir_def_id == closure_base_def_id {
                     tcx.type_of(closure_base_def_id)
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 2bf2824..420ae11 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -75,7 +75,7 @@
         let cx = Cx::new(&infcx, id);
         let mut mir = if cx.tables().tainted_by_errors {
             build::construct_error(cx, body_id)
-        } else if let hir::BodyOwnerKind::Fn = cx.body_owner_kind {
+        } else if cx.body_owner_kind.is_fn_or_closure() {
             // fetch the fully liberated fn signature (that is, all bound
             // types/lifetimes replaced)
             let fn_hir_id = tcx.hir().node_to_hir_id(id);
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index b44c2cc..78abba5 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -613,6 +613,7 @@
             hir::BodyOwnerKind::Static(_) =>
                 // No need to free storage in this context.
                 None,
+            hir::BodyOwnerKind::Closure |
             hir::BodyOwnerKind::Fn =>
                 Some(self.topmost_scope()),
         }
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index 6113d88..f514cac 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -61,6 +61,7 @@
         let constness = match body_owner_kind {
             hir::BodyOwnerKind::Const |
             hir::BodyOwnerKind::Static(_) => hir::Constness::Const,
+            hir::BodyOwnerKind::Closure |
             hir::BodyOwnerKind::Fn => hir::Constness::NotConst,
         };
 
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index eb151b5..ab8da2f 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -4,6 +4,7 @@
 
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
+use rustc::ty::cast::CastTy;
 use rustc::hir;
 use rustc::hir::Node;
 use rustc::hir::def_id::DefId;
@@ -20,6 +21,7 @@
 
 pub struct UnsafetyChecker<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
+    const_context: bool,
     min_const_fn: bool,
     source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
     violations: Vec<UnsafetyViolation>,
@@ -33,14 +35,20 @@
 
 impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> {
     fn new(
+        const_context: bool,
         min_const_fn: bool,
         mir: &'a Mir<'tcx>,
         source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Self {
+        // sanity check
+        if min_const_fn {
+            assert!(const_context);
+        }
         Self {
             mir,
+            const_context,
             min_const_fn,
             source_scope_local_data,
             violations: vec![],
@@ -124,29 +132,70 @@
                     rvalue: &Rvalue<'tcx>,
                     location: Location)
     {
-        if let &Rvalue::Aggregate(box ref aggregate, _) = rvalue {
-            match aggregate {
-                &AggregateKind::Array(..) |
-                &AggregateKind::Tuple => {}
-                &AggregateKind::Adt(ref def, ..) => {
-                    match self.tcx.layout_scalar_valid_range(def.did) {
-                        (Bound::Unbounded, Bound::Unbounded) => {},
-                        _ => self.require_unsafe(
-                            "initializing type with `rustc_layout_scalar_valid_range` attr",
-                            "initializing a layout restricted type's field with a value outside \
-                            the valid range is undefined behavior",
-                            UnsafetyViolationKind::GeneralAndConstFn,
-                        ),
+        match rvalue {
+            Rvalue::Aggregate(box ref aggregate, _) => {
+                match aggregate {
+                    &AggregateKind::Array(..) |
+                    &AggregateKind::Tuple => {}
+                    &AggregateKind::Adt(ref def, ..) => {
+                        match self.tcx.layout_scalar_valid_range(def.did) {
+                            (Bound::Unbounded, Bound::Unbounded) => {},
+                            _ => self.require_unsafe(
+                                "initializing type with `rustc_layout_scalar_valid_range` attr",
+                                "initializing a layout restricted type's field with a value \
+                                outside the valid range is undefined behavior",
+                                UnsafetyViolationKind::GeneralAndConstFn,
+                            ),
+                        }
+                    }
+                    &AggregateKind::Closure(def_id, _) |
+                    &AggregateKind::Generator(def_id, _, _) => {
+                        let UnsafetyCheckResult {
+                            violations, unsafe_blocks
+                        } = self.tcx.unsafety_check_result(def_id);
+                        self.register_violations(&violations, &unsafe_blocks);
                     }
                 }
-                &AggregateKind::Closure(def_id, _) |
-                &AggregateKind::Generator(def_id, _, _) => {
-                    let UnsafetyCheckResult {
-                        violations, unsafe_blocks
-                    } = self.tcx.unsafety_check_result(def_id);
-                    self.register_violations(&violations, &unsafe_blocks);
+            },
+            // casting pointers to ints is unsafe in const fn because the const evaluator cannot
+            // possibly know what the result of various operations like `address / 2` would be
+            // pointers during const evaluation have no integral address, only an abstract one
+            Rvalue::Cast(CastKind::Misc, ref operand, cast_ty)
+            if self.const_context && self.tcx.features().const_raw_ptr_to_usize_cast => {
+                let operand_ty = operand.ty(self.mir, self.tcx);
+                let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
+                let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
+                match (cast_in, cast_out) {
+                    (CastTy::Ptr(_), CastTy::Int(_)) |
+                    (CastTy::FnPtr, CastTy::Int(_)) => {
+                        self.register_violations(&[UnsafetyViolation {
+                            source_info: self.source_info,
+                            description: Symbol::intern("cast of pointer to int").as_interned_str(),
+                            details: Symbol::intern("casting pointers to integers in constants")
+                                     .as_interned_str(),
+                            kind: UnsafetyViolationKind::General,
+                        }], &[]);
+                    },
+                    _ => {},
                 }
             }
+            // raw pointer and fn pointer operations are unsafe as it is not clear whether one
+            // pointer would be "less" or "equal" to another, because we cannot know where llvm
+            // or the linker will place various statics in memory. Without this information the
+            // result of a comparison of addresses would differ between runtime and compile-time.
+            Rvalue::BinaryOp(_, ref lhs, _)
+            if self.const_context && self.tcx.features().const_compare_raw_pointers => {
+                if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.mir, self.tcx).sty {
+                    self.register_violations(&[UnsafetyViolation {
+                        source_info: self.source_info,
+                        description: Symbol::intern("pointer operation").as_interned_str(),
+                        details: Symbol::intern("operations on pointers in constants")
+                                 .as_interned_str(),
+                        kind: UnsafetyViolationKind::General,
+                    }], &[]);
+                }
+            }
+            _ => {},
         }
         self.super_rvalue(rvalue, location);
     }
@@ -484,8 +533,16 @@
     };
 
     let param_env = tcx.param_env(def_id);
+
+    let id = tcx.hir().as_local_node_id(def_id).unwrap();
+    let (const_context, min_const_fn) = match tcx.hir().body_owner_kind(id) {
+        hir::BodyOwnerKind::Closure => (false, false),
+        hir::BodyOwnerKind::Fn => (tcx.is_const_fn(def_id), tcx.is_min_const_fn(def_id)),
+        hir::BodyOwnerKind::Const |
+        hir::BodyOwnerKind::Static(_) => (true, false),
+    };
     let mut checker = UnsafetyChecker::new(
-        tcx.is_min_const_fn(def_id),
+        const_context, min_const_fn,
         mir, source_scope_local_data, tcx, param_env);
     checker.visit_mir(mir);
 
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 8b970c1..9f0907a 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -1,6 +1,5 @@
 //! Inlining pass for MIR functions
 
-use rustc::hir;
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def_id::DefId;
 
@@ -74,15 +73,12 @@
 
         // Only do inlining into fn bodies.
         let id = self.tcx.hir().as_local_node_id(self.source.def_id).unwrap();
-        let body_owner_kind = self.tcx.hir().body_owner_kind(id);
-
-        if let (hir::BodyOwnerKind::Fn, None) = (body_owner_kind, self.source.promoted) {
-
+        if self.tcx.hir().body_owner_kind(id).is_fn_or_closure() && self.source.promoted.is_none() {
             for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated() {
                 if let Some(callsite) = self.get_valid_function_call(bb,
-                                                                     bb_data,
-                                                                     caller_mir,
-                                                                     param_env) {
+                                                                    bb_data,
+                                                                    caller_mir,
+                                                                    param_env) {
                     callsites.push_back(callsite);
                 }
             }
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 78cf715..2d94190 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -1152,6 +1152,7 @@
         let id = tcx.hir().as_local_node_id(def_id).unwrap();
         let mut const_promoted_temps = None;
         let mode = match tcx.hir().body_owner_kind(id) {
+            hir::BodyOwnerKind::Closure => Mode::Fn,
             hir::BodyOwnerKind::Fn => {
                 if tcx.is_const_fn(def_id) {
                     Mode::ConstFn
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index fca208b..f4685e0 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -573,6 +573,7 @@
     let body_owner_kind = tcx.hir().body_owner_kind(id);
     match (body_owner_kind, src.promoted) {
         (_, Some(i)) => write!(w, "{:?} in", i)?,
+        (hir::BodyOwnerKind::Closure, _) |
         (hir::BodyOwnerKind::Fn, _) => write!(w, "fn")?,
         (hir::BodyOwnerKind::Const, _) => write!(w, "const")?,
         (hir::BodyOwnerKind::Static(hir::MutImmutable), _) => write!(w, "static")?,
@@ -585,6 +586,7 @@
     })?;
 
     match (body_owner_kind, src.promoted) {
+        (hir::BodyOwnerKind::Closure, None) |
         (hir::BodyOwnerKind::Fn, None) => {
             write!(w, "(")?;
 
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index 49914dc..c11b1af 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -191,6 +191,7 @@
         self.in_static = false;
 
         match self.tcx.hir().body_owner_kind(item_id) {
+            hir::BodyOwnerKind::Closure |
             hir::BodyOwnerKind::Fn => self.in_fn = true,
             hir::BodyOwnerKind::Static(_) => self.in_static = true,
             _ => {}
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.rs b/src/test/ui/cast/cast-ptr-to-int-const.rs
index 70b4869..ac153cb 100644
--- a/src/test/ui/cast/cast-ptr-to-int-const.rs
+++ b/src/test/ui/cast/cast-ptr-to-int-const.rs
@@ -1,7 +1,11 @@
 // gate-test-const_raw_ptr_to_usize_cast
 
 fn main() {
-    const X: u32 = main as u32; //~ ERROR casting pointers to integers in constants is unstable
+    const X: u32 = unsafe {
+        main as u32 //~ ERROR casting pointers to integers in constants is unstable
+    };
     const Y: u32 = 0;
-    const Z: u32 = &Y as *const u32 as u32; //~ ERROR is unstable
+    const Z: u32 = unsafe {
+        &Y as *const u32 as u32 //~ ERROR is unstable
+    };
 }
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.stderr b/src/test/ui/cast/cast-ptr-to-int-const.stderr
index 3cce07d..d04595e 100644
--- a/src/test/ui/cast/cast-ptr-to-int-const.stderr
+++ b/src/test/ui/cast/cast-ptr-to-int-const.stderr
@@ -1,16 +1,16 @@
 error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
-  --> $DIR/cast-ptr-to-int-const.rs:4:20
+  --> $DIR/cast-ptr-to-int-const.rs:5:9
    |
-LL |     const X: u32 = main as u32; //~ ERROR casting pointers to integers in constants is unstable
-   |                    ^^^^^^^^^^^
+LL |         main as u32 //~ ERROR casting pointers to integers in constants is unstable
+   |         ^^^^^^^^^^^
    |
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
 error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
-  --> $DIR/cast-ptr-to-int-const.rs:6:20
+  --> $DIR/cast-ptr-to-int-const.rs:9:9
    |
-LL |     const Z: u32 = &Y as *const u32 as u32; //~ ERROR is unstable
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^
+LL |         &Y as *const u32 as u32 //~ ERROR is unstable
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs
index 63bac17..4426668 100644
--- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs
+++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs
@@ -3,13 +3,13 @@
 fn main() {}
 
 // unconst and bad, will thus error in miri
-const X: bool = &1 as *const i32 == &2 as *const i32; //~ ERROR any use of this value will cause
+const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this
 // unconst and fine
-const X2: bool = 42 as *const i32 == 43 as *const i32;
+const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
 // unconst and fine
-const Y: usize = 42usize as *const i32 as usize + 1;
+const Y: usize = unsafe { 42usize as *const i32 as usize + 1 };
 // unconst and bad, will thus error in miri
-const Y2: usize = &1 as *const i32 as usize + 1; //~ ERROR any use of this value will cause
+const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this
 // unconst and fine
 const Z: i32 = unsafe { *(&1 as *const i32) };
 // unconst and bad, will thus error in miri
diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
index ea11359..6be54c0 100644
--- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
+++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
@@ -1,20 +1,20 @@
 error: any use of this value will cause an error
   --> $DIR/const_raw_ptr_ops.rs:6:1
    |
-LL | const X: bool = &1 as *const i32 == &2 as *const i32; //~ ERROR any use of this value will cause
-   | ^^^^^^^^^^^^^^^^------------------------------------^
-   |                 |
-   |                 "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
+LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+   |                          |
+   |                          "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
    |
    = note: #[deny(const_err)] on by default
 
 error: any use of this value will cause an error
   --> $DIR/const_raw_ptr_ops.rs:12:1
    |
-LL | const Y2: usize = &1 as *const i32 as usize + 1; //~ ERROR any use of this value will cause
-   | ^^^^^^^^^^^^^^^^^^-----------------------------^
-   |                   |
-   |                   "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
+LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------^^^
+   |                            |
+   |                            "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
 
 error: any use of this value will cause an error
   --> $DIR/const_raw_ptr_ops.rs:16:1
diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
index d8abd97..c2600f8 100644
--- a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
+++ b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
@@ -1,5 +1,5 @@
 const fn cmp(x: fn(), y: fn()) -> bool { //~ ERROR function pointers in const fn are unstable
-    x == y
+    unsafe { x == y }
 }
 
 fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
index 91b0760..763c69e 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
@@ -95,97 +95,109 @@
    |                                          ^^^^^^^^^^
 
 error: casting pointers to ints is unstable in const fn
-  --> $DIR/min_const_fn.rs:94:42
+  --> $DIR/min_const_fn.rs:94:63
+   |
+LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
+   |                                                               ^^^^^^^^^^
+
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:96:42
    |
 LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
 
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:98:63
+   |
+LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
+   |                                                               ^^^^^^^^^^
+
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/min_const_fn.rs:96:38
+  --> $DIR/min_const_fn.rs:100:38
    |
 LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
    |                                      ^^^^^^^^^^^^^^^^^^^^^^
 
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/min_const_fn.rs:98:29
+  --> $DIR/min_const_fn.rs:102:29
    |
 LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
    |                             ^^^^^^^^^^^
 
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/min_const_fn.rs:100:44
+  --> $DIR/min_const_fn.rs:104:44
    |
 LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
    |                                            ^^^^^^
 
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/min_const_fn.rs:102:44
+  --> $DIR/min_const_fn.rs:106:44
    |
 LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
    |                                            ^^^^^^
 
 error: mutable references in const fn are unstable
-  --> $DIR/min_const_fn.rs:104:14
+  --> $DIR/min_const_fn.rs:108:14
    |
 LL | const fn inc(x: &mut i32) { *x += 1 }
    |              ^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:109:6
+  --> $DIR/min_const_fn.rs:113:6
    |
 LL | impl<T: std::fmt::Debug> Foo<T> {
    |      ^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:114:6
+  --> $DIR/min_const_fn.rs:118:6
    |
 LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
    |      ^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:119:6
+  --> $DIR/min_const_fn.rs:123:6
    |
 LL | impl<T: Sync + Sized> Foo<T> {
    |      ^
 
 error: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn.rs:125:24
+  --> $DIR/min_const_fn.rs:129:24
    |
 LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:127:34
+  --> $DIR/min_const_fn.rs:131:34
    |
 LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
    |                                  ^^^^^^^^^^^^^^^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:129:22
+  --> $DIR/min_const_fn.rs:133:22
    |
 LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
    |                      ^^^^^^^^^^^^^^^^^^^^
 
 error: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn.rs:130:23
+  --> $DIR/min_const_fn.rs:134:23
    |
 LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
    |                       ^^^^^^^^^^^^^^^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:131:23
+  --> $DIR/min_const_fn.rs:135:23
    |
 LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
    |                       ^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:132:32
+  --> $DIR/min_const_fn.rs:136:32
    |
 LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning[E0515]: cannot return reference to temporary value
-  --> $DIR/min_const_fn.rs:132:63
+  --> $DIR/min_const_fn.rs:136:63
    |
 LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |                                                               ^--
@@ -197,24 +209,24 @@
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:137:41
+  --> $DIR/min_const_fn.rs:141:41
    |
 LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: function pointers in const fn are unstable
-  --> $DIR/min_const_fn.rs:140:21
+  --> $DIR/min_const_fn.rs:144:21
    |
 LL | const fn no_fn_ptrs(_x: fn()) {}
    |                     ^^
 
 error: function pointers in const fn are unstable
-  --> $DIR/min_const_fn.rs:142:27
+  --> $DIR/min_const_fn.rs:146:27
    |
 LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
    |                           ^^^^
 
-error: aborting due to 34 previous errors
+error: aborting due to 36 previous errors
 
 Some errors occurred: E0493, E0515.
 For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs
index 05cf3d5..ee3ffcd 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs
@@ -90,9 +90,13 @@
 const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
 const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
 const fn foo30(x: *const u32) -> usize { x as usize }
-//~^ ERROR casting pointers to int
+//~^ ERROR casting pointers to ints is unstable
+const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
+//~^ ERROR casting pointers to ints is unstable
 const fn foo30_2(x: *mut u32) -> usize { x as usize }
-//~^ ERROR casting pointers to int
+//~^ ERROR casting pointers to ints is unstable
+const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
+//~^ ERROR casting pointers to ints is unstable
 const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
 //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
 const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
index 2cae714..52c60c5 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
@@ -95,113 +95,125 @@
    |                                          ^^^^^^^^^^
 
 error: casting pointers to ints is unstable in const fn
-  --> $DIR/min_const_fn.rs:94:42
+  --> $DIR/min_const_fn.rs:94:63
+   |
+LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
+   |                                                               ^^^^^^^^^^
+
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:96:42
    |
 LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
 
+error: casting pointers to ints is unstable in const fn
+  --> $DIR/min_const_fn.rs:98:63
+   |
+LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
+   |                                                               ^^^^^^^^^^
+
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/min_const_fn.rs:96:38
+  --> $DIR/min_const_fn.rs:100:38
    |
 LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
    |                                      ^^^^^^^^^^^^^^^^^^^^^^
 
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/min_const_fn.rs:98:29
+  --> $DIR/min_const_fn.rs:102:29
    |
 LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
    |                             ^^^^^^^^^^^
 
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/min_const_fn.rs:100:44
+  --> $DIR/min_const_fn.rs:104:44
    |
 LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
    |                                            ^^^^^^
 
 error: `if`, `match`, `&&` and `||` are not stable in const fn
-  --> $DIR/min_const_fn.rs:102:44
+  --> $DIR/min_const_fn.rs:106:44
    |
 LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
    |                                            ^^^^^^
 
 error: mutable references in const fn are unstable
-  --> $DIR/min_const_fn.rs:104:14
+  --> $DIR/min_const_fn.rs:108:14
    |
 LL | const fn inc(x: &mut i32) { *x += 1 }
    |              ^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:109:6
+  --> $DIR/min_const_fn.rs:113:6
    |
 LL | impl<T: std::fmt::Debug> Foo<T> {
    |      ^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:114:6
+  --> $DIR/min_const_fn.rs:118:6
    |
 LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
    |      ^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:119:6
+  --> $DIR/min_const_fn.rs:123:6
    |
 LL | impl<T: Sync + Sized> Foo<T> {
    |      ^
 
 error: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn.rs:125:24
+  --> $DIR/min_const_fn.rs:129:24
    |
 LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:127:34
+  --> $DIR/min_const_fn.rs:131:34
    |
 LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
    |                                  ^^^^^^^^^^^^^^^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:129:22
+  --> $DIR/min_const_fn.rs:133:22
    |
 LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
    |                      ^^^^^^^^^^^^^^^^^^^^
 
 error: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn.rs:130:23
+  --> $DIR/min_const_fn.rs:134:23
    |
 LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
    |                       ^^^^^^^^^^^^^^^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:131:23
+  --> $DIR/min_const_fn.rs:135:23
    |
 LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
    |                       ^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:132:32
+  --> $DIR/min_const_fn.rs:136:32
    |
 LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:137:41
+  --> $DIR/min_const_fn.rs:141:41
    |
 LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: function pointers in const fn are unstable
-  --> $DIR/min_const_fn.rs:140:21
+  --> $DIR/min_const_fn.rs:144:21
    |
 LL | const fn no_fn_ptrs(_x: fn()) {}
    |                     ^^
 
 error: function pointers in const fn are unstable
-  --> $DIR/min_const_fn.rs:142:27
+  --> $DIR/min_const_fn.rs:146:27
    |
 LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
    |                           ^^^^
 
-error: aborting due to 34 previous errors
+error: aborting due to 36 previous errors
 
 For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
index 140f98b..d6d5ce4 100644
--- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
+++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
@@ -8,7 +8,7 @@
              <Bar as Foo<i16>>
              <Bar as Foo<i32>>
              <Bar as Foo<i8>>
-             <Bar as Foo<u8>>
+             <Bar as Foo<u16>>
            and 2 others
 
 error: aborting due to previous error
diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
index 2346698..3411958 100644
--- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
+++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
@@ -40,10 +40,10 @@
    |     ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `bool`
    |
    = help: the following implementations were found:
+             <bool as Foo<bool>>
+             <bool as Foo<i8>>
              <bool as Foo<u16>>
              <bool as Foo<u32>>
-             <bool as Foo<u64>>
-             <bool as Foo<u8>>
            and 2 others
 note: required by `Foo::bar`
   --> $DIR/issue-39802-show-5-trait-impls.rs:2:5
diff --git a/src/test/ui/error-codes/E0395.rs b/src/test/ui/error-codes/E0395.rs
index c2de56c..9657bbd 100644
--- a/src/test/ui/error-codes/E0395.rs
+++ b/src/test/ui/error-codes/E0395.rs
@@ -3,6 +3,6 @@
 static FOO: i32 = 42;
 static BAR: i32 = 42;
 
-static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
+static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
 fn main() {
 }
diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr
index 45e1ba0..cc7d94e 100644
--- a/src/test/ui/error-codes/E0395.stderr
+++ b/src/test/ui/error-codes/E0395.stderr
@@ -1,8 +1,8 @@
 error[E0658]: comparing raw pointers inside static (see issue #53020)
-  --> $DIR/E0395.rs:6:22
+  --> $DIR/E0395.rs:6:29
    |
-LL | static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_compare_raw_pointers)] to the crate attributes to enable
 
diff --git a/src/test/ui/feature-gates/feature-gate-is_sorted.rs b/src/test/ui/feature-gates/feature-gate-is_sorted.rs
new file mode 100644
index 0000000..078ecc5
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-is_sorted.rs
@@ -0,0 +1,13 @@
+fn main() {
+    // Assert `Iterator` methods are feature gated
+    assert!([1, 2, 2, 9].iter().is_sorted());
+    //~^ ERROR: use of unstable library feature 'is_sorted': new API
+    assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+    //~^ ERROR: use of unstable library feature 'is_sorted': new API
+
+    // Assert `[T]` methods are feature gated
+    assert!([1, 2, 2, 9].is_sorted());
+    //~^ ERROR: use of unstable library feature 'is_sorted': new API
+    assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+    //~^ ERROR: use of unstable library feature 'is_sorted': new API
+}
diff --git a/src/test/ui/feature-gates/feature-gate-is_sorted.stderr b/src/test/ui/feature-gates/feature-gate-is_sorted.stderr
new file mode 100644
index 0000000..8230c1e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-is_sorted.stderr
@@ -0,0 +1,35 @@
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+  --> $DIR/feature-gate-is_sorted.rs:3:33
+   |
+LL |     assert!([1, 2, 2, 9].iter().is_sorted());
+   |                                 ^^^^^^^^^
+   |
+   = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+  --> $DIR/feature-gate-is_sorted.rs:5:39
+   |
+LL |     assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+   |                                       ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+  --> $DIR/feature-gate-is_sorted.rs:9:26
+   |
+LL |     assert!([1, 2, 2, 9].is_sorted());
+   |                          ^^^^^^^^^
+   |
+   = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+  --> $DIR/feature-gate-is_sorted.rs:11:32
+   |
+LL |     assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+   |                                ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-17458.rs b/src/test/ui/issues/issue-17458.rs
index d7a1752..444e94d 100644
--- a/src/test/ui/issues/issue-17458.rs
+++ b/src/test/ui/issues/issue-17458.rs
@@ -1,4 +1,4 @@
-static X: usize = 0 as *const usize as usize;
+static X: usize = unsafe { 0 as *const usize as usize };
 //~^ ERROR: casting pointers to integers in statics is unstable
 
 fn main() {
diff --git a/src/test/ui/issues/issue-17458.stderr b/src/test/ui/issues/issue-17458.stderr
index 0492141..a1a8ed9 100644
--- a/src/test/ui/issues/issue-17458.stderr
+++ b/src/test/ui/issues/issue-17458.stderr
@@ -1,8 +1,8 @@
 error[E0658]: casting pointers to integers in statics is unstable (see issue #51910)
-  --> $DIR/issue-17458.rs:1:19
+  --> $DIR/issue-17458.rs:1:28
    |
-LL | static X: usize = 0 as *const usize as usize;
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | static X: usize = unsafe { 0 as *const usize as usize };
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
diff --git a/src/test/ui/issues/issue-18294.rs b/src/test/ui/issues/issue-18294.rs
index df4fd16..1c2229f 100644
--- a/src/test/ui/issues/issue-18294.rs
+++ b/src/test/ui/issues/issue-18294.rs
@@ -1,5 +1,5 @@
 fn main() {
     const X: u32 = 1;
-    const Y: usize = &X as *const u32 as usize; //~ ERROR is unstable
+    const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable
     println!("{}", Y);
 }
diff --git a/src/test/ui/issues/issue-18294.stderr b/src/test/ui/issues/issue-18294.stderr
index 2af7f45..f3e8ab1 100644
--- a/src/test/ui/issues/issue-18294.stderr
+++ b/src/test/ui/issues/issue-18294.stderr
@@ -1,8 +1,8 @@
 error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
-  --> $DIR/issue-18294.rs:3:22
+  --> $DIR/issue-18294.rs:3:31
    |
-LL |     const Y: usize = &X as *const u32 as usize; //~ ERROR is unstable
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
diff --git a/src/test/ui/issues/issue-25826.rs b/src/test/ui/issues/issue-25826.rs
index e602265..36a69cf 100644
--- a/src/test/ui/issues/issue-25826.rs
+++ b/src/test/ui/issues/issue-25826.rs
@@ -1,6 +1,6 @@
 fn id<T>(t: T) -> T { t }
 fn main() {
-    const A: bool = id::<u8> as *const () < id::<u16> as *const ();
+    const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
     //~^ ERROR comparing raw pointers inside constant
     println!("{}", A);
 }
diff --git a/src/test/ui/issues/issue-25826.stderr b/src/test/ui/issues/issue-25826.stderr
index 73ebf29..dc547f7c 100644
--- a/src/test/ui/issues/issue-25826.stderr
+++ b/src/test/ui/issues/issue-25826.stderr
@@ -1,8 +1,8 @@
 error[E0658]: comparing raw pointers inside constant (see issue #53020)
-  --> $DIR/issue-25826.rs:3:21
+  --> $DIR/issue-25826.rs:3:30
    |
-LL |     const A: bool = id::<u8> as *const () < id::<u16> as *const ();
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_compare_raw_pointers)] to the crate attributes to enable
 
diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr
index 202885e..df8e646 100644
--- a/src/test/ui/try-block/try-block-bad-type.stderr
+++ b/src/test/ui/try-block/try-block-bad-type.stderr
@@ -6,10 +6,10 @@
    |
    = help: the following implementations were found:
              <i32 as std::convert::From<bool>>
+             <i32 as std::convert::From<core::num::NonZeroI32>>
              <i32 as std::convert::From<i16>>
              <i32 as std::convert::From<i8>>
-             <i32 as std::convert::From<u16>>
-             <i32 as std::convert::From<u8>>
+           and 2 others
    = note: required by `std::convert::From::from`
 
 error[E0271]: type mismatch resolving `<std::result::Result<i32, i32> as std::ops::Try>::Ok == &str`
diff --git a/src/tools/clippy b/src/tools/clippy
index 1b89724..1838bfe 160000
--- a/src/tools/clippy
+++ b/src/tools/clippy
@@ -1 +1 @@
-Subproject commit 1b89724b4889aef631b40d52c0943bdc28e04d1d
+Subproject commit 1838bfe5a9ff951ffd716e4632156113d95d14a4