about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-10-02 00:48:41 +0000
committerbors <bors@rust-lang.org>2020-10-02 00:48:41 +0000
commitf283d3f02cf3ed261a519afe05cde9e23d1d9278 (patch)
treea7e6921f19e98580b47e0751b7ef50992a49cf5f
parent66936de05962e7e90adb265fb102042c34c7cbfe (diff)
parent5a7218009ec093f03bc0d2eb3ea2444ed4276f23 (diff)
downloadrust-f283d3f02cf3ed261a519afe05cde9e23d1d9278.tar.gz
rust-f283d3f02cf3ed261a519afe05cde9e23d1d9278.zip
Auto merge of #77436 - JohnTitor:rollup-65dh7rp, r=JohnTitor
Rollup of 11 pull requests

Successful merges:

 - #76851 (Fix 'FIXME' about using NonZeroU32 instead of u32.)
 - #76979 (Improve std::sys::windows::compat)
 - #77111 (Stabilize slice_ptr_range.)
 - #77147 (Split sys_common::Mutex in StaticMutex and MovableMutex.)
 - #77312 (Remove outdated line from `publish_toolstate` hook)
 - #77362 (Fix is_absolute on WASI)
 - #77375 (rustc_metadata: Do not forget to encode inherent impls for foreign types)
 - #77385 (Improve the example for ptr::copy)
 - #77389 (Fix some clippy lints)
 - #77399 (BTreeMap: use Unique::from to avoid a cast where type information exists)
 - #77429 (Link `new` method in `DefautHasher`s doc)

Failed merges:

r? `@ghost`
-rw-r--r--compiler/rustc_feature/src/accepted.rs4
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_feature/src/lib.rs23
-rw-r--r--compiler/rustc_feature/src/removed.rs6
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs1
-rw-r--r--library/alloc/src/collections/btree/node.rs2
-rw-r--r--library/core/src/intrinsics.rs12
-rw-r--r--library/core/src/slice/mod.rs6
-rw-r--r--library/std/src/collections/hash/map.rs7
-rw-r--r--library/std/src/path.rs2
-rw-r--r--library/std/src/sync/condvar.rs4
-rw-r--r--library/std/src/sync/mutex.rs30
-rw-r--r--library/std/src/sys/hermit/args.rs4
-rw-r--r--library/std/src/sys/unix/args.rs4
-rw-r--r--library/std/src/sys/unix/os.rs9
-rw-r--r--library/std/src/sys/vxworks/args.rs4
-rw-r--r--library/std/src/sys/vxworks/os.rs9
-rw-r--r--library/std/src/sys/windows/c.rs2
-rw-r--r--library/std/src/sys/windows/compat.rs75
-rw-r--r--library/std/src/sys/windows/mutex.rs21
-rw-r--r--library/std/src/sys_common/at_exit_imp.rs7
-rw-r--r--library/std/src/sys_common/condvar.rs10
-rw-r--r--library/std/src/sys_common/mutex.rs127
-rw-r--r--library/std/src/sys_common/thread_local_key.rs4
-rw-r--r--library/std/src/thread/mod.rs5
-rw-r--r--library/std/src/time.rs4
-rw-r--r--library/test/src/bench.rs2
-rw-r--r--library/test/src/formatters/pretty.rs2
-rw-r--r--library/test/src/formatters/terse.rs4
-rw-r--r--library/test/src/lib.rs8
-rw-r--r--library/test/src/stats.rs2
-rw-r--r--src/test/ui/extern/auxiliary/extern-types-inherent-impl.rs9
-rw-r--r--src/test/ui/extern/extern-types-inherent-impl.rs23
-rw-r--r--src/test/ui/issues/issue-54062.rs3
-rw-r--r--src/test/ui/issues/issue-54062.stderr13
-rwxr-xr-xsrc/tools/publish_toolstate.py3
36 files changed, 228 insertions, 227 deletions
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 0477f6f149b..e2492efb9d7 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -1,6 +1,6 @@
 //! List of the accepted feature gates.
 
