diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 47b006985ec56..db8a6d9620495 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -558,7 +558,7 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
     fn universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex {
         let infcx = self.infcx;
         let index =
-            self.universe_indices.len() - debruijn.as_usize() + self.current_index.as_usize() - 1;
+            self.universe_indices.len() + self.current_index.as_usize() - debruijn.as_usize() - 1;
         let universe = self.universe_indices[index].unwrap_or_else(|| {
             for i in self.universe_indices.iter_mut().take(index + 1) {
                 *i = i.or_else(|| Some(infcx.create_next_universe()))
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index 07e542b70b90c..a87318ff34e6d 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -42,7 +42,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{Coercion, InferOk, InferResult};
-use rustc_infer::traits::Obligation;
+use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
@@ -146,6 +146,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             .and_then(|InferOk { value: ty, obligations }| success(f(ty), ty, obligations))
     }
 
+    #[instrument(skip(self))]
     fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
         // First, remove any resolved type variables (at the top level, at least):
         let a = self.shallow_resolve(a);
@@ -933,14 +934,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Same as `try_coerce()`, but without side-effects.
+    ///
+    /// Returns false if the coercion creates any obligations that result in
+    /// errors.
     pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool {
         let source = self.resolve_vars_with_obligations(expr_ty);
-        debug!("coercion::can({:?} -> {:?})", source, target);
+        debug!("coercion::can_with_predicates({:?} -> {:?})", source, target);
 
         let cause = self.cause(rustc_span::DUMMY_SP, ObligationCauseCode::ExprAssignable);
         // We don't ever need two-phase here since we throw out the result of the coercion
         let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
-        self.probe(|_| coerce.coerce(source, target)).is_ok()
+        self.probe(|_| {
+            let ok = match coerce.coerce(source, target) {
+                Ok(ok) => ok,
+                _ => return false,
+            };
+            let mut fcx = traits::FulfillmentContext::new_in_snapshot();
+            fcx.register_predicate_obligations(self, ok.obligations);
+            fcx.select_where_possible(&self).is_ok()
+        })
     }
 
     /// Given a type and a target type, this function will calculate and return
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index da8b863e2dbe6..339c46616a590 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -341,7 +341,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 for (sp, label) in spans_and_labels {
                     multi_span.push_span_label(sp, label);
                 }
-                err.span_note(multi_span, "closures can only be coerced to `fn` types if they do not capture any variables");
+                err.span_note(
+                    multi_span,
+                    "closures can only be coerced to `fn` types if they do not capture any variables"
+                );
             }
         }
     }
@@ -361,15 +364,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return false;
         }
         let pin_did = self.tcx.lang_items().pin_type();
+        // This guards the `unwrap` and `mk_box` below.
+        if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() {
+            return false;
+        }
         match expected.kind() {
-            ty::Adt(def, _) if Some(def.did) != pin_did => return false,
-            // This guards the `unwrap` and `mk_box` below.
-            _ if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() => return false,
-            _ => {}
+            ty::Adt(def, _) if Some(def.did) == pin_did => (),
+            _ => return false,
         }
-        let boxed_found = self.tcx.mk_box(found);
-        let new_found = self.tcx.mk_lang_item(boxed_found, LangItem::Pin).unwrap();
-        if self.can_coerce(new_found, expected) {
+        let box_found = self.tcx.mk_box(found);
+        let pin_box_found = self.tcx.mk_lang_item(box_found, LangItem::Pin).unwrap();
+        let pin_found = self.tcx.mk_lang_item(found, LangItem::Pin).unwrap();
+        if self.can_coerce(pin_box_found, expected) {
+            debug!("can coerce {:?} to {:?}, suggesting Box::pin", pin_box_found, expected);
             match found.kind() {
                 ty::Adt(def, _) if def.is_box() => {
                     err.help("use `Box::pin`");
@@ -381,11 +388,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             (expr.span.shrink_to_lo(), "Box::pin(".to_string()),
                             (expr.span.shrink_to_hi(), ")".to_string()),
                         ],
-                        Applicability::MachineApplicable,
+                        Applicability::MaybeIncorrect,
                     );
                 }
             }
             true
+        } else if self.can_coerce(pin_found, expected) {
+            match found.kind() {
+                ty::Adt(def, _) if def.is_box() => {
+                    err.help("use `Box::pin`");
+                    true
+                }
+                _ => false,
+            }
         } else {
             false
         }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 89ab11fb97e10..e86c41b1ff887 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -74,6 +74,7 @@
         not(any(test, bootstrap)),
         any(not(feature = "miri-test-libstd"), test, doctest),
         no_global_oom_handling,
+        not(no_global_oom_handling),
         target_has_atomic = "ptr"
     ))
 )]
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 12d79a56a527c..e225776bc647f 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -536,7 +536,7 @@ pub trait FromStr: Sized {
     ///
     /// If parsing succeeds, return the value inside [`Ok`], otherwise
     /// when the string is ill-formatted return an error specific to the
-    /// inside [`Err`]. The error type is specific to implementation of the trait.
+    /// inside [`Err`]. The error type is specific to the implementation of the trait.
     ///
     /// # Examples
     ///
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index b16436a18f0af..1d2d26b8f0046 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -195,7 +195,15 @@
     test(no_crate_inject, attr(deny(warnings))),
     test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
 )]
-#![cfg_attr(not(bootstrap), doc(cfg_hide(not(test), not(any(test, bootstrap)))))]
+#![cfg_attr(
+    not(bootstrap),
+    doc(cfg_hide(
+        not(test),
+        not(any(test, bootstrap)),
+        no_global_oom_handling,
+        not(no_global_oom_handling)
+    ))
+)]
 // Don't link to std. We are std.
 #![no_std]
 #![warn(deprecated_in_future)]
diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs
index 2719a530dfd41..a4fe5f67f699a 100644
--- a/library/std/src/sys/windows/stdio.rs
+++ b/library/std/src/sys/windows/stdio.rs
@@ -291,15 +291,25 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [u16]) -> io::Result<usize> {
     };
 
     let mut amount = 0;
-    cvt(unsafe {
-        c::ReadConsoleW(
-            handle,
-            buf.as_mut_ptr() as c::LPVOID,
-            buf.len() as u32,
-            &mut amount,
-            &mut input_control as c::PCONSOLE_READCONSOLE_CONTROL,
-        )
-    })?;
+    loop {
+        cvt(unsafe {
+            c::SetLastError(0);
+            c::ReadConsoleW(
+                handle,
+                buf.as_mut_ptr() as c::LPVOID,
+                buf.len() as u32,
+                &mut amount,
+                &mut input_control as c::PCONSOLE_READCONSOLE_CONTROL,
+            )
+        })?;
+
+        // ReadConsoleW returns success with ERROR_OPERATION_ABORTED for Ctrl-C or Ctrl-Break.
+        // Explicitly check for that case here and try again.
+        if amount == 0 && unsafe { c::GetLastError() } == c::ERROR_OPERATION_ABORTED {
+            continue;
+        }
+        break;
+    }
 
     if amount > 0 && buf[amount as usize - 1] == CTRL_Z {
         amount -= 1;
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 7818b8b7d515d..e658d958d0a26 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -825,15 +825,10 @@ impl Config {
                 };
             }
 
-            if config.llvm_thin_lto {
-                // If we're building with ThinLTO on, we want to link to LLVM
-                // shared, to avoid re-doing ThinLTO (which happens in the link
-                // step) with each stage.
-                assert_ne!(
-                    llvm.link_shared,
-                    Some(false),
-                    "setting link-shared=false is incompatible with thin-lto=true"
-                );
+            if config.llvm_thin_lto && llvm.link_shared.is_none() {
+                // If we're building with ThinLTO on, by default we want to link
+                // to LLVM shared, to avoid re-doing ThinLTO (which happens in
+                // the link step) with each stage.
                 config.llvm_link_shared = true;
             }
         }
diff --git a/src/test/ui/cross/cross-borrow-trait.stderr b/src/test/ui/cross/cross-borrow-trait.stderr
index f693a3149b2a1..81f309eae087c 100644
--- a/src/test/ui/cross/cross-borrow-trait.stderr
+++ b/src/test/ui/cross/cross-borrow-trait.stderr
@@ -2,10 +2,8 @@ error[E0308]: mismatched types
   --> $DIR/cross-borrow-trait.rs:10:26
    |
 LL |     let _y: &dyn Trait = x;