-use super::{Feature, State};
+use super::{to_nonzero, Feature, State};
 use rustc_span::symbol::sym;
 
 macro_rules! declare_features {
@@ -14,7 +14,7 @@ macro_rules! declare_features {
                     state: State::Accepted,
                     name: sym::$feature,
                     since: $ver,
-                    issue: $issue,
+                    issue: to_nonzero($issue),
                     edition: None,
                     description: concat!($($doc,)*),
                 }
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 348cff8d2da..060efd270dd 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -1,6 +1,6 @@
 //! List of the active feature gates.
 
-use super::{Feature, State};
+use super::{to_nonzero, Feature, State};
 
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
@@ -29,7 +29,7 @@ macro_rules! declare_features {
                     state: State::Active { set: set!($feature) },
                     name: sym::$feature,
                     since: $ver,
-                    issue: $issue,
+                    issue: to_nonzero($issue),
                     edition: $edition,
                     description: concat!($($doc,)*),
                 }
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 15564a59658..68ac2841fed 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -46,17 +46,11 @@ pub struct Feature {
     pub state: State,
     pub name: Symbol,
     pub since: &'static str,
-    issue: Option<u32>, // FIXME: once #58732 is done make this an Option<NonZeroU32>
+    issue: Option<NonZeroU32>,
     pub edition: Option<Edition>,
     description: &'static str,
 }
 
-impl Feature {
-    fn issue(&self) -> Option<NonZeroU32> {
-        self.issue.and_then(NonZeroU32::new)
-    }
-}
-
 #[derive(Copy, Clone, Debug)]
 pub enum Stability {
     Unstable,
@@ -102,8 +96,8 @@ impl UnstableFeatures {
 fn find_lang_feature_issue(feature: Symbol) -> Option<NonZeroU32> {
     if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.name == feature) {
         // FIXME (#28244): enforce that active features have issue numbers
-        // assert!(info.issue().is_some())
-        info.issue()
+        // assert!(info.issue.is_some())
+        info.issue
     } else {
         // search in Accepted, Removed, or Stable Removed features
         let found = ACCEPTED_FEATURES
@@ -112,12 +106,21 @@ fn find_lang_feature_issue(feature: Symbol) -> Option<NonZeroU32> {
             .chain(STABLE_REMOVED_FEATURES)
             .find(|t| t.name == feature);
         match found {
-            Some(found) => found.issue(),
+            Some(found) => found.issue,
             None => panic!("feature `{}` is not declared anywhere", feature),
         }
     }
 }
 
+const fn to_nonzero(n: Option<u32>) -> Option<NonZeroU32> {
+    // Can be replaced with `n.and_then(NonZeroU32::new)` if that is ever usable
+    // in const context. Requires https://github.com/rust-lang/rfcs/pull/2632.
+    match n {
+        None => None,
+        Some(n) => NonZeroU32::new(n),
+    }
+}
+
 pub enum GateIssue {
     Language,
     Library(Option<NonZeroU32>),
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 8d410894e8b..a480ddc7f34 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -1,6 +1,6 @@
 //! List of the removed feature gates.
 
-use super::{Feature, State};
+use super::{to_nonzero, Feature, State};
 use rustc_span::symbol::sym;
 
 macro_rules! declare_features {
@@ -14,7 +14,7 @@ macro_rules! declare_features {
                     state: State::Removed { reason: $reason },
                     name: sym::$feature,
                     since: $ver,
-                    issue: $issue,
+                    issue: to_nonzero($issue),
                     edition: None,
                     description: concat!($($doc,)*),
                 }
@@ -32,7 +32,7 @@ macro_rules! declare_features {
                     state: State::Stabilized { reason: None },
                     name: sym::$feature,
                     since: $ver,
-                    issue: $issue,
+                    issue: to_nonzero($issue),
                     edition: None,
                     description: concat!($($doc,)*),
                 }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 757156e5a7d..f58a792ef58 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1753,6 +1753,7 @@ impl EncodeContext<'a, 'tcx> {
         self.encode_const_stability(def_id);
         self.encode_deprecation(def_id);
         self.encode_item_type(def_id);
+        self.encode_inherent_implementations(def_id);
         if let hir::ForeignItemKind::Fn(..) = nitem.kind {
             record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
             self.encode_variances_of(def_id);
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index c3f27c10599..ba08f65f903 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -128,7 +128,7 @@ impl<K, V> BoxedNode<K, V> {
     }
 
     fn from_internal(node: Box<InternalNode<K, V>>) -> Self {
-        BoxedNode { ptr: Box::into_unique(node).cast() }
+        BoxedNode { ptr: Unique::from(&mut Box::leak(node).data) }
     }
 
     unsafe fn from_ptr(ptr: NonNull<LeafNode<K, V>>) -> Self {
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 243fc7bfaa5..4e4b31c0cb4 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1901,11 +1901,21 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
 /// ```
 /// use std::ptr;
 ///
+/// /// # Safety:
+/// /// * `ptr` must be correctly aligned for its type and non-zero.
+/// /// * `ptr` must be valid for reads of `elts` contiguous objects of type `T`.
+/// /// * Those elements must not be used after calling this function unless `T: Copy`.
 /// # #[allow(dead_code)]
 /// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> {
 ///     let mut dst = Vec::with_capacity(elts);
-///     dst.set_len(elts);
+///
+///     // SAFETY: Our precondition ensures the source is aligned and valid,
+///     // and `Vec::with_capacity` ensures that we have usable space to write them.
 ///     ptr::copy(ptr, dst.as_mut_ptr(), elts);
+///
+///     // SAFETY: We created it with this much capacity earlier,
+///     // and the previous `copy` has initialized these elements.
+///     dst.set_len(elts);
 ///     dst
 /// }
 /// ```
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 4192632fe57..b1ca093add5 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -458,8 +458,6 @@ impl<T> [T] {
     /// element of this slice:
     ///
     /// ```
-    /// #![feature(slice_ptr_range)]
-    ///
     /// let a = [1, 2, 3];
     /// let x = &a[1] as *const _;
     /// let y = &5 as *const _;
@@ -469,7 +467,7 @@ impl<T> [T] {
     /// ```
     ///
     /// [`as_ptr`]: #method.as_ptr
-    #[unstable(feature = "slice_ptr_range", issue = "65807")]
+    #[stable(feature = "slice_ptr_range", since = "1.48.0")]
     #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
     pub const fn as_ptr_range(&self) -> Range<*const T> {
@@ -511,7 +509,7 @@ impl<T> [T] {
     /// common in C++.
     ///
     /// [`as_mut_ptr`]: #method.as_mut_ptr
-    #[unstable(feature = "slice_ptr_range", issue = "65807")]
+    #[stable(feature = "slice_ptr_range", since = "1.48.0")]
     #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
     pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> {
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 1bb835e1ead..4424a4c1992 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -2836,11 +2836,10 @@ impl DefaultHasher {
 
 #[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
 impl Default for DefaultHasher {
-    // FIXME: here should link `new` to [DefaultHasher::new], but it occurs intra-doc link
-    // resolution failure when re-exporting libstd items. When #56922 fixed,
-    // link `new` to [DefaultHasher::new] again.
-    /// Creates a new `DefaultHasher` using `new`.
+    /// Creates a new `DefaultHasher` using [`new`].
     /// See its documentation for more.
+    ///
+    /// [`new`]: DefaultHasher::new
     fn default() -> DefaultHasher {
         DefaultHasher::new()
     }
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index b83c1e9628d..6fa73042a30 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1838,7 +1838,7 @@ impl Path {
             // FIXME: Allow Redox prefixes
             self.has_root() || has_redox_scheme(self.as_u8_slice())
         } else {
-            self.has_root() && (cfg!(unix) || self.prefix().is_some())
+            self.has_root() && (cfg!(any(unix, target_os = "wasi")) || self.prefix().is_some())
         }
     }
 
diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs
index 7e2155dae6f..1376d8ebe8f 100644
--- a/library/std/src/sync/condvar.rs
+++ b/library/std/src/sync/condvar.rs
@@ -553,8 +553,8 @@ impl Condvar {
         unsafe { self.inner.notify_all() }
     }
 
-    fn verify(&self, mutex: &sys_mutex::Mutex) {
-        let addr = mutex as *const _ as usize;
+    fn verify(&self, mutex: &sys_mutex::MovableMutex) {
+        let addr = mutex.raw() as *const _ as usize;
         match self.mutex.compare_and_swap(0, addr, Ordering::SeqCst) {
             // If we got out 0, then we have successfully bound the mutex to
             // this cvar.
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs
index a1703c731d4..e8f5a6f4294 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/mutex.rs
@@ -166,12 +166,7 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "mutex_type")]
 pub struct Mutex<T: ?Sized> {
-    // Note that this mutex is in a *box*, not inlined into the struct itself.
-    // Once a native mutex has been used once, its address can never change (it
-    // can't be moved). This mutex type can be safely moved at any time, so to
-    // ensure that the native mutex is used correctly we box the inner mutex to
-    // give it a constant address.
-    inner: Box<sys::Mutex>,
+    inner: sys::MovableMutex,
     poison: poison::Flag,
     data: UnsafeCell<T>,
 }
@@ -218,15 +213,11 @@ impl<T> Mutex<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(t: T) -> Mutex<T> {
-        let mut m = Mutex {
-            inner: box sys::Mutex::new(),
+        Mutex {
+            inner: sys::MovableMutex::new(),
             poison: poison::Flag::new(),
             data: UnsafeCell::new(t),
-        };
-        unsafe {
-            m.inner.init();
         }
-        m
     }
 }
 
@@ -378,7 +369,6 @@ impl<T: ?Sized> Mutex<T> {
                 (ptr::read(inner), ptr::read(poison), ptr::read(data))
             };
             mem::forget(self);
-            inner.destroy(); // Keep in sync with the `Drop` impl.
             drop(inner);
 
             poison::map_result(poison.borrow(), |_| data.into_inner())
@@ -411,18 +401,6 @@ impl<T: ?Sized> Mutex<T> {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<#[may_dangle] T: ?Sized> Drop for Mutex<T> {
-    fn drop(&mut self) {
-        // This is actually safe b/c we know that there is no further usage of
-        // this mutex (it's up to the user to arrange for a mutex to get
-        // dropped, that's not our job)
-        //
-        // IMPORTANT: This code must be kept in sync with `Mutex::into_inner`.
-        unsafe { self.inner.destroy() }
-    }
-}
-
 #[stable(feature = "mutex_from", since = "1.24.0")]
 impl<T> From<T> for Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
@@ -509,7 +487,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> {
     }
 }
 
-pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
+pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::MovableMutex {
     &guard.lock.inner
 }
 
diff --git a/library/std/src/sys/hermit/args.rs b/library/std/src/sys/hermit/args.rs
index 72c1b8511ca..77272939272 100644
--- a/library/std/src/sys/hermit/args.rs
+++ b/library/std/src/sys/hermit/args.rs
@@ -57,11 +57,11 @@ mod imp {
     use crate::ptr;
     use crate::sys_common::os_str_bytes::*;
 
-    use crate::sys_common::mutex::Mutex;
+    use crate::sys_common::mutex::StaticMutex;
 
     static mut ARGC: isize = 0;
     static mut ARGV: *const *const u8 = ptr::null();
-    static LOCK: Mutex = Mutex::new();
+    static LOCK: StaticMutex = StaticMutex::new();
 
     pub unsafe fn init(argc: isize, argv: *const *const u8) {
         let _guard = LOCK.lock();
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs
index 9bc44a59482..f7c3f163718 100644
--- a/library/std/src/sys/unix/args.rs
+++ b/library/std/src/sys/unix/args.rs
@@ -80,13 +80,13 @@ mod imp {
     use crate::ptr;
     use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering};
 
-    use crate::sys_common::mutex::Mutex;
+    use crate::sys_common::mutex::StaticMutex;
 
     static ARGC: AtomicIsize = AtomicIsize::new(0);
     static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
     // We never call `ENV_LOCK.init()`, so it is UB to attempt to
     // acquire this mutex reentrantly!
-    static LOCK: Mutex = Mutex::new();
+    static LOCK: StaticMutex = StaticMutex::new();
 
     unsafe fn really_init(argc: isize, argv: *const *const u8) {
         let _guard = LOCK.lock();
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 4aa61fc5bf6..c9f9ed01e12 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -21,7 +21,7 @@ use crate::slice;
 use crate::str;
 use crate::sys::cvt;
 use crate::sys::fd;
-use crate::sys_common::mutex::{Mutex, MutexGuard};
+use crate::sys_common::mutex::{StaticMutex, StaticMutexGuard};
 use crate::vec;
 
 use libc::{c_char, c_int, c_void};
@@ -470,10 +470,9 @@ pub unsafe fn environ() -> *mut *const *const c_char {
     &mut environ
 }
 
-pub unsafe fn env_lock() -> MutexGuard<'static> {
-    // We never call `ENV_LOCK.init()`, so it is UB to attempt to
-    // acquire this mutex reentrantly!
-    static ENV_LOCK: Mutex = Mutex::new();
+pub unsafe fn env_lock() -> StaticMutexGuard<'static> {
+    // It is UB to attempt to acquire this mutex reentrantly!
+    static ENV_LOCK: StaticMutex = StaticMutex::new();
     ENV_LOCK.lock()
 }
 
diff --git a/library/std/src/sys/vxworks/args.rs b/library/std/src/sys/vxworks/args.rs
index adff6c489bb..30cf7a707c7 100644
--- a/library/std/src/sys/vxworks/args.rs
+++ b/library/std/src/sys/vxworks/args.rs
@@ -57,11 +57,11 @@ mod imp {
     use crate::marker::PhantomData;
     use crate::ptr;
 
-    use crate::sys_common::mutex::Mutex;
+    use crate::sys_common::mutex::StaticMutex;
 
     static mut ARGC: isize = 0;
     static mut ARGV: *const *const u8 = ptr::null();
-    static LOCK: Mutex = Mutex::new();
+    static LOCK: StaticMutex = StaticMutex::new();
 
     pub unsafe fn init(argc: isize, argv: *const *const u8) {
         let _guard = LOCK.lock();
diff --git a/library/std/src/sys/vxworks/os.rs b/library/std/src/sys/vxworks/os.rs
index 1fadf716135..08394a8d29d 100644
--- a/library/std/src/sys/vxworks/os.rs
+++ b/library/std/src/sys/vxworks/os.rs
@@ -10,7 +10,7 @@ use crate::path::{self, Path, PathBuf};
 use crate::slice;
 use crate::str;
 use crate::sys::cvt;
-use crate::sys_common::mutex::{Mutex, MutexGuard};
+use crate::sys_common::mutex::{StaticMutex, StaticMutexGuard};
 use libc::{self, c_char /*,c_void */, c_int};
 /*use sys::fd; this one is probably important */
 use crate::vec;
@@ -212,10 +212,9 @@ pub unsafe fn environ() -> *mut *const *const c_char {
     &mut environ
 }
 
-pub unsafe fn env_lock() -> MutexGuard<'static> {
-    // We never call `ENV_LOCK.init()`, so it is UB to attempt to
-    // acquire this mutex reentrantly!
-    static ENV_LOCK: Mutex = Mutex::new();
+pub unsafe fn env_lock() -> StaticMutexGuard<'static> {
+    // It is UB to attempt to acquire this mutex reentrantly!
+    static ENV_LOCK: StaticMutex = StaticMutex::new();
     ENV_LOCK.lock()
 }
 
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index f440442ca30..559c4dc9c7c 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -1032,7 +1032,7 @@ extern "system" {
 // Functions that aren't available on every version of Windows that we support,
 // but we still use them and just provide some form of a fallback implementation.
 compat_fn! {
-    kernel32:
+    "kernel32":
 
     pub fn CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
                                _lpTargetFileName: LPCWSTR,
diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs
index d6d433f9d08..3f25f05e1b9 100644
--- a/library/std/src/sys/windows/compat.rs
+++ b/library/std/src/sys/windows/compat.rs
@@ -12,7 +12,6 @@
 //! function is available but afterwards it's just a load and a jump.
 
 use crate::ffi::CString;
-use crate::sync::atomic::{AtomicUsize, Ordering};
 use crate::sys::c;
 
 pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
@@ -28,45 +27,69 @@ pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
     }
 }
 
-pub fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str, fallback: usize) -> usize {
-    let value = lookup(module, symbol).unwrap_or(fallback);
-    ptr.store(value, Ordering::SeqCst);
-    value
-}
-
 macro_rules! compat_fn {
-    ($module:ident: $(
+    ($module:literal: $(
         $(#[$meta:meta])*
-        pub fn $symbol:ident($($argname:ident: $argtype:ty),*)
-                                  -> $rettype:ty {
-            $($body:expr);*
-        }
+        pub fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty $body:block
     )*) => ($(
-        #[allow(unused_variables)]
         $(#[$meta])*
-        pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
+        pub mod $symbol {
+            use super::*;
             use crate::sync::atomic::{AtomicUsize, Ordering};
             use crate::mem;
+
             type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
 
             static PTR: AtomicUsize = AtomicUsize::new(0);
 
+            #[allow(unused_variables)]
+            unsafe extern "system" fn fallback($($argname: $argtype),*) -> $rettype $body
+
+            /// This address is stored in `PTR` to incidate an unavailable API.
+            ///
+            /// This way, call() will end up calling fallback() if it is unavailable.
+            ///
+            /// This is a `static` to avoid rustc duplicating `fn fallback()`
+            /// into both load() and is_available(), which would break
+            /// is_available()'s comparison. By using the same static variable
+            /// in both places, they'll refer to the same (copy of the)
+            /// function.
+            ///
+            /// LLVM merging the address of fallback with other functions
+            /// (because of unnamed_addr) is fine, since it's only compared to
+            /// an address from GetProcAddress from an external dll.
+            static FALLBACK: F = fallback;
+
+            #[cold]
             fn load() -> usize {
-                crate::sys::compat::store_func(&PTR,
-                                          stringify!($module),
-                                          stringify!($symbol),
-                                          fallback as usize)
+                // There is no locking here. It's okay if this is executed by multiple threads in
+                // parallel. `lookup` will result in the same value, and it's okay if they overwrite
+                // eachothers result as long as they do so atomically. We don't need any guarantees
+                // about memory ordering, as this involves just a single atomic variable which is
+                // not used to protect or order anything else.
+                let addr = crate::sys::compat::lookup($module, stringify!($symbol))
+                    .unwrap_or(FALLBACK as usize);
+                PTR.store(addr, Ordering::Relaxed);
+                addr
             }
-            unsafe extern "system" fn fallback($($argname: $argtype),*)
-                                               -> $rettype {
-                $($body);*
+
+            fn addr() -> usize {
+                match PTR.load(Ordering::Relaxed) {
+                    0 => load(),
+                    addr => addr,
+                }
+            }
+
+            #[allow(dead_code)]
+            pub fn is_available() -> bool {
+                addr() != FALLBACK as usize
             }
 
-            let addr = match PTR.load(Ordering::SeqCst) {
-                0 => load(),
-                n => n,
-            };
-            mem::transmute::<usize, F>(addr)($($argname),*)
+            pub unsafe fn call($($argname: $argtype),*) -> $rettype {
+                mem::transmute::<usize, F>(addr())($($argname),*)
+            }
         }
+
+        pub use $symbol::call as $symbol;
     )*)
 }
diff --git a/library/std/src/sys/windows/mutex.rs b/library/std/src/sys/windows/mutex.rs
index 1e09b95c872..e2aaca59fe2 100644
--- a/library/std/src/sys/windows/mutex.rs
+++ b/library/std/src/sys/windows/mutex.rs
@@ -23,7 +23,6 @@ use crate::cell::{Cell, UnsafeCell};
 use crate::mem::{self, MaybeUninit};
 use crate::sync::atomic::{AtomicUsize, Ordering};
 use crate::sys::c;
-use crate::sys::compat;
 
 pub struct Mutex {
     // This is either directly an SRWLOCK (if supported), or a Box<Inner> otherwise.
@@ -40,8 +39,8 @@ struct Inner {
 
 #[derive(Clone, Copy)]
 enum Kind {
-    SRWLock = 1,
-    CriticalSection = 2,
+    SRWLock,
+    CriticalSection,
 }
 
 #[inline]
@@ -130,21 +129,7 @@ impl Mutex {
 }
 
 fn kind() -> Kind {
-    static KIND: AtomicUsize = AtomicUsize::new(0);
-
-    let val = KIND.load(Ordering::SeqCst);
-    if val == Kind::SRWLock as usize {
-        return Kind::SRWLock;
-    } else if val == Kind::CriticalSection as usize {
-        return Kind::CriticalSection;
-    }
-
-    let ret = match compat::lookup("kernel32", "AcquireSRWLockExclusive") {
-        None => Kind::CriticalSection,
-        Some(..) => Kind::SRWLock,
-    };
-    KIND.store(ret as usize, Ordering::SeqCst);
-    ret
+    if c::AcquireSRWLockExclusive::is_available() { Kind::SRWLock } else { Kind::CriticalSection }
 }
 
 pub struct ReentrantMutex {
diff --git a/library/std/src/sys_common/at_exit_imp.rs b/library/std/src/sys_common/at_exit_imp.rs
index 6b799db856e..90d5d3a7898 100644
--- a/library/std/src/sys_common/at_exit_imp.rs
+++ b/library/std/src/sys_common/at_exit_imp.rs
@@ -4,7 +4,7 @@
 
 use crate::mem;
 use crate::ptr;
-use crate::sys_common::mutex::Mutex;
+use crate::sys_common::mutex::StaticMutex;
 
 type Queue = Vec<Box<dyn FnOnce()>>;
 
@@ -12,9 +12,8 @@ type Queue = Vec<Box<dyn FnOnce()>>;
 // on poisoning and this module needs to operate at a lower level than requiring
 // the thread infrastructure to be in place (useful on the borders of
 // initialization/destruction).
-// We never call `LOCK.init()`, so it is UB to attempt to
-// acquire this mutex reentrantly!
-static LOCK: Mutex = Mutex::new();
+// It is UB to attempt to acquire this mutex reentrantly!
+static LOCK: StaticMutex = StaticMutex::new();
 static mut QUEUE: *mut Queue = ptr::null_mut();
 
 const DONE: *mut Queue = 1_usize as *mut _;
diff --git a/library/std/src/sys_common/condvar.rs b/library/std/src/sys_common/condvar.rs
index f9611bc6f7b..a48d301f812 100644
--- a/library/std/src/sys_common/condvar.rs
+++ b/library/std/src/sys_common/condvar.rs
@@ -1,5 +1,5 @@
 use crate::sys::condvar as imp;
-use crate::sys_common::mutex::{self, Mutex};
+use crate::sys_common::mutex::MovableMutex;
 use crate::time::Duration;
 
 /// An OS-based condition variable.
@@ -46,8 +46,8 @@ impl Condvar {
     /// Behavior is also undefined if more than one mutex is used concurrently
     /// on this condition variable.
     #[inline]
-    pub unsafe fn wait(&self, mutex: &Mutex) {
-        self.0.wait(mutex::raw(mutex))
+    pub unsafe fn wait(&self, mutex: &MovableMutex) {
+        self.0.wait(mutex.raw())
     }
 
     /// Waits for a signal on the specified mutex with a timeout duration
@@ -57,8 +57,8 @@ impl Condvar {
     /// Behavior is also undefined if more than one mutex is used concurrently
     /// on this condition variable.
     #[inline]
-    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        self.0.wait_timeout(mutex::raw(mutex), dur)
+    pub unsafe fn wait_timeout(&self, mutex: &MovableMutex, dur: Duration) -> bool {
+        self.0.wait_timeout(mutex.raw(), dur)
     }
 
     /// Deallocates all resources associated with this condition variable.
diff --git a/library/std/src/sys_common/mutex.rs b/library/std/src/sys_common/mutex.rs
index e66d8994147..93ec7d89bc5 100644
--- a/library/std/src/sys_common/mutex.rs
+++ b/library/std/src/sys_common/mutex.rs
@@ -1,101 +1,106 @@
 use crate::sys::mutex as imp;
 
-/// An OS-based mutual exclusion lock.
+/// An OS-based mutual exclusion lock, meant for use in static variables.
+///
+/// This mutex has a const constructor ([`StaticMutex::new`]), does not
+/// implement `Drop` to cleanup resources, and causes UB when moved or used
+/// reentrantly.
+///
+/// This mutex does not implement poisoning.
 ///
-/// This is the thinnest cross-platform wrapper around OS mutexes. All usage of
-/// this mutex is unsafe and it is recommended to instead use the safe wrapper
-/// at the top level of the crate instead of this type.
-pub struct Mutex(imp::Mutex);
+/// This is a wrapper around `imp::Mutex` that does *not* call `init()` and
+/// `destroy()`.
+pub struct StaticMutex(imp::Mutex);
 
-unsafe impl Sync for Mutex {}
+unsafe impl Sync for StaticMutex {}
 
-impl Mutex {
+impl StaticMutex {
     /// Creates a new mutex for use.
     ///
     /// Behavior is undefined if the mutex is moved after it is
     /// first used with any of the functions below.
-    /// Also, until `init` is called, behavior is undefined if this
-    /// mutex is ever used reentrantly, i.e., `raw_lock` or `try_lock`
-    /// are called by the thread currently holding the lock.
+    /// Also, the behavior is undefined if this mutex is ever used reentrantly,
+    /// i.e., `lock` is called by the thread currently holding the lock.
     #[rustc_const_stable(feature = "const_sys_mutex_new", since = "1.0.0")]
-    pub const fn new() -> Mutex {
-        Mutex(imp::Mutex::new())
+    pub const fn new() -> Self {
+        Self(imp::Mutex::new())
     }
 
-    /// Prepare the mutex for use.
+    /// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
+    /// will be unlocked.
     ///
-    /// This should be called once the mutex is at a stable memory address.
-    /// If called, this must be the very first thing that happens to the mutex.
-    /// Calling it in parallel with or after any operation (including another
-    /// `init()`) is undefined behavior.
+    /// It is undefined behaviour to call this function while locked, or if the
+    /// mutex has been moved since the last time this was called.
     #[inline]
-    pub unsafe fn init(&mut self) {
-        self.0.init()
+    pub unsafe fn lock(&self) -> StaticMutexGuard<'_> {
+        self.0.lock();
+        StaticMutexGuard(&self.0)
     }
+}
 
-    /// Locks the mutex blocking the current thread until it is available.
-    ///
-    /// Behavior is undefined if the mutex has been moved between this and any
-    /// previous function call.
+#[must_use]
+pub struct StaticMutexGuard<'a>(&'a imp::Mutex);
+
+impl Drop for StaticMutexGuard<'_> {
     #[inline]
-    pub unsafe fn raw_lock(&self) {
-        self.0.lock()
+    fn drop(&mut self) {
+        unsafe {
+            self.0.unlock();
+        }
     }
+}
 
-    /// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
-    /// will be unlocked.
+/// An OS-based mutual exclusion lock.
+///
+/// This mutex does *not* have a const constructor, cleans up its resources in
+/// its `Drop` implementation, may safely be moved (when not borrowed), and
+/// does not cause UB when used reentrantly.
+///
+/// This mutex does not implement poisoning.
+///
+/// This is a wrapper around `Box<imp::Mutex>`, to allow the object to be moved
+/// without moving the raw mutex.
+pub struct MovableMutex(Box<imp::Mutex>);
+
+unsafe impl Sync for MovableMutex {}
+
+impl MovableMutex {
+    /// Creates a new mutex.
+    pub fn new() -> Self {
+        let mut mutex = box imp::Mutex::new();
+        unsafe { mutex.init() };
+        Self(mutex)
+    }
+
+    pub(crate) fn raw(&self) -> &imp::Mutex {
+        &self.0
+    }
+
+    /// Locks the mutex blocking the current thread until it is available.
     #[inline]
-    pub unsafe fn lock(&self) -> MutexGuard<'_> {
-        self.raw_lock();
-        MutexGuard(&self.0)
+    pub fn raw_lock(&self) {
+        unsafe { self.0.lock() }
     }
 
     /// Attempts to lock the mutex without blocking, returning whether it was
     /// successfully acquired or not.
-    ///
-    /// Behavior is undefined if the mutex has been moved between this and any
-    /// previous function call.
     #[inline]
-    pub unsafe fn try_lock(&self) -> bool {
-        self.0.try_lock()
+    pub fn try_lock(&self) -> bool {
+        unsafe { self.0.try_lock() }
     }
 
     /// Unlocks the mutex.
     ///
     /// Behavior is undefined if the current thread does not actually hold the
     /// mutex.
-    ///
-    /// Consider switching from the pair of raw_lock() and raw_unlock() to
-    /// lock() whenever possible.
     #[inline]
     pub unsafe fn raw_unlock(&self) {
         self.0.unlock()
     }
-
-    /// Deallocates all resources associated with this mutex.
-    ///
-    /// Behavior is undefined if there are current or will be future users of
-    /// this mutex.
-    #[inline]
-    pub unsafe fn destroy(&self) {
-        self.0.destroy()
-    }
 }
 
-// not meant to be exported to the outside world, just the containing module
-pub fn raw(mutex: &Mutex) -> &imp::Mutex {
-    &mutex.0
-}
-
-#[must_use]
-/// A simple RAII utility for the above Mutex without the poisoning semantics.
-pub struct MutexGuard<'a>(&'a imp::Mutex);
-
-impl Drop for MutexGuard<'_> {
-    #[inline]
+impl Drop for MovableMutex {
     fn drop(&mut self) {
-        unsafe {
-            self.0.unlock();
-        }
+        unsafe { self.0.destroy() };
     }
 }
diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs
index 676eadd1fac..dbcb7b36265 100644
--- a/library/std/src/sys_common/thread_local_key.rs
+++ b/library/std/src/sys_common/thread_local_key.rs
@@ -53,7 +53,7 @@ mod tests;
 
 use crate::sync::atomic::{self, AtomicUsize, Ordering};
 use crate::sys::thread_local_key as imp;
-use crate::sys_common::mutex::Mutex;
+use crate::sys_common::mutex::StaticMutex;
 
 /// A type for TLS keys that are statically allocated.
 ///
@@ -157,7 +157,7 @@ impl StaticKey {
         if imp::requires_synchronized_create() {
             // We never call `INIT_LOCK.init()`, so it is UB to attempt to
             // acquire this mutex reentrantly!
-            static INIT_LOCK: Mutex = Mutex::new();
+            static INIT_LOCK: StaticMutex = StaticMutex::new();
             let _guard = INIT_LOCK.lock();
             let mut key = self.key.load(Ordering::SeqCst);
             if key == 0 {
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index fb2fbb5bf2d..087175bb92a 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -972,9 +972,8 @@ pub struct ThreadId(NonZeroU64);
 impl ThreadId {
     // Generate a new unique thread ID.
     fn new() -> ThreadId {
-        // We never call `GUARD.init()`, so it is UB to attempt to
-        // acquire this mutex reentrantly!
-        static GUARD: mutex::Mutex = mutex::Mutex::new();
+        // It is UB to attempt to acquire this mutex reentrantly!
+        static GUARD: mutex::StaticMutex = mutex::StaticMutex::new();
         static mut COUNTER: u64 = 1;
 
         unsafe {
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 18e38c6299b..e7df3841147 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -20,7 +20,7 @@ use crate::error::Error;
 use crate::fmt;
 use crate::ops::{Add, AddAssign, Sub, SubAssign};
 use crate::sys::time;
-use crate::sys_common::mutex::Mutex;
+use crate::sys_common::mutex::StaticMutex;
 use crate::sys_common::FromInner;
 
 #[stable(feature = "time", since = "1.3.0")]
@@ -243,7 +243,7 @@ impl Instant {
             return Instant(os_now);
         }
 
-        static LOCK: Mutex = Mutex::new();
+        static LOCK: StaticMutex = StaticMutex::new();
         static mut LAST_NOW: time::Instant = time::Instant::zero();
         unsafe {
             let _lock = LOCK.lock();
diff --git a/library/test/src/bench.rs b/library/test/src/bench.rs
index a03cf9dd791..10546de1764 100644
--- a/library/test/src/bench.rs
+++ b/library/test/src/bench.rs
@@ -159,7 +159,7 @@ where
             return summ5;
         }
 
-        total_run = total_run + loop_run;
+        total_run += loop_run;
         // Longest we ever run for is 3s.
         if total_run > Duration::from_secs(3) {
             return summ5;
diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs
index 4a93e084df1..8c90b57b3ba 100644
--- a/library/test/src/formatters/pretty.rs
+++ b/library/test/src/formatters/pretty.rs
@@ -139,7 +139,7 @@ impl<T: Write> PrettyFormatter<T> {
                 stdouts.push_str(&format!("---- {} stdout ----\n", f.name));
                 let output = String::from_utf8_lossy(stdout);
                 stdouts.push_str(&output);
-                stdouts.push_str("\n");
+                stdouts.push('\n');
             }
         }
         if !stdouts.is_empty() {
diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs
index 5a264d20057..1ae7846a99e 100644
--- a/library/test/src/formatters/terse.rs
+++ b/library/test/src/formatters/terse.rs
@@ -114,7 +114,7 @@ impl<T: Write> TerseFormatter<T> {
                 stdouts.push_str(&format!("---- {} stdout ----\n", f.name));
                 let output = String::from_utf8_lossy(stdout);
                 stdouts.push_str(&output);
-                stdouts.push_str("\n");
+                stdouts.push('\n');
             }
         }
         if !stdouts.is_empty() {
@@ -140,7 +140,7 @@ impl<T: Write> TerseFormatter<T> {
                 fail_out.push_str(&format!("---- {} stdout ----\n", f.name));
                 let output = String::from_utf8_lossy(stdout);
                 fail_out.push_str(&output);
-                fail_out.push_str("\n");
+                fail_out.push('\n');
             }
         }
         if !fail_out.is_empty() {
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index caea4b1e309..b0b81f85fe0 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -237,11 +237,9 @@ where
     let event = TestEvent::TeFiltered(filtered_descs);
     notify_about_test_event(event)?;
 
-    let (filtered_tests, filtered_benchs): (Vec<_>, _) =
-        filtered_tests.into_iter().partition(|e| match e.testfn {
-            StaticTestFn(_) | DynTestFn(_) => true,
-            _ => false,
-        });
+    let (filtered_tests, filtered_benchs): (Vec<_>, _) = filtered_tests
+        .into_iter()
+        .partition(|e| matches!(e.testfn, StaticTestFn(_) | DynTestFn(_)));
 
     let concurrency = opts.test_threads.unwrap_or_else(get_concurrency);
 
diff --git a/library/test/src/stats.rs b/library/test/src/stats.rs
index 1a2cb893a8a..53f38894474 100644
--- a/library/test/src/stats.rs
+++ b/library/test/src/stats.rs
@@ -199,7 +199,7 @@ impl Stats for [f64] {
             let mut v: f64 = 0.0;
             for s in self {
                 let x = *s - mean;
-                v = v + x * x;
+                v += x * x;
             }
             // N.B., this is _supposed to be_ len-1, not len. If you
             // change it back to len, you will be calculating a
diff --git a/src/test/ui/extern/auxiliary/extern-types-inherent-impl.rs b/src/test/ui/extern/auxiliary/extern-types-inherent-impl.rs
new file mode 100644
index 00000000000..a1efe181843
--- /dev/null
+++ b/src/test/ui/extern/auxiliary/extern-types-inherent-impl.rs
@@ -0,0 +1,9 @@
+#![feature(extern_types)]
+
+extern "C" {
+    pub type CrossCrate;
+}
+
+impl CrossCrate {
+    pub fn foo(&self) {}
+}
diff --git a/src/test/ui/extern/extern-types-inherent-impl.rs b/src/test/ui/extern/extern-types-inherent-impl.rs
index fc98f55dc07..3f09ac7b8c3 100644
--- a/src/test/ui/extern/extern-types-inherent-impl.rs
+++ b/src/test/ui/extern/extern-types-inherent-impl.rs
@@ -1,19 +1,26 @@
-// run-pass
-#![allow(dead_code)]
 // Test that inherent impls can be defined for extern types.
 
+// check-pass
+// aux-build:extern-types-inherent-impl.rs
+
 #![feature(extern_types)]
 
-extern {
-    type A;
+extern crate extern_types_inherent_impl;
+use extern_types_inherent_impl::CrossCrate;
+
+extern "C" {
+    type Local;
 }
 
-impl A {
-    fn foo(&self) { }
+impl Local {
+    fn foo(&self) {}
 }
 
-fn use_foo(x: &A) {
+fn use_foo(x: &Local, y: &CrossCrate) {
+    Local::foo(x);
     x.foo();
+    CrossCrate::foo(y);
+    y.foo();
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/issues/issue-54062.rs b/src/test/ui/issues/issue-54062.rs
index 60a9b00d5d4..093d6601d4e 100644
--- a/src/test/ui/issues/issue-54062.rs
+++ b/src/test/ui/issues/issue-54062.rs
@@ -7,7 +7,6 @@ struct Test {
 fn main() {}
 
 fn testing(test: Test) {
-    let _ = test.comps.inner.lock().unwrap();
+    let _ = test.comps.inner.try_lock();
     //~^ ERROR: field `inner` of struct `Mutex` is private
-    //~| ERROR: no method named `unwrap` found
 }
diff --git a/src/test/ui/issues/issue-54062.stderr b/src/test/ui/issues/issue-54062.stderr
index e9e8080d467..5361ee1d345 100644
--- a/src/test/ui/issues/issue-54062.stderr
+++ b/src/test/ui/issues/issue-54062.stderr
@@ -1,16 +1,9 @@
 error[E0616]: field `inner` of struct `Mutex` is private
   --> $DIR/issue-54062.rs:10:24
    |
-LL |     let _ = test.comps.inner.lock().unwrap();
+LL |     let _ = test.comps.inner.try_lock();
    |                        ^^^^^ private field
 
-error[E0599]: no method named `unwrap` found for struct `std::sys_common::mutex::MutexGuard<'_>` in the current scope
-  --> $DIR/issue-54062.rs:10:37
-   |
-LL |     let _ = test.comps.inner.lock().unwrap();
-   |                                     ^^^^^^ method not found in `std::sys_common::mutex::MutexGuard<'_>`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0599, E0616.
-For more information about an error, try `rustc --explain E0599`.
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 9cfde0c232b..33613e2dc10 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -157,9 +157,6 @@ def issue(
 
         cc @{}, do you think you would have time to do the follow-up work?
         If so, that would be great!
-
-        And nominating for compiler team prioritization.
-
         ''').format(
             relevant_pr_number, tool, status_description,
             REPOS.get(tool), relevant_pr_user