-   |             ----------   ^
-   |             |            |
-   |             |            expected `&dyn Trait`, found struct `Box`
-   |             |            help: consider borrowing here: `&x`
+   |             ----------   ^ expected `&dyn Trait`, found struct `Box`
+   |             |
    |             expected due to this
    |
    = note: expected reference `&dyn Trait`
diff --git a/src/test/ui/dst/dst-bad-coercions.stderr b/src/test/ui/dst/dst-bad-coercions.stderr
index 3e23c5f5c7443..01f862ed516e9 100644
--- a/src/test/ui/dst/dst-bad-coercions.stderr
+++ b/src/test/ui/dst/dst-bad-coercions.stderr
@@ -13,10 +13,8 @@ error[E0308]: mismatched types
   --> $DIR/dst-bad-coercions.rs:15:21
    |
 LL |     let y: &dyn T = x;
-   |            ------   ^
-   |            |        |
-   |            |        expected `&dyn T`, found *-ptr
-   |            |        help: consider borrowing here: `&x`
+   |            ------   ^ expected `&dyn T`, found *-ptr
+   |            |
    |            expected due to this
    |
    = note: expected reference `&dyn T`
@@ -37,10 +35,8 @@ error[E0308]: mismatched types
   --> $DIR/dst-bad-coercions.rs:20:21
    |
 LL |     let y: &dyn T = x;
-   |            ------   ^
-   |            |        |
-   |            |        expected `&dyn T`, found *-ptr
-   |            |        help: consider borrowing here: `&x`
+   |            ------   ^ expected `&dyn T`, found *-ptr
+   |            |
    |            expected due to this
    |
    = note: expected reference `&dyn T`
diff --git a/src/test/ui/suggestions/box-future-wrong-output.rs b/src/test/ui/suggestions/box-future-wrong-output.rs
new file mode 100644
index 0000000000000..d49819fcb14cf
--- /dev/null
+++ b/src/test/ui/suggestions/box-future-wrong-output.rs
@@ -0,0 +1,22 @@
+// Issue #72117
+// edition:2018
+
+use core::future::Future;
+use core::pin::Pin;
+
+pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
+
+impl<T: ?Sized> FutureExt for T where T: Future {}
+trait FutureExt: Future {
+    fn boxed<'a>(self) -> BoxFuture<'a, Self::Output>
+    where
+        Self: Sized + Send + 'a,
+    {
+        Box::pin(self)
+    }
+}
+
+fn main() {
+    let _: BoxFuture<'static, bool> = async {}.boxed();
+    //~^ ERROR: mismatched types
+}
diff --git a/src/test/ui/suggestions/box-future-wrong-output.stderr b/src/test/ui/suggestions/box-future-wrong-output.stderr
new file mode 100644
index 0000000000000..e0c57af25b3d2
--- /dev/null
+++ b/src/test/ui/suggestions/box-future-wrong-output.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/box-future-wrong-output.rs:20:39
+   |
+LL |     let _: BoxFuture<'static, bool> = async {}.boxed();
+   |            ------------------------   ^^^^^^^^^^^^^^^^ expected `bool`, found `()`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `Pin<Box<(dyn Future<Output = bool> + Send + 'static)>>`
+              found struct `Pin<Box<dyn Future<Output = ()> + Send>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs
index 5dee0f5dae0b0..89a36e89b0acf 100644
--- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs
+++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs
@@ -11,13 +11,13 @@ fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32>
     x //~ ERROR mismatched types
 }
 
-// This case is still subpar:
-// `Pin::new(x)`: store this in the heap by calling `Box::new`: `Box::new(x)`
-// Should suggest changing the code from `Pin::new` to `Box::pin`.
 fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
     Box::new(x) //~ ERROR mismatched types
 }
 
+// This case is still subpar:
+// `Pin::new(x)`: store this in the heap by calling `Box::new`: `Box::new(x)`
+// Should suggest changing the code from `Pin::new` to `Box::pin`.
 fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
     Pin::new(x) //~ ERROR mismatched types
     //~^ ERROR E0277
diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
index ff08178cb7470..f0af37e0cbe8a 100644
--- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
+++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
@@ -15,7 +15,7 @@ LL |     Box::pin(x)
    |     +++++++++ +
 
 error[E0308]: mismatched types
-  --> $DIR/expected-boxed-future-isnt-pinned.rs:18:5
+  --> $DIR/expected-boxed-future-isnt-pinned.rs:15:5
    |
 LL | fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
    |                                                         ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type