about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTakashi Idobe <idobetakashi@gmail.com>2021-09-24 08:31:03 -0500
committerGitHub <noreply@github.com>2021-09-24 08:31:03 -0500
commitcb1c06fdd8921071a353b70d4752d834a76c5f94 (patch)
treed4606b4bee7f5dd22f5a0122fa5796961b815a60
parentb146525140a8776aec1f7852643ec2abd787a197 (diff)
parent91d8da1f4ba24679e92b7939a26c681a5d2d3548 (diff)
downloadrust-cb1c06fdd8921071a353b70d4752d834a76c5f94.tar.gz
rust-cb1c06fdd8921071a353b70d4752d834a76c5f94.zip
Merge branch 'rust-lang:master' into master
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs25
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs15
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs35
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/type_variable.rs29
-rw-r--r--compiler/rustc_infer/src/traits/engine.rs3
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs13
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs15
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs8
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs14
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/relationships.rs69
-rw-r--r--compiler/rustc_typeck/src/check/check.rs32
-rw-r--r--compiler/rustc_typeck/src/check/coercion.rs19
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs2
-rw-r--r--compiler/rustc_typeck/src/check/fallback.rs372
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs9
-rw-r--r--compiler/rustc_typeck/src/check/inherited.rs7
-rw-r--r--compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs21
-rw-r--r--library/core/src/num/int_macros.rs38
-rw-r--r--library/core/src/num/uint_macros.rs14
-rw-r--r--library/core/tests/num/int_macros.rs34
-rw-r--r--library/core/tests/num/uint_macros.rs10
-rw-r--r--library/std/src/sync/mpsc/shared.rs6
m---------src/llvm-project0
-rw-r--r--src/test/rustdoc/cross-crate-primitive-doc.rs2
-rw-r--r--src/test/rustdoc/intra-doc/prim-methods-external-core.rs2
-rw-r--r--src/test/ui/attributes/extented-attribute-macro-error.rs8
-rw-r--r--src/test/ui/attributes/extented-attribute-macro-error.stderr10
-rw-r--r--src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr19
-rw-r--r--src/test/ui/coercion/coerce-issue-49593-box-never.rs10
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.stderr4
-rw-r--r--src/test/ui/intrinsics/panic-uninitialized-zeroed.rs11
-rw-r--r--src/test/ui/never_type/defaulted-never-note.fallback.stderr (renamed from src/test/ui/never_type/defaulted-never-note.stderr)4
-rw-r--r--src/test/ui/never_type/defaulted-never-note.rs20
-rw-r--r--src/test/ui/never_type/diverging-fallback-control-flow.rs38
-rw-r--r--src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr18
-rw-r--r--src/test/ui/never_type/diverging-fallback-no-leak.rs19
-rw-r--r--src/test/ui/never_type/diverging-fallback-unconstrained-return.rs37
-rw-r--r--src/test/ui/never_type/fallback-closure-ret.rs23
-rw-r--r--src/test/ui/never_type/fallback-closure-wrap.fallback.stderr17
-rw-r--r--src/test/ui/never_type/fallback-closure-wrap.rs30
-rw-r--r--src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr17
-rw-r--r--src/test/ui/never_type/never-value-fallback-issue-66757.rs9
-rw-r--r--src/test/ui/recursion/issue-26548-recursion-via-normalize.rs6
-rw-r--r--src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr6
-rw-r--r--src/test/ui/suggestions/missing-type-param-used-in-param.fixed8
-rw-r--r--src/test/ui/suggestions/missing-type-param-used-in-param.rs8
-rw-r--r--src/test/ui/suggestions/missing-type-param-used-in-param.stderr21
-rw-r--r--src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr2
-rw-r--r--src/test/ui/type-alias-impl-trait/inference-cycle.stderr2
57 files changed, 933 insertions, 257 deletions
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 757ccbddbee..9e03fc33ae0 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -4,7 +4,7 @@ use crate::type_::Type;
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
-use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_middle::ty::{self, Ty, TypeFoldable};
 use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
 use rustc_target::abi::{Int, Pointer, F32, F64};
@@ -43,7 +43,8 @@ fn uncached_llvm_type<'a, 'tcx>(
         // in problematically distinct types due to HRTB and subtyping (see #47638).
         // ty::Dynamic(..) |
         ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str => {
-            let mut name = with_no_trimmed_paths(|| layout.ty.to_string());
+            let mut name =
+                with_no_visible_paths(|| with_no_trimmed_paths(|| layout.ty.to_string()));
             if let (&ty::Adt(def, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
             {
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 5aa2a422133..b0a5631549d 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -15,7 +15,7 @@ use rustc_index::vec::Idx;
 use rustc_middle::mir::AssertKind;
 use rustc_middle::mir::{self, SwitchTargets};
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
-use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
 use rustc_span::source_map::Span;
 use rustc_span::{sym, Symbol};
@@ -476,15 +476,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false),
             };
             if do_panic {
-                let msg_str = with_no_trimmed_paths(|| {
-                    if layout.abi.is_uninhabited() {
-                        // Use this error even for the other intrinsics as it is more precise.
-                        format!("attempted to instantiate uninhabited type `{}`", ty)
-                    } else if intrinsic == ZeroValid {
-                        format!("attempted to zero-initialize type `{}`, which is invalid", ty)
-                    } else {
-                        format!("attempted to leave type `{}` uninitialized, which is invalid", ty)
-                    }
+                let msg_str = with_no_visible_paths(|| {
+                    with_no_trimmed_paths(|| {
+                        if layout.abi.is_uninhabited() {
+                            // Use this error even for the other intrinsics as it is more precise.
+                            format!("attempted to instantiate uninhabited type `{}`", ty)
+                        } else if intrinsic == ZeroValid {
+                            format!("attempted to zero-initialize type `{}`, which is invalid", ty)
+                        } else {
+                            format!(
+                                "attempted to leave type `{}` uninitialized, which is invalid",
+                                ty
+                            )
+                        }
+                    })
                 });
                 let msg = bx.const_str(Symbol::intern(&msg_str));
                 let location = self.get_caller_location(bx, source_info).immediate();
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index a0ee212bed0..8dd7e6af257 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -22,6 +22,7 @@
 // is also useful to track which value is the "expected" value in
 // terms of error reporting.
 
+use super::equate::Equate;
 use super::glb::Glb;
 use super::lub::Lub;
 use super::sub::Sub;
@@ -29,7 +30,6 @@ use super::type_variable::TypeVariableValue;
 use super::unify_key::replace_if_possible;
 use super::unify_key::{ConstVarValue, ConstVariableValue};
 use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use super::{equate::Equate, type_variable::Diverging};
 use super::{InferCtxt, MiscVariable, TypeTrace};
 
 use crate::traits::{Obligation, PredicateObligations};
@@ -645,7 +645,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                                 .inner
                                 .borrow_mut()
                                 .type_variables()
-                                .new_var(self.for_universe, Diverging::NotDiverging, origin);
+                                .new_var(self.for_universe, origin);
                             let u = self.tcx().mk_ty_var(new_var_id);
 
                             // Record that we replaced `vid` with `new_var_id` as part of a generalization
@@ -885,11 +885,12 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
 
                         let origin =
                             *self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
-                        let new_var_id = self.infcx.inner.borrow_mut().type_variables().new_var(
-                            self.for_universe,
-                            Diverging::NotDiverging,
-                            origin,
-                        );
+                        let new_var_id = self
+                            .infcx
+                            .inner
+                            .borrow_mut()
+                            .type_variables()
+                            .new_var(self.for_universe, origin);
                         let u = self.tcx().mk_ty_var(new_var_id);
                         debug!(
                             "ConstInferUnifier: replacing original vid={:?} with new={:?}",
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index b8089b2499b..d9b7022f03a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -7,7 +7,7 @@
 //! inference graph arose so that we can explain to the user what gave
 //! rise to a particular error.
 //!
-//! The basis of the system are the "origin" types. An "origin" is the
+//! The system is based around a set of "origin" types. An "origin" is the
 //! reason that a constraint or inference variable arose. There are
 //! different "origin" enums for different kinds of constraints/variables
 //! (e.g., `TypeOrigin`, `RegionVariableOrigin`). An origin always has
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 43d3730c049..632e792bbd1 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -46,7 +46,7 @@ use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, Veri
 use self::region_constraints::{
     RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot,
 };
-use self::type_variable::{Diverging, TypeVariableOrigin, TypeVariableOriginKind};
+use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 
 pub mod at;
 pub mod canonical;
@@ -702,17 +702,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         t.fold_with(&mut self.freshener())
     }
 
-    /// Returns whether `ty` is a diverging type variable or not.
-    /// (If `ty` is not a type variable at all, returns not diverging.)
-    ///
-    /// No attempt is made to resolve `ty`.
-    pub fn type_var_diverges(&'a self, ty: Ty<'_>) -> Diverging {
-        match *ty.kind() {
-            ty::Infer(ty::TyVar(vid)) => self.inner.borrow_mut().type_variables().var_diverges(vid),
-            _ => Diverging::NotDiverging,
-        }
-    }
-
     /// Returns the origin of the type variable identified by `vid`, or `None`
     /// if this is not a type variable.
     ///
@@ -1071,12 +1060,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         })
     }
 
-    pub fn next_ty_var_id(&self, diverging: Diverging, origin: TypeVariableOrigin) -> TyVid {
-        self.inner.borrow_mut().type_variables().new_var(self.universe(), diverging, origin)
+    /// Number of type variables created so far.
+    pub fn num_ty_vars(&self) -> usize {
+        self.inner.borrow_mut().type_variables().num_vars()
+    }
+
+    pub fn next_ty_var_id(&self, origin: TypeVariableOrigin) -> TyVid {
+        self.inner.borrow_mut().type_variables().new_var(self.universe(), origin)
     }
 
     pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
-        self.tcx.mk_ty_var(self.next_ty_var_id(Diverging::NotDiverging, origin))
+        self.tcx.mk_ty_var(self.next_ty_var_id(origin))
     }
 
     pub fn next_ty_var_in_universe(
@@ -1084,18 +1078,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         origin: TypeVariableOrigin,
         universe: ty::UniverseIndex,
     ) -> Ty<'tcx> {
-        let vid = self.inner.borrow_mut().type_variables().new_var(
-            universe,
-            Diverging::NotDiverging,
-            origin,
-        );
+        let vid = self.inner.borrow_mut().type_variables().new_var(universe, origin);
         self.tcx.mk_ty_var(vid)
     }
 
-    pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
-        self.tcx.mk_ty_var(self.next_ty_var_id(Diverging::Diverges, origin))
-    }
-
     pub fn next_const_var(
         &self,
         ty: Ty<'tcx>,
@@ -1207,7 +1193,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 // as the substitutions for the default, `(T, U)`.
                 let ty_var_id = self.inner.borrow_mut().type_variables().new_var(
                     self.universe(),
-                    Diverging::NotDiverging,
                     TypeVariableOrigin {
                         kind: TypeVariableOriginKind::TypeParameterDefinition(
                             param.name,
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index e88c6608aca..73d74584a5e 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -22,7 +22,6 @@
 //!   constituents)
 
 use crate::infer::combine::ConstEquateRelation;
-use crate::infer::type_variable::Diverging;
 use crate::infer::InferCtxt;
 use crate::infer::{ConstVarValue, ConstVariableValue};
 use rustc_data_structures::fx::FxHashMap;
@@ -927,8 +926,7 @@ where
                             // Replacing with a new variable in the universe `self.universe`,
                             // it will be unified later with the original type variable in
                             // the universe `_universe`.
-                            let new_var_id =
-                                variables.new_var(self.universe, Diverging::NotDiverging, origin);
+                            let new_var_id = variables.new_var(self.universe, origin);
 
                             let u = self.tcx().mk_ty_var(new_var_id);
                             debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs
index f15268f6895..0e832685310 100644
--- a/compiler/rustc_infer/src/infer/type_variable.rs
+++ b/compiler/rustc_infer/src/infer/type_variable.rs
@@ -129,19 +129,16 @@ pub enum TypeVariableOriginKind {
     SubstitutionPlaceholder,
     AutoDeref,
     AdjustmentType,
-    DivergingFn,
+
+    /// In type check, when we are type checking a function that
+    /// returns `-> dyn Foo`, we substitute a type variable for the
+    /// return type for diagnostic purposes.
+    DynReturnFn,
     LatticeVariable,
 }
 
 pub(crate) struct TypeVariableData {
     origin: TypeVariableOrigin,
-    diverging: Diverging,
-}
-
-#[derive(Copy, Clone, Debug)]
-pub enum Diverging {
-    NotDiverging,
-    Diverges,
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -191,14 +188,6 @@ impl<'tcx> TypeVariableStorage<'tcx> {
 }
 
 impl<'tcx> TypeVariableTable<'_, 'tcx> {
-    /// Returns the diverges flag given when `vid` was created.
-    ///
-    /// Note that this function does not return care whether
-    /// `vid` has been unified with something else or not.
-    pub fn var_diverges(&self, vid: ty::TyVid) -> Diverging {
-        self.storage.values.get(vid.index()).diverging
-    }
-
     /// Returns the origin that was given when `vid` was created.
     ///
     /// Note that this function does not return care whether
@@ -260,7 +249,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
     pub fn new_var(
         &mut self,
         universe: ty::UniverseIndex,
-        diverging: Diverging,
         origin: TypeVariableOrigin,
     ) -> ty::TyVid {
         let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
@@ -268,13 +256,10 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
         let sub_key = self.sub_relations().new_key(());
         assert_eq!(eq_key.vid, sub_key);
 
-        let index = self.values().push(TypeVariableData { origin, diverging });
+        let index = self.values().push(TypeVariableData { origin });
         assert_eq!(eq_key.vid.as_u32(), index as u32);
 
-        debug!(
-            "new_var(index={:?}, universe={:?}, diverging={:?}, origin={:?}",
-            eq_key.vid, universe, diverging, origin,
-        );
+        debug!("new_var(index={:?}, universe={:?}, origin={:?}", eq_key.vid, universe, origin,);
 
         eq_key.vid
     }
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs
index 42333dc29bc..a12f7dc759c 100644
--- a/compiler/rustc_infer/src/traits/engine.rs
+++ b/compiler/rustc_infer/src/traits/engine.rs
@@ -1,5 +1,6 @@
 use crate::infer::InferCtxt;
 use crate::traits::Obligation;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness};
@@ -73,6 +74,8 @@ pub trait TraitEngine<'tcx>: 'tcx {
     }
 
     fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
+
+    fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships>;
 }
 
 pub trait TraitEngineExt<'tcx> {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index c13d7720e37..b4f7a9fa8e9 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -599,7 +599,7 @@ rustc_queries! {
         desc { "computing the inferred outlives predicates for items in this crate" }
     }
 
-    /// Maps from an impl/trait `DefId to a list of the `DefId`s of its items.
+    /// Maps from an impl/trait `DefId` to a list of the `DefId`s of its items.
     query associated_item_def_ids(key: DefId) -> &'tcx [DefId] {
         desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) }
     }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 777c6035be8..cc81ddbcc01 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2090,3 +2090,16 @@ impl<'tcx> fmt::Debug for SymbolName<'tcx> {
         fmt::Display::fmt(&self.name, fmt)
     }
 }
+
+#[derive(Debug, Default, Copy, Clone)]
+pub struct FoundRelationships {
+    /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo`
+    /// obligation, where:
+    ///
+    ///  * `Foo` is not `Sized`
+    ///  * `(): Foo` may be satisfied
+    pub self_in_trait: bool,
+    /// This is true if we identified that this Ty (`?T`) is found in a `<_ as
+    /// _>::AssocType = ?T`
+    pub output: bool,
+}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index db4a1d94d1a..d99534c200a 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -59,6 +59,7 @@ thread_local! {
     static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) };
     static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
     static NO_QUERIES: Cell<bool> = const { Cell::new(false) };
+    static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
 }
 
 /// Avoids running any queries during any prints that occur
@@ -112,6 +113,16 @@ pub fn with_no_trimmed_paths<F: FnOnce() -> R, R>(f: F) -> R {
     })
 }
 
+/// Prevent selection of visible paths. `Display` impl of DefId will prefer visible (public) reexports of types as paths.
+pub fn with_no_visible_paths<F: FnOnce() -> R, R>(f: F) -> R {
+    NO_VISIBLE_PATH.with(|flag| {
+        let old = flag.replace(true);
+        let result = f();
+        flag.set(old);
+        result
+    })
+}
+
 /// The "region highlights" are used to control region printing during
 /// specific error messages. When a "region highlight" is enabled, it
 /// gives an alternate way to print specific regions. For now, we
@@ -268,6 +279,10 @@ pub trait PrettyPrinter<'tcx>:
     /// from at least one local module, and returns `true`. If the crate defining `def_id` is
     /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
     fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), Self::Error> {
+        if NO_VISIBLE_PATH.with(|flag| flag.get()) {
+            return Ok((self, false));
+        }
+
         let mut callers = Vec::new();
         self.try_print_visible_def_path_recur(def_id, &mut callers)
     }
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 0fbaf81c21e..1e17ba204b2 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1673,6 +1673,14 @@ impl<'tcx> TyS<'tcx> {
     }
 
     #[inline]
+    pub fn ty_vid(&self) -> Option<ty::TyVid> {
+        match self.kind() {
+            &Infer(TyVar(vid)) => Some(vid),
+            _ => None,
+        }
+    }
+
+    #[inline]
     pub fn is_ty_infer(&self) -> bool {
         matches!(self.kind(), Infer(_))
     }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index fe0468c6956..c5417ea23f2 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1568,6 +1568,20 @@ impl<'a> Parser<'a> {
 
     pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
         self.parse_opt_lit().ok_or_else(|| {
+            if let token::Interpolated(inner) = &self.token.kind {
+                let expr = match inner.as_ref() {
+                    token::NtExpr(expr) => Some(expr),
+                    token::NtLiteral(expr) => Some(expr),
+                    _ => None,
+                };
+                if let Some(expr) = expr {
+                    if matches!(expr.kind, ExprKind::Err) {
+                        self.diagnostic()
+                            .delay_span_bug(self.token.span, &"invalid interpolated expression");
+                        return self.diagnostic().struct_dummy();
+                    }
+                }
+            }
             let msg = format!("unexpected token: {}", super::token_descr(&self.token));
             self.struct_span_err(self.token.span, &msg)
         })
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 90a6ba474b4..bb686b5ef3f 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -321,10 +321,13 @@ macro_rules! define_queries {
             pub fn $name<$tcx>(tcx: QueryCtxt<$tcx>, key: query_keys::$name<$tcx>) -> QueryStackFrame {
                 let kind = dep_graph::DepKind::$name;
                 let name = stringify!($name);
-                let description = ty::print::with_forced_impl_filename_line(
+                // Disable visible paths printing for performance reasons.
+                // Showing visible path instead of any path is not that important in production.
+                let description = ty::print::with_no_visible_paths(
+                    || ty::print::with_forced_impl_filename_line(
                     // Force filename-line mode to avoid invoking `type_of` query.
                     || queries::$name::describe(tcx, key)
-                );
+                ));
                 let description = if tcx.sess.verbose() {
                     format!("{} [{}]", description, name)
                 } else {
diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
index 9c962d30ce0..ec62ee40068 100644
--- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
@@ -7,16 +7,21 @@ use crate::traits::{
     ChalkEnvironmentAndGoal, FulfillmentError, FulfillmentErrorCode, ObligationCause,
     PredicateObligation, SelectionError, TraitEngine,
 };
-use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_middle::ty::{self, Ty};
 
 pub struct FulfillmentContext<'tcx> {
     obligations: FxIndexSet<PredicateObligation<'tcx>>,
+
+    relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>,
 }
 
 impl FulfillmentContext<'tcx> {
     crate fn new() -> Self {
-        FulfillmentContext { obligations: FxIndexSet::default() }
+        FulfillmentContext {
+            obligations: FxIndexSet::default(),
+            relationships: FxHashMap::default(),
+        }
     }
 }
 
@@ -39,6 +44,8 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
         assert!(!infcx.is_in_snapshot());
         let obligation = infcx.resolve_vars_if_possible(obligation);
 
+        super::relationships::update(self, infcx, &obligation);
+
         self.obligations.insert(obligation);
     }
 
@@ -146,4 +153,8 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
     fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
         self.obligations.iter().cloned().collect()
     }
+
+    fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
+        &mut self.relationships
+    }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index b376f429292..61462f23886 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -1,4 +1,5 @@
 use crate::infer::{InferCtxt, TyOrConstInferVar};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::obligation_forest::ProcessResult;
 use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
 use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
@@ -53,6 +54,9 @@ pub struct FulfillmentContext<'tcx> {
     // A list of all obligations that have been registered with this
     // fulfillment context.
     predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
+
+    relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>,
+
     // Should this fulfillment context register type-lives-for-region
     // obligations on its parent infcx? In some cases, region
     // obligations are either already known to hold (normalization) or
@@ -97,6 +101,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
     pub fn new() -> FulfillmentContext<'tcx> {
         FulfillmentContext {
             predicates: ObligationForest::new(),
+            relationships: FxHashMap::default(),
             register_region_obligations: true,
             usable_in_snapshot: false,
         }
@@ -105,6 +110,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
     pub fn new_in_snapshot() -> FulfillmentContext<'tcx> {
         FulfillmentContext {
             predicates: ObligationForest::new(),
+            relationships: FxHashMap::default(),
             register_region_obligations: true,
             usable_in_snapshot: true,
         }
@@ -113,6 +119,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
     pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> {
         FulfillmentContext {
             predicates: ObligationForest::new(),
+            relationships: FxHashMap::default(),
             register_region_obligations: false,
             usable_in_snapshot: false,
         }
@@ -210,6 +217,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
 
         assert!(!infcx.is_in_snapshot() || self.usable_in_snapshot);
 
+        super::relationships::update(self, infcx, &obligation);
+
         self.predicates
             .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
     }
@@ -265,6 +274,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
     fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
         self.predicates.map_pending_obligations(|o| o.obligation.clone())
     }
+
+    fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
+        &mut self.relationships
+    }
 }
 
 struct FulfillProcessor<'a, 'b, 'tcx> {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index ef208c44471..df2422048b9 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -15,6 +15,7 @@ mod object_safety;
 mod on_unimplemented;
 mod project;
 pub mod query;
+pub(crate) mod relationships;
 mod select;
 mod specialize;
 mod structural_match;
diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs
new file mode 100644
index 00000000000..7751dd84f4c
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/relationships.rs
@@ -0,0 +1,69 @@
+use crate::infer::InferCtxt;
+use crate::traits::query::evaluate_obligation::InferCtxtExt;
+use crate::traits::{ObligationCause, PredicateObligation};
+use rustc_infer::traits::TraitEngine;
+use rustc_middle::ty::{self, ToPredicate};
+
+pub(crate) fn update<'tcx, T>(
+    engine: &mut T,
+    infcx: &InferCtxt<'_, 'tcx>,
+    obligation: &PredicateObligation<'tcx>,
+) where
+    T: TraitEngine<'tcx>,
+{
+    // (*) binder skipped
+    if let ty::PredicateKind::Trait(predicate) = obligation.predicate.kind().skip_binder() {
+        if let Some(ty) =
+            infcx.shallow_resolve(predicate.self_ty()).ty_vid().map(|t| infcx.root_var(t))
+        {
+            if infcx
+                .tcx
+                .lang_items()
+                .sized_trait()
+                .map_or(false, |st| st != predicate.trait_ref.def_id)
+            {
+                let new_self_ty = infcx.tcx.types.unit;
+
+                let trait_ref = ty::TraitRef {
+                    substs: infcx
+                        .tcx
+                        .mk_substs_trait(new_self_ty, &predicate.trait_ref.substs[1..]),
+                    ..predicate.trait_ref
+                };
+
+                // Then contstruct a new obligation with Self = () added
+                // to the ParamEnv, and see if it holds.
+                let o = rustc_infer::traits::Obligation::new(
+                    ObligationCause::dummy(),
+                    obligation.param_env,
+                    obligation
+                        .predicate
+                        .kind()
+                        .map_bound(|_| {
+                            // (*) binder moved here
+                            ty::PredicateKind::Trait(ty::TraitPredicate {
+                                trait_ref,
+                                constness: predicate.constness,
+                            })
+                        })
+                        .to_predicate(infcx.tcx),
+                );
+                // Don't report overflow errors. Otherwise equivalent to may_hold.
+                if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) {
+                    if result.may_apply() {
+                        engine.relationships().entry(ty).or_default().self_in_trait = true;
+                    }
+                }
+            }
+        }
+    }
+
+    if let ty::PredicateKind::Projection(predicate) = obligation.predicate.kind().skip_binder() {
+        // If the projection predicate (Foo::Bar == X) has X as a non-TyVid,
+        // we need to make it into one.
+        if let Some(vid) = predicate.ty.ty_vid() {
+            debug!("relationship: {:?}.output = true", vid);
+            engine.relationships().entry(vid).or_default().output = true;
+        }
+    }
+}
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index d6c59312c0b..9f0ed0cd18d 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -241,32 +241,16 @@ pub(super) fn check_fn<'a, 'tcx>(
     // we saw and assigning it to the expected return type. This isn't
     // really expected to fail, since the coercions would have failed
     // earlier when trying to find a LUB.
-    //
-    // However, the behavior around `!` is sort of complex. In the
-    // event that the `actual_return_ty` comes back as `!`, that
-    // indicates that the fn either does not return or "returns" only
-    // values of type `!`. In this case, if there is an expected
-    // return type that is *not* `!`, that should be ok. But if the
-    // return type is being inferred, we want to "fallback" to `!`:
-    //
-    //     let x = move || panic!();
-    //
-    // To allow for that, I am creating a type variable with diverging
-    // fallback. This was deemed ever so slightly better than unifying
-    // the return value with `!` because it allows for the caller to
-    // make more assumptions about the return type (e.g., they could do
-    //
-    //     let y: Option<u32> = Some(x());
-    //
-    // which would then cause this return type to become `u32`, not
-    // `!`).
     let coercion = fcx.ret_coercion.take().unwrap().into_inner();
     let mut actual_return_ty = coercion.complete(&fcx);
-    if actual_return_ty.is_never() {
-        actual_return_ty = fcx.next_diverging_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::DivergingFn,
-            span,
-        });
+    debug!("actual_return_ty = {:?}", actual_return_ty);
+    if let ty::Dynamic(..) = declared_ret_ty.kind() {
+        // We have special-cased the case where the function is declared
+        // `-> dyn Foo` and we don't actually relate it to the
+        // `fcx.ret_coercion`, so just substitute a type variable.
+        actual_return_ty =
+            fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span });
+        debug!("actual_return_ty replaced with {:?}", actual_return_ty);
     }
     fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty);
 
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index 92d0470bc2f..5b9481ce4e1 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -159,24 +159,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         // Coercing from `!` to any type is allowed:
         if a.is_never() {
-            // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
-            // type variable, we want `?T` to fallback to `!` if not
-            // otherwise constrained. An example where this arises:
-            //
-            //     let _: Option<?T> = Some({ return; });
-            //
-            // here, we would coerce from `!` to `?T`.
-            return if b.is_ty_var() {
-                // Micro-optimization: no need for this if `b` is
-                // already resolved in some way.
-                let diverging_ty = self.next_diverging_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::AdjustmentType,
-                    span: self.cause.span,
-                });
-                self.coerce_from_inference_variable(diverging_ty, b, simple(Adjust::NeverToAny))
-            } else {
-                success(simple(Adjust::NeverToAny)(b), b, vec![])
-            };
+            return success(simple(Adjust::NeverToAny)(b), b, vec![]);
         }
 
         // Coercing *from* an unresolved inference variable means that
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 11b6c93a115..8a69e0a737d 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -77,7 +77,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 !self.typeck_results.borrow().adjustments().contains_key(expr.hir_id),
                 "expression with never type wound up being adjusted"
             );
-            let adj_ty = self.next_diverging_ty_var(TypeVariableOrigin {
+            let adj_ty = self.next_ty_var(TypeVariableOrigin {
                 kind: TypeVariableOriginKind::AdjustmentType,
                 span: expr.span,
             });
diff --git a/compiler/rustc_typeck/src/check/fallback.rs b/compiler/rustc_typeck/src/check/fallback.rs
index 8f6cdc7bb12..296e45337ed 100644
--- a/compiler/rustc_typeck/src/check/fallback.rs
+++ b/compiler/rustc_typeck/src/check/fallback.rs
@@ -1,29 +1,52 @@
 use crate::check::FnCtxt;
-use rustc_infer::infer::type_variable::Diverging;
+use rustc_data_structures::{
+    fx::FxHashMap,
+    graph::WithSuccessors,
+    graph::{iterate::DepthFirstSearch, vec_graph::VecGraph},
+    stable_set::FxHashSet,
+};
 use rustc_middle::ty::{self, Ty};
 
 impl<'tcx> FnCtxt<'_, 'tcx> {
     /// Performs type inference fallback, returning true if any fallback
     /// occurs.
     pub(super) fn type_inference_fallback(&self) -> bool {
+        debug!(
+            "type-inference-fallback start obligations: {:#?}",
+            self.fulfillment_cx.borrow_mut().pending_obligations()
+        );
+
         // All type checking constraints were added, try to fallback unsolved variables.
         self.select_obligations_where_possible(false, |_| {});
-        let mut fallback_has_occurred = false;
 
+        debug!(
+            "type-inference-fallback post selection obligations: {:#?}",
+            self.fulfillment_cx.borrow_mut().pending_obligations()
+        );
+
+        // Check if we have any unsolved varibales. If not, no need for fallback.
+        let unsolved_variables = self.unsolved_variables();
+        if unsolved_variables.is_empty() {
+            return false;
+        }
+
+        let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables);
+
+        let mut fallback_has_occurred = false;
         // We do fallback in two passes, to try to generate
         // better error messages.
         // The first time, we do *not* replace opaque types.
-        for ty in &self.unsolved_variables() {
+        for ty in unsolved_variables {
             debug!("unsolved_variable = {:?}", ty);
-            fallback_has_occurred |= self.fallback_if_possible(ty);
+            fallback_has_occurred |= self.fallback_if_possible(ty, &diverging_fallback);
         }
 
-        // We now see if we can make progress. This might
-        // cause us to unify inference variables for opaque types,
-        // since we may have unified some other type variables
-        // during the first phase of fallback.
-        // This means that we only replace inference variables with their underlying
-        // opaque types as a last resort.
+        // We now see if we can make progress. This might cause us to
+        // unify inference variables for opaque types, since we may
+        // have unified some other type variables during the first
+        // phase of fallback.  This means that we only replace
+        // inference variables with their underlying opaque types as a
+        // last resort.
         //
         // In code like this:
         //
@@ -62,36 +85,44 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
     //
     // - Unconstrained floats are replaced with with `f64`.
     //
-    // - Non-numerics get replaced with `!` when `#![feature(never_type_fallback)]`
-    //   is enabled. Otherwise, they are replaced with `()`.
+    // - Non-numerics may get replaced with `()` or `!`, depending on
+    //   how they were categorized by `calculate_diverging_fallback`
+    //   (and the setting of `#![feature(never_type_fallback)]`).
+    //
+    // Fallback becomes very dubious if we have encountered
+    // type-checking errors.  In that case, fallback to Error.
     //
-    // Fallback becomes very dubious if we have encountered type-checking errors.
-    // In that case, fallback to Error.
     // The return value indicates whether fallback has occurred.
-    fn fallback_if_possible(&self, ty: Ty<'tcx>) -> bool {
+    fn fallback_if_possible(
+        &self,
+        ty: Ty<'tcx>,
+        diverging_fallback: &FxHashMap<Ty<'tcx>, Ty<'tcx>>,
+    ) -> bool {
         // Careful: we do NOT shallow-resolve `ty`. We know that `ty`
-        // is an unsolved variable, and we determine its fallback based
-        // solely on how it was created, not what other type variables
-        // it may have been unified with since then.
+        // is an unsolved variable, and we determine its fallback
+        // based solely on how it was created, not what other type
+        // variables it may have been unified with since then.
         //
-        // The reason this matters is that other attempts at fallback may
-        // (in principle) conflict with this fallback, and we wish to generate
-        // a type error in that case. (However, this actually isn't true right now,
-        // because we're only using the builtin fallback rules. This would be
-        // true if we were using user-supplied fallbacks. But it's still useful
-        // to write the code to detect bugs.)
+        // The reason this matters is that other attempts at fallback
+        // may (in principle) conflict with this fallback, and we wish
+        // to generate a type error in that case. (However, this
+        // actually isn't true right now, because we're only using the
+        // builtin fallback rules. This would be true if we were using
+        // user-supplied fallbacks. But it's still useful to write the
+        // code to detect bugs.)
         //
-        // (Note though that if we have a general type variable `?T` that is then unified
-        // with an integer type variable `?I` that ultimately never gets
-        // resolved to a special integral type, `?T` is not considered unsolved,
-        // but `?I` is. The same is true for float variables.)
+        // (Note though that if we have a general type variable `?T`
+        // that is then unified with an integer type variable `?I`
+        // that ultimately never gets resolved to a special integral
+        // type, `?T` is not considered unsolved, but `?I` is. The
+        // same is true for float variables.)
         let fallback = match ty.kind() {
             _ if self.is_tainted_by_errors() => self.tcx.ty_error(),
             ty::Infer(ty::IntVar(_)) => self.tcx.types.i32,
             ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
-            _ => match self.type_var_diverges(ty) {
-                Diverging::Diverges => self.tcx.mk_diverging_default(),
-                Diverging::NotDiverging => return false,
+            _ => match diverging_fallback.get(&ty) {
+                Some(&fallback_ty) => fallback_ty,
+                None => return false,
             },
         };
         debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
@@ -105,11 +136,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         true
     }
 
-    /// Second round of fallback: Unconstrained type variables
-    /// created from the instantiation of an opaque
-    /// type fall back to the opaque type itself. This is a
-    /// somewhat incomplete attempt to manage "identity passthrough"
-    /// for `impl Trait` types.
+    /// Second round of fallback: Unconstrained type variables created
+    /// from the instantiation of an opaque type fall back to the
+    /// opaque type itself. This is a somewhat incomplete attempt to
+    /// manage "identity passthrough" for `impl Trait` types.
     ///
     /// For example, in this code:
     ///
@@ -158,4 +188,274 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
             return false;
         }
     }
+
+    /// The "diverging fallback" system is rather complicated. This is
+    /// a result of our need to balance 'do the right thing' with
+    /// backwards compatibility.
+    ///
+    /// "Diverging" type variables are variables created when we
+    /// coerce a `!` type into an unbound type variable `?X`. If they
+    /// never wind up being constrained, the "right and natural" thing
+    /// is that `?X` should "fallback" to `!`. This means that e.g. an
+    /// expression like `Some(return)` will ultimately wind up with a
+    /// type like `Option<!>` (presuming it is not assigned or
+    /// constrained to have some other type).
+    ///
+    /// However, the fallback used to be `()` (before the `!` type was
+    /// added).  Moreover, there are cases where the `!` type 'leaks
+    /// out' from dead code into type variables that affect live
+    /// code. The most common case is something like this:
+    ///
+    /// ```rust
+    /// match foo() {
+    ///     22 => Default::default(), // call this type `?D`
+    ///     _ => return, // return has type `!`
+    /// } // call the type of this match `?M`
+    /// ```
+    ///
+    /// Here, coercing the type `!` into `?M` will create a diverging
+    /// type variable `?X` where `?X <: ?M`.  We also have that `?D <:
+    /// ?M`. If `?M` winds up unconstrained, then `?X` will
+    /// fallback. If it falls back to `!`, then all the type variables
+    /// will wind up equal to `!` -- this includes the type `?D`
+    /// (since `!` doesn't implement `Default`, we wind up a "trait
+    /// not implemented" error in code like this). But since the
+    /// original fallback was `()`, this code used to compile with `?D
+    /// = ()`. This is somewhat surprising, since `Default::default()`
+    /// on its own would give an error because the types are
+    /// insufficiently constrained.
+    ///
+    /// Our solution to this dilemma is to modify diverging variables
+    /// so that they can *either* fallback to `!` (the default) or to
+    /// `()` (the backwards compatibility case). We decide which
+    /// fallback to use based on whether there is a coercion pattern
+    /// like this:
+    ///
+    /// ```
+    /// ?Diverging -> ?V
+    /// ?NonDiverging -> ?V
+    /// ?V != ?NonDiverging
+    /// ```
+    ///
+    /// Here `?Diverging` represents some diverging type variable and
+    /// `?NonDiverging` represents some non-diverging type
+    /// variable. `?V` can be any type variable (diverging or not), so
+    /// long as it is not equal to `?NonDiverging`.
+    ///
+    /// Intuitively, what we are looking for is a case where a
+    /// "non-diverging" type variable (like `?M` in our example above)
+    /// is coerced *into* some variable `?V` that would otherwise
+    /// fallback to `!`. In that case, we make `?V` fallback to `!`,
+    /// along with anything that would flow into `?V`.
+    ///
+    /// The algorithm we use:
+    /// * Identify all variables that are coerced *into* by a
+    ///   diverging variable.  Do this by iterating over each
+    ///   diverging, unsolved variable and finding all variables
+    ///   reachable from there. Call that set `D`.
+    /// * Walk over all unsolved, non-diverging variables, and find
+    ///   any variable that has an edge into `D`.
+    fn calculate_diverging_fallback(
+        &self,
+        unsolved_variables: &[Ty<'tcx>],
+    ) -> FxHashMap<Ty<'tcx>, Ty<'tcx>> {
+        debug!("calculate_diverging_fallback({:?})", unsolved_variables);
+
+        let relationships = self.fulfillment_cx.borrow_mut().relationships().clone();
+
+        // Construct a coercion graph where an edge `A -> B` indicates
+        // a type variable is that is coerced
+        let coercion_graph = self.create_coercion_graph();
+
+        // Extract the unsolved type inference variable vids; note that some
+        // unsolved variables are integer/float variables and are excluded.
+        let unsolved_vids = unsolved_variables.iter().filter_map(|ty| ty.ty_vid());
+
+        // Compute the diverging root vids D -- that is, the root vid of
+        // those type variables that (a) are the target of a coercion from
+        // a `!` type and (b) have not yet been solved.
+        //
+        // These variables are the ones that are targets for fallback to
+        // either `!` or `()`.
+        let diverging_roots: FxHashSet<ty::TyVid> = self
+            .diverging_type_vars
+            .borrow()
+            .iter()
+            .map(|&ty| self.infcx.shallow_resolve(ty))
+            .filter_map(|ty| ty.ty_vid())
+            .map(|vid| self.infcx.root_var(vid))
+            .collect();
+        debug!(
+            "calculate_diverging_fallback: diverging_type_vars={:?}",
+            self.diverging_type_vars.borrow()
+        );
+        debug!("calculate_diverging_fallback: diverging_roots={:?}", diverging_roots);
+
+        // Find all type variables that are reachable from a diverging
+        // type variable. These will typically default to `!`, unless
+        // we find later that they are *also* reachable from some
+        // other type variable outside this set.
+        let mut roots_reachable_from_diverging = DepthFirstSearch::new(&coercion_graph);
+        let mut diverging_vids = vec![];
+        let mut non_diverging_vids = vec![];
+        for unsolved_vid in unsolved_vids {
+            let root_vid = self.infcx.root_var(unsolved_vid);
+            debug!(
+                "calculate_diverging_fallback: unsolved_vid={:?} root_vid={:?} diverges={:?}",
+                unsolved_vid,
+                root_vid,
+                diverging_roots.contains(&root_vid),
+            );
+            if diverging_roots.contains(&root_vid) {
+                diverging_vids.push(unsolved_vid);
+                roots_reachable_from_diverging.push_start_node(root_vid);
+
+                debug!(
+                    "calculate_diverging_fallback: root_vid={:?} reaches {:?}",
+                    root_vid,
+                    coercion_graph.depth_first_search(root_vid).collect::<Vec<_>>()
+                );
+
+                // drain the iterator to visit all nodes reachable from this node
+                roots_reachable_from_diverging.complete_search();
+            } else {
+                non_diverging_vids.push(unsolved_vid);
+            }
+        }
+
+        debug!(
+            "calculate_diverging_fallback: roots_reachable_from_diverging={:?}",
+            roots_reachable_from_diverging,
+        );
+
+        // Find all type variables N0 that are not reachable from a
+        // diverging variable, and then compute the set reachable from
+        // N0, which we call N. These are the *non-diverging* type
+        // variables. (Note that this set consists of "root variables".)
+        let mut roots_reachable_from_non_diverging = DepthFirstSearch::new(&coercion_graph);
+        for &non_diverging_vid in &non_diverging_vids {
+            let root_vid = self.infcx.root_var(non_diverging_vid);
+            if roots_reachable_from_diverging.visited(root_vid) {
+                continue;
+            }
+            roots_reachable_from_non_diverging.push_start_node(root_vid);
+            roots_reachable_from_non_diverging.complete_search();
+        }
+        debug!(
+            "calculate_diverging_fallback: roots_reachable_from_non_diverging={:?}",
+            roots_reachable_from_non_diverging,
+        );
+
+        debug!("inherited: {:#?}", self.inh.fulfillment_cx.borrow_mut().pending_obligations());
+        debug!("obligations: {:#?}", self.fulfillment_cx.borrow_mut().pending_obligations());
+        debug!("relationships: {:#?}", relationships);
+
+        // For each diverging variable, figure out whether it can
+        // reach a member of N. If so, it falls back to `()`. Else
+        // `!`.
+        let mut diverging_fallback = FxHashMap::default();
+        diverging_fallback.reserve(diverging_vids.len());
+        for &diverging_vid in &diverging_vids {
+            let diverging_ty = self.tcx.mk_ty_var(diverging_vid);
+            let root_vid = self.infcx.root_var(diverging_vid);
+            let can_reach_non_diverging = coercion_graph
+                .depth_first_search(root_vid)
+                .any(|n| roots_reachable_from_non_diverging.visited(n));
+
+            let mut relationship = ty::FoundRelationships { self_in_trait: false, output: false };
+
+            for (vid, rel) in relationships.iter() {
+                if self.infcx.root_var(*vid) == root_vid {
+                    relationship.self_in_trait |= rel.self_in_trait;
+                    relationship.output |= rel.output;
+                }
+            }
+
+            if relationship.self_in_trait && relationship.output {
+                // This case falls back to () to ensure that the code pattern in
+                // src/test/ui/never_type/fallback-closure-ret.rs continues to
+                // compile when never_type_fallback is enabled.
+                //
+                // This rule is not readily explainable from first principles,
+                // but is rather intended as a patchwork fix to ensure code
+                // which compiles before the stabilization of never type
+                // fallback continues to work.
+                //
+                // Typically this pattern is encountered in a function taking a
+                // closure as a parameter, where the return type of that closure
+                // (checked by `relationship.output`) is expected to implement
+                // some trait (checked by `relationship.self_in_trait`). This
+                // can come up in non-closure cases too, so we do not limit this
+                // rule to specifically `FnOnce`.
+                //
+                // When the closure's body is something like `panic!()`, the
+                // return type would normally be inferred to `!`. However, it
+                // needs to fall back to `()` in order to still compile, as the
+                // trait is specifically implemented for `()` but not `!`.
+                //
+                // For details on the requirements for these relationships to be
+                // set, see the relationship finding module in
+                // compiler/rustc_trait_selection/src/traits/relationships.rs.
+                debug!("fallback to () - found trait and projection: {:?}", diverging_vid);
+                diverging_fallback.insert(diverging_ty, self.tcx.types.unit);
+            } else if can_reach_non_diverging {
+                debug!("fallback to () - reached non-diverging: {:?}", diverging_vid);
+                diverging_fallback.insert(diverging_ty, self.tcx.types.unit);
+            } else {
+                debug!("fallback to ! - all diverging: {:?}", diverging_vid);
+                diverging_fallback.insert(diverging_ty, self.tcx.mk_diverging_default());
+            }
+        }
+
+        diverging_fallback
+    }
+
+    /// Returns a graph whose nodes are (unresolved) inference variables and where
+    /// an edge `?A -> ?B` indicates that the variable `?A` is coerced to `?B`.
+    fn create_coercion_graph(&self) -> VecGraph<ty::TyVid> {
+        let pending_obligations = self.fulfillment_cx.borrow_mut().pending_obligations();
+        debug!("create_coercion_graph: pending_obligations={:?}", pending_obligations);
+        let coercion_edges: Vec<(ty::TyVid, ty::TyVid)> = pending_obligations
+            .into_iter()
+            .filter_map(|obligation| {
+                // The predicates we are looking for look like `Coerce(?A -> ?B)`.
+                // They will have no bound variables.
+                obligation.predicate.kind().no_bound_vars()
+            })
+            .filter_map(|atom| {
+                // We consider both subtyping and coercion to imply 'flow' from
+                // some position in the code `a` to a different position `b`.
+                // This is then used to determine which variables interact with
+                // live code, and as such must fall back to `()` to preserve
+                // soundness.
+                //
+                // In practice currently the two ways that this happens is
+                // coercion and subtyping.
+                let (a, b) = if let ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) = atom {
+                    (a, b)
+                } else if let ty::PredicateKind::Subtype(ty::SubtypePredicate {
+                    a_is_expected: _,
+                    a,
+                    b,
+                }) = atom
+                {
+                    (a, b)
+                } else {
+                    return None;
+                };
+
+                let a_vid = self.root_vid(a)?;
+                let b_vid = self.root_vid(b)?;
+                Some((a_vid, b_vid))
+            })
+            .collect();
+        debug!("create_coercion_graph: coercion_edges={:?}", coercion_edges);
+        let num_ty_vars = self.infcx.num_ty_vars();
+        VecGraph::new(num_ty_vars, coercion_edges)
+    }
+
+    /// If `ty` is an unresolved type variable, returns its root vid.
+    fn root_vid(&self, ty: Ty<'tcx>) -> Option<ty::TyVid> {
+        Some(self.infcx.root_var(self.infcx.shallow_resolve(ty).ty_vid()?))
+    }
 }
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index ed01dae59f6..562d05d3ef9 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -286,6 +286,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return;
         }
 
+        for a in &adj {
+            if let Adjust::NeverToAny = a.kind {
+                if a.target.is_ty_var() {
+                    self.diverging_type_vars.borrow_mut().insert(a.target);
+                    debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target);
+                }
+            }
+        }
+
         let autoborrow_mut = adj.iter().any(|adj| {
             matches!(
                 adj,
diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs
index 6006c8f7513..f7552c1f4eb 100644
--- a/compiler/rustc_typeck/src/check/inherited.rs
+++ b/compiler/rustc_typeck/src/check/inherited.rs
@@ -1,6 +1,7 @@
 use super::callee::DeferredCallResolution;
 use super::MaybeInProgressTables;
 
+use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefIdMap, LocalDefId};
 use rustc_hir::HirIdMap;
@@ -56,6 +57,11 @@ pub struct Inherited<'a, 'tcx> {
     pub(super) constness: hir::Constness,
 
     pub(super) body_id: Option<hir::BodyId>,
+
+    /// Whenever we introduce an adjustment from `!` into a type variable,
+    /// we record that type variable here. This is later used to inform
+    /// fallback. See the `fallback` module for details.
+    pub(super) diverging_type_vars: RefCell<FxHashSet<Ty<'tcx>>>,
 }
 
 impl<'a, 'tcx> Deref for Inherited<'a, 'tcx> {
@@ -121,6 +127,7 @@ impl Inherited<'a, 'tcx> {
             deferred_call_resolutions: RefCell::new(Default::default()),
             deferred_cast_checks: RefCell::new(Vec::new()),
             deferred_generator_interiors: RefCell::new(Vec::new()),
+            diverging_type_vars: RefCell::new(Default::default()),
             constness,
             body_id,
         }
diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
index 7e69ad21d03..2e3db4d6d65 100644
--- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
@@ -1,6 +1,7 @@
 use crate::structured_errors::StructuredDiagnostic;
 use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_hir as hir;
+use rustc_middle::hir::map::fn_sig;
 use rustc_middle::middle::resolve_lifetime::LifetimeScopeForPath;
 use rustc_middle::ty::{self as ty, TyCtxt};
 use rustc_session::Session;
@@ -292,12 +293,30 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
         &self,
         num_params_to_take: usize,
     ) -> String {
+        let fn_sig = self.tcx.hir().get_if_local(self.def_id).and_then(|node| fn_sig(node));
+        let is_used_in_input = |def_id| {
+            fn_sig.map_or(false, |fn_sig| {
+                fn_sig.decl.inputs.iter().any(|ty| match ty.kind {
+                    hir::TyKind::Path(hir::QPath::Resolved(
+                        None,
+                        hir::Path { res: hir::def::Res::Def(_, id), .. },
+                    )) if *id == def_id => true,
+                    _ => false,
+                })
+            })
+        };
         self.gen_params
             .params
             .iter()
             .skip(self.params_offset + self.num_provided_type_or_const_args())
             .take(num_params_to_take)
-            .map(|param| param.name.to_string())
+            .map(|param| match param.kind {
+                // This is being infered from the item's inputs, no need to set it.
+                ty::GenericParamDefKind::Type { .. } if is_used_in_input(param.def_id) => {
+                    "_".to_string()
+                }
+                _ => param.name.to_string(),
+            })
             .collect::<Vec<_>>()
             .join(", ")
     }
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 2a02545041d..daef5c98967 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -1849,17 +1849,17 @@ macro_rules! int_impl {
         #[doc = concat!("let a: ", stringify!($SelfT)," = 8;")]
         /// let b = 3;
         ///
-        /// assert_eq!(a.div_floor(b), 2);
-        /// assert_eq!(a.div_floor(-b), -3);
-        /// assert_eq!((-a).div_floor(b), -3);
-        /// assert_eq!((-a).div_floor(-b), 2);
+        /// assert_eq!(a.unstable_div_floor(b), 2);
+        /// assert_eq!(a.unstable_div_floor(-b), -3);
+        /// assert_eq!((-a).unstable_div_floor(b), -3);
+        /// assert_eq!((-a).unstable_div_floor(-b), 2);
         /// ```
         #[unstable(feature = "int_roundings", issue = "88581")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
         #[rustc_inherit_overflow_checks]
-        pub const fn div_floor(self, rhs: Self) -> Self {
+        pub const fn unstable_div_floor(self, rhs: Self) -> Self {
             let d = self / rhs;
             let r = self % rhs;
             if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
@@ -1884,17 +1884,17 @@ macro_rules! int_impl {
         #[doc = concat!("let a: ", stringify!($SelfT)," = 8;")]
         /// let b = 3;
         ///
-        /// assert_eq!(a.div_ceil(b), 3);
-        /// assert_eq!(a.div_ceil(-b), -2);
-        /// assert_eq!((-a).div_ceil(b), -2);
-        /// assert_eq!((-a).div_ceil(-b), 3);
+        /// assert_eq!(a.unstable_div_ceil(b), 3);
+        /// assert_eq!(a.unstable_div_ceil(-b), -2);
+        /// assert_eq!((-a).unstable_div_ceil(b), -2);
+        /// assert_eq!((-a).unstable_div_ceil(-b), 3);
         /// ```
         #[unstable(feature = "int_roundings", issue = "88581")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
         #[rustc_inherit_overflow_checks]
-        pub const fn div_ceil(self, rhs: Self) -> Self {
+        pub const fn unstable_div_ceil(self, rhs: Self) -> Self {
             let d = self / rhs;
             let r = self % rhs;
             if (r > 0 && rhs > 0) || (r < 0 && rhs < 0) {
@@ -1919,21 +1919,21 @@ macro_rules! int_impl {
         ///
         /// ```
         /// #![feature(int_roundings)]
-        #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")]
-        #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")]
-        #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(-8), 16);")]
-        #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(-8), 16);")]
-        #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(8), -16);")]
-        #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(8), -16);")]
-        #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(-8), -16);")]
-        #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(-8), -24);")]
+        #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".unstable_next_multiple_of(8), 16);")]
+        #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".unstable_next_multiple_of(8), 24);")]
+        #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".unstable_next_multiple_of(-8), 16);")]
+        #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".unstable_next_multiple_of(-8), 16);")]
+        #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").unstable_next_multiple_of(8), -16);")]
+        #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").unstable_next_multiple_of(8), -16);")]
+        #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").unstable_next_multiple_of(-8), -16);")]
+        #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").unstable_next_multiple_of(-8), -24);")]
         /// ```
         #[unstable(feature = "int_roundings", issue = "88581")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
         #[rustc_inherit_overflow_checks]
-        pub const fn next_multiple_of(self, rhs: Self) -> Self {
+        pub const fn unstable_next_multiple_of(self, rhs: Self) -> Self {
             // This would otherwise fail when calculating `r` when self == T::MIN.
             if rhs == -1 {
                 return self;
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 7523d8ec976..8ce82662630 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1859,12 +1859,12 @@ macro_rules! uint_impl {
         ///
         /// ```
         /// #![feature(int_roundings)]
-        #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_floor(4), 1);")]
+        #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".unstable_div_floor(4), 1);")]
         /// ```
         #[unstable(feature = "int_roundings", issue = "88581")]
         #[inline(always)]
         #[rustc_inherit_overflow_checks]
-        pub const fn div_floor(self, rhs: Self) -> Self {
+        pub const fn unstable_div_floor(self, rhs: Self) -> Self {
             self / rhs
         }
 
@@ -1880,12 +1880,12 @@ macro_rules! uint_impl {
         ///
         /// ```
         /// #![feature(int_roundings)]
-        #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_ceil(4), 2);")]
+        #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".unstable_div_ceil(4), 2);")]
         /// ```
         #[unstable(feature = "int_roundings", issue = "88581")]
         #[inline]
         #[rustc_inherit_overflow_checks]
-        pub const fn div_ceil(self, rhs: Self) -> Self {
+        pub const fn unstable_div_ceil(self, rhs: Self) -> Self {
             let d = self / rhs;
             let r = self % rhs;
             if r > 0 && rhs > 0 {
@@ -1908,15 +1908,15 @@ macro_rules! uint_impl {
         ///
         /// ```
         /// #![feature(int_roundings)]
-        #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")]
-        #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")]
+        #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".unstable_next_multiple_of(8), 16);")]
+        #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".unstable_next_multiple_of(8), 24);")]
         /// ```
         #[unstable(feature = "int_roundings", issue = "88581")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
         #[rustc_inherit_overflow_checks]
-        pub const fn next_multiple_of(self, rhs: Self) -> Self {
+        pub const fn unstable_next_multiple_of(self, rhs: Self) -> Self {
             match self % rhs {
                 0 => self,
                 r => self + (rhs - r)
diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs
index d2d655ea2c7..0ad85bf6d94 100644
--- a/library/core/tests/num/int_macros.rs
+++ b/library/core/tests/num/int_macros.rs
@@ -294,33 +294,33 @@ macro_rules! int_module {
             fn test_div_floor() {
                 let a: $T = 8;
                 let b = 3;
-                assert_eq!(a.div_floor(b), 2);
-                assert_eq!(a.div_floor(-b), -3);
-                assert_eq!((-a).div_floor(b), -3);
-                assert_eq!((-a).div_floor(-b), 2);
+                assert_eq!(a.unstable_div_floor(b), 2);
+                assert_eq!(a.unstable_div_floor(-b), -3);
+                assert_eq!((-a).unstable_div_floor(b), -3);
+                assert_eq!((-a).unstable_div_floor(-b), 2);
             }
 
             #[test]
             fn test_div_ceil() {
                 let a: $T = 8;
                 let b = 3;
-                assert_eq!(a.div_ceil(b), 3);
-                assert_eq!(a.div_ceil(-b), -2);
-                assert_eq!((-a).div_ceil(b), -2);
-                assert_eq!((-a).div_ceil(-b), 3);
+                assert_eq!(a.unstable_div_ceil(b), 3);
+                assert_eq!(a.unstable_div_ceil(-b), -2);
+                assert_eq!((-a).unstable_div_ceil(b), -2);
+                assert_eq!((-a).unstable_div_ceil(-b), 3);
             }
 
             #[test]
             fn test_next_multiple_of() {
-                assert_eq!((16 as $T).next_multiple_of(8), 16);
-                assert_eq!((23 as $T).next_multiple_of(8), 24);
-                assert_eq!((16 as $T).next_multiple_of(-8), 16);
-                assert_eq!((23 as $T).next_multiple_of(-8), 16);
-                assert_eq!((-16 as $T).next_multiple_of(8), -16);
-                assert_eq!((-23 as $T).next_multiple_of(8), -16);
-                assert_eq!((-16 as $T).next_multiple_of(-8), -16);
-                assert_eq!((-23 as $T).next_multiple_of(-8), -24);
-                assert_eq!(MIN.next_multiple_of(-1), MIN);
+                assert_eq!((16 as $T).unstable_next_multiple_of(8), 16);
+                assert_eq!((23 as $T).unstable_next_multiple_of(8), 24);
+                assert_eq!((16 as $T).unstable_next_multiple_of(-8), 16);
+                assert_eq!((23 as $T).unstable_next_multiple_of(-8), 16);
+                assert_eq!((-16 as $T).unstable_next_multiple_of(8), -16);
+                assert_eq!((-23 as $T).unstable_next_multiple_of(8), -16);
+                assert_eq!((-16 as $T).unstable_next_multiple_of(-8), -16);
+                assert_eq!((-23 as $T).unstable_next_multiple_of(-8), -24);
+                assert_eq!(MIN.unstable_next_multiple_of(-1), MIN);
             }
 
             #[test]
diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs
index 49f8f1f13fa..35ec88c6af7 100644
--- a/library/core/tests/num/uint_macros.rs
+++ b/library/core/tests/num/uint_macros.rs
@@ -208,19 +208,19 @@ macro_rules! uint_module {
 
             #[test]
             fn test_div_floor() {
-                assert_eq!((8 as $T).div_floor(3), 2);
+                assert_eq!((8 as $T).unstable_div_floor(3), 2);
             }
 
             #[test]
             fn test_div_ceil() {
-                assert_eq!((8 as $T).div_ceil(3), 3);
+                assert_eq!((8 as $T).unstable_div_ceil(3), 3);
             }
 
             #[test]
             fn test_next_multiple_of() {
-                assert_eq!((16 as $T).next_multiple_of(8), 16);
-                assert_eq!((23 as $T).next_multiple_of(8), 24);
-                assert_eq!(MAX.next_multiple_of(1), MAX);
+                assert_eq!((16 as $T).unstable_next_multiple_of(8), 16);
+                assert_eq!((23 as $T).unstable_next_multiple_of(8), 24);
+                assert_eq!(MAX.unstable_next_multiple_of(1), MAX);
             }
 
             #[test]
diff --git a/library/std/src/sync/mpsc/shared.rs b/library/std/src/sync/mpsc/shared.rs
index 0c32e636a56..8487a5f8b50 100644
--- a/library/std/src/sync/mpsc/shared.rs
+++ b/library/std/src/sync/mpsc/shared.rs
@@ -248,7 +248,11 @@ impl<T> Packet<T> {
     // Returns true if blocking should proceed.
     fn decrement(&self, token: SignalToken) -> StartResult {
         unsafe {
-            assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
+            assert_eq!(
+                self.to_wake.load(Ordering::SeqCst),
+                0,
+                "This is a known bug in the Rust standard library. See https://github.com/rust-lang/rust/issues/39364"
+            );
             let ptr = token.cast_to_usize();
             self.to_wake.store(ptr, Ordering::SeqCst);
 
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 86c7daa627aefda1371568b948eba21edf72074
+Subproject cba558df777a045b5657d56c29944e9e8fd3a77
diff --git a/src/test/rustdoc/cross-crate-primitive-doc.rs b/src/test/rustdoc/cross-crate-primitive-doc.rs
index 120b6e9747f..4ba296ee04a 100644
--- a/src/test/rustdoc/cross-crate-primitive-doc.rs
+++ b/src/test/rustdoc/cross-crate-primitive-doc.rs
@@ -1,6 +1,6 @@
 // aux-build:primitive-doc.rs
 // compile-flags: --extern-html-root-url=primitive_doc=../ -Z unstable-options
-// ignore-windows
+// only-linux
 
 #![feature(no_core)]
 #![no_core]
diff --git a/src/test/rustdoc/intra-doc/prim-methods-external-core.rs b/src/test/rustdoc/intra-doc/prim-methods-external-core.rs
index 5a92a28556e..9d869984bbd 100644
--- a/src/test/rustdoc/intra-doc/prim-methods-external-core.rs
+++ b/src/test/rustdoc/intra-doc/prim-methods-external-core.rs
@@ -1,7 +1,7 @@
 // aux-build:my-core.rs
 // build-aux-docs
 // ignore-cross-compile
-// ignore-windows
+// only-linux
 
 #![deny(broken_intra_doc_links)]
 #![feature(no_core, lang_items)]
diff --git a/src/test/ui/attributes/extented-attribute-macro-error.rs b/src/test/ui/attributes/extented-attribute-macro-error.rs
new file mode 100644
index 00000000000..f5f75f9f4da
--- /dev/null
+++ b/src/test/ui/attributes/extented-attribute-macro-error.rs
@@ -0,0 +1,8 @@
+// normalize-stderr-test: "couldn't read.*" -> "couldn't read the file"
+
+#![feature(extended_key_value_attributes)]
+#![doc = include_str!("../not_existing_file.md")]
+struct Documented {}
+//~^^ ERROR couldn't read
+
+fn main() {}
diff --git a/src/test/ui/attributes/extented-attribute-macro-error.stderr b/src/test/ui/attributes/extented-attribute-macro-error.stderr
new file mode 100644
index 00000000000..e4deeacd0ff
--- /dev/null
+++ b/src/test/ui/attributes/extented-attribute-macro-error.stderr
@@ -0,0 +1,10 @@
+error: couldn't read the file
+  --> $DIR/extented-attribute-macro-error.rs:4:10
+   |
+LL | #![doc = include_str!("../not_existing_file.md")]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr
new file mode 100644
index 00000000000..fbaa874792a
--- /dev/null
+++ b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `(): std::error::Error` is not satisfied
+  --> $DIR/coerce-issue-49593-box-never.rs:17:53
+   |
+LL |     /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
+   |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
+   |
+   = note: required for the cast to the object type `dyn std::error::Error`
+
+error[E0277]: the trait bound `(): std::error::Error` is not satisfied
+  --> $DIR/coerce-issue-49593-box-never.rs:22:49
+   |
+LL |     /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
+   |
+   = note: required for the cast to the object type `(dyn std::error::Error + 'static)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.rs b/src/test/ui/coercion/coerce-issue-49593-box-never.rs
index 0824ce8cd58..7a4324bd5ad 100644
--- a/src/test/ui/coercion/coerce-issue-49593-box-never.rs
+++ b/src/test/ui/coercion/coerce-issue-49593-box-never.rs
@@ -1,5 +1,9 @@
-// check-pass
-#![feature(never_type, never_type_fallback)]
+// revisions: nofallback fallback
+//[fallback] check-pass
+//[nofallback] check-fail
+
+#![feature(never_type)]
+#![cfg_attr(fallback, feature(never_type_fallback))]
 #![allow(unreachable_code)]
 
 use std::error::Error;
@@ -11,10 +15,12 @@ fn raw_ptr_box<T>(t: T) -> *mut T {
 
 fn foo(x: !) -> Box<dyn Error> {
     /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
+    //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied
 }
 
 fn foo_raw_ptr(x: !) -> *mut dyn Error {
     /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
+    //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied
 }
 
 fn no_coercion(d: *mut dyn Error) -> *mut dyn Error {
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index a31c104d8f5..634ff14869e 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -34,7 +34,7 @@ note: ...which requires type-checking `cycle1`...
    |
 LL |     send(cycle2().clone());
    |     ^^^^
-   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+   = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
 note: ...which requires computing type of `cycle2::{opaque#0}`...
   --> $DIR/auto-trait-leak.rs:19:16
    |
@@ -70,7 +70,7 @@ note: ...which requires type-checking `cycle2`...
    |
 LL |     send(cycle1().clone());
    |     ^^^^
-   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+   = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
    = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/auto-trait-leak.rs:1:1
diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
index 88ef8182f02..50f1a2f25b9 100644
--- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
+++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
@@ -2,6 +2,7 @@
 // ignore-wasm32-bare compiled with panic=abort by default
 // revisions: mir thir
 // [thir]compile-flags: -Zthir-unsafeck
+// ignore-tidy-linelength
 
 // This test checks panic emitted from `mem::{uninitialized,zeroed}`.
 
@@ -114,11 +115,11 @@ fn main() {
 
         test_panic_msg(
             || mem::uninitialized::<*const dyn Send>(),
-            "attempted to leave type `*const dyn std::marker::Send` uninitialized, which is invalid"
+            "attempted to leave type `*const dyn core::marker::Send` uninitialized, which is invalid"
         );
         test_panic_msg(
             || mem::zeroed::<*const dyn Send>(),
-            "attempted to zero-initialize type `*const dyn std::marker::Send`, which is invalid"
+            "attempted to zero-initialize type `*const dyn core::marker::Send`, which is invalid"
         );
 
         /* FIXME(#66151) we conservatively do not error here yet.
@@ -145,12 +146,12 @@ fn main() {
 
         test_panic_msg(
             || mem::uninitialized::<(NonNull<u32>, u32, u32)>(),
-            "attempted to leave type `(std::ptr::NonNull<u32>, u32, u32)` uninitialized, \
+            "attempted to leave type `(core::ptr::non_null::NonNull<u32>, u32, u32)` uninitialized, \
                 which is invalid"
         );
         test_panic_msg(
             || mem::zeroed::<(NonNull<u32>, u32, u32)>(),
-            "attempted to zero-initialize type `(std::ptr::NonNull<u32>, u32, u32)`, \
+            "attempted to zero-initialize type `(core::ptr::non_null::NonNull<u32>, u32, u32)`, \
                 which is invalid"
         );
 
@@ -187,7 +188,7 @@ fn main() {
         );
         test_panic_msg(
             || mem::uninitialized::<ManuallyDrop<LR>>(),
-            "attempted to leave type `std::mem::ManuallyDrop<LR>` uninitialized, which is invalid"
+            "attempted to leave type `core::mem::manually_drop::ManuallyDrop<LR>` uninitialized, which is invalid"
         );
 
         // Some things that should work.
diff --git a/src/test/ui/never_type/defaulted-never-note.stderr b/src/test/ui/never_type/defaulted-never-note.fallback.stderr
index 109a81a5ca0..588d644c77b 100644
--- a/src/test/ui/never_type/defaulted-never-note.stderr
+++ b/src/test/ui/never_type/defaulted-never-note.fallback.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied
-  --> $DIR/defaulted-never-note.rs:26:5
+  --> $DIR/defaulted-never-note.rs:30:5
    |
 LL |     foo(_x);
    |     ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!`
@@ -8,7 +8,7 @@ LL |     foo(_x);
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information).
    = help: did you intend to use the type `()` here instead?
 note: required by a bound in `foo`
-  --> $DIR/defaulted-never-note.rs:21:11
+  --> $DIR/defaulted-never-note.rs:25:11
    |
 LL | fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
diff --git a/src/test/ui/never_type/defaulted-never-note.rs b/src/test/ui/never_type/defaulted-never-note.rs
index 70333c5f324..54f551759cb 100644
--- a/src/test/ui/never_type/defaulted-never-note.rs
+++ b/src/test/ui/never_type/defaulted-never-note.rs
@@ -1,6 +1,10 @@
+// revisions: nofallback fallback
+//[nofallback] run-pass
+//[fallback] check-fail
+
 // We need to opt into the `never_type_fallback` feature
 // to trigger the requirement that this is testing.
-#![feature(never_type, never_type_fallback)]
+#![cfg_attr(fallback, feature(never_type, never_type_fallback))]
 
 #![allow(unused)]
 
@@ -19,16 +23,16 @@ trait ImplementedForUnitButNotNever {}
 impl ImplementedForUnitButNotNever for () {}
 
 fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
-//~^ NOTE required by this bound in `foo`
-//~| NOTE required by a bound in `foo`
+//[fallback]~^ NOTE required by this bound in `foo`
+//[fallback]~| NOTE required by a bound in `foo`
 fn smeg() {
     let _x = return;
     foo(_x);
-    //~^ ERROR the trait bound
-    //~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented
-    //~| NOTE this trait is implemented for `()`
-    //~| NOTE this error might have been caused
-    //~| HELP did you intend
+    //[fallback]~^ ERROR the trait bound
+    //[fallback]~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented
+    //[fallback]~| NOTE this trait is implemented for `()`
+    //[fallback]~| NOTE this error might have been caused
+    //[fallback]~| HELP did you intend
 }
 
 fn main() {
diff --git a/src/test/ui/never_type/diverging-fallback-control-flow.rs b/src/test/ui/never_type/diverging-fallback-control-flow.rs
index ea4881049d7..45a3362fa6d 100644
--- a/src/test/ui/never_type/diverging-fallback-control-flow.rs
+++ b/src/test/ui/never_type/diverging-fallback-control-flow.rs
@@ -1,30 +1,28 @@
+// revisions: nofallback fallback
 // run-pass
 
 #![allow(dead_code)]
 #![allow(unused_assignments)]
 #![allow(unused_variables)]
 #![allow(unreachable_code)]
-
 // Test various cases where we permit an unconstrained variable
-// to fallback based on control-flow.
-//
-// These represent current behavior, but are pretty dubious.  I would
-// like to revisit these and potentially change them. --nmatsakis
-
-#![feature(never_type, never_type_fallback)]
+// to fallback based on control-flow. In all of these cases,
+// the type variable winds up being the target of both a `!` coercion
+// and a coercion from a non-`!` variable, and hence falls back to `()`.
+#![cfg_attr(fallback, feature(never_type, never_type_fallback))]
 
-trait BadDefault {
+trait UnitDefault {
     fn default() -> Self;
 }
 
-impl BadDefault for u32 {
+impl UnitDefault for u32 {
     fn default() -> Self {
         0
     }
 }
 
-impl BadDefault for ! {
-    fn default() -> ! {
+impl UnitDefault for () {
+    fn default() -> () {
         panic!()
     }
 }
@@ -33,7 +31,7 @@ fn assignment() {
     let x;
 
     if true {
-        x = BadDefault::default();
+        x = UnitDefault::default();
     } else {
         x = return;
     }
@@ -45,13 +43,13 @@ fn assignment_rev() {
     if true {
         x = return;
     } else {
-        x = BadDefault::default();
+        x = UnitDefault::default();
     }
 }
 
 fn if_then_else() {
     let _x = if true {
-        BadDefault::default()
+        UnitDefault::default()
     } else {
         return;
     };
@@ -61,19 +59,19 @@ fn if_then_else_rev() {
     let _x = if true {
         return;
     } else {
-        BadDefault::default()
+        UnitDefault::default()
     };
 }
 
 fn match_arm() {
-    let _x = match Ok(BadDefault::default()) {
+    let _x = match Ok(UnitDefault::default()) {
         Ok(v) => v,
         Err(()) => return,
     };
 }
 
 fn match_arm_rev() {
-    let _x = match Ok(BadDefault::default()) {
+    let _x = match Ok(UnitDefault::default()) {
         Err(()) => return,
         Ok(v) => v,
     };
@@ -84,7 +82,7 @@ fn loop_break() {
         if false {
             break return;
         } else {
-            break BadDefault::default();
+            break UnitDefault::default();
         }
     };
 }
@@ -94,9 +92,9 @@ fn loop_break_rev() {
         if false {
             break return;
         } else {
-            break BadDefault::default();
+            break UnitDefault::default();
         }
     };
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr
new file mode 100644
index 00000000000..3a5b602f111
--- /dev/null
+++ b/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `!: Test` is not satisfied
+  --> $DIR/diverging-fallback-no-leak.rs:17:5
+   |
+LL |     unconstrained_arg(return);
+   |     ^^^^^^^^^^^^^^^^^ the trait `Test` is not implemented for `!`
+   |
+   = note: this trait is implemented for `()`.
+   = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information).
+   = help: did you intend to use the type `()` here instead?
+note: required by a bound in `unconstrained_arg`
+  --> $DIR/diverging-fallback-no-leak.rs:12:25
+   |
+LL | fn unconstrained_arg<T: Test>(_: T) {}
+   |                         ^^^^ required by this bound in `unconstrained_arg`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/never_type/diverging-fallback-no-leak.rs b/src/test/ui/never_type/diverging-fallback-no-leak.rs
new file mode 100644
index 00000000000..03478e19ddc
--- /dev/null
+++ b/src/test/ui/never_type/diverging-fallback-no-leak.rs
@@ -0,0 +1,19 @@
+// revisions: nofallback fallback
+//[nofallback] check-pass
+
+#![cfg_attr(fallback, feature(never_type, never_type_fallback))]
+
+fn make_unit() {}
+
+trait Test {}
+impl Test for i32 {}
+impl Test for () {}
+
+fn unconstrained_arg<T: Test>(_: T) {}
+
+fn main() {
+    // Here the type variable falls back to `!`,
+    // and hence we get a type error.
+    unconstrained_arg(return);
+    //[fallback]~^ ERROR trait bound `!: Test` is not satisfied
+}
diff --git a/src/test/ui/never_type/diverging-fallback-unconstrained-return.rs b/src/test/ui/never_type/diverging-fallback-unconstrained-return.rs
new file mode 100644
index 00000000000..7ea97126f89
--- /dev/null
+++ b/src/test/ui/never_type/diverging-fallback-unconstrained-return.rs
@@ -0,0 +1,37 @@
+// Variant of diverging-falllback-control-flow that tests
+// the specific case of a free function with an unconstrained
+// return type. This captures the pattern we saw in the wild
+// in the objc crate, where changing the fallback from `!` to `()`
+// resulted in unsoundness.
+//
+// check-pass
+
+// revisions: nofallback fallback
+
+#![cfg_attr(fallback, feature(never_type, never_type_fallback))]
+
+
+fn make_unit() {}
+
+trait UnitReturn {}
+impl UnitReturn for i32 {}
+impl UnitReturn for () {}
+
+fn unconstrained_return<T: UnitReturn>() -> T {
+    unsafe {
+        let make_unit_fn: fn() = make_unit;
+        let ffi: fn() -> T = std::mem::transmute(make_unit_fn);
+        ffi()
+    }
+}
+
+fn main() {
+    // In Ye Olde Days, the `T` parameter of `unconstrained_return`
+    // winds up "entangled" with the `!` type that results from
+    // `panic!`, and hence falls back to `()`. This is kind of unfortunate
+    // and unexpected. When we introduced the `!` type, the original
+    // idea was to change that fallback to `!`, but that would have resulted
+    // in this code no longer compiling (or worse, in some cases it injected
+    // unsound results).
+    let _ = if true { unconstrained_return() } else { panic!() };
+}
diff --git a/src/test/ui/never_type/fallback-closure-ret.rs b/src/test/ui/never_type/fallback-closure-ret.rs
new file mode 100644
index 00000000000..5c8ce48cbb0
--- /dev/null
+++ b/src/test/ui/never_type/fallback-closure-ret.rs
@@ -0,0 +1,23 @@
+// This test verifies that never type fallback preserves the following code in a
+// compiling state. This pattern is fairly common in the wild, notably seen in
+// wasmtime v0.16. Typically this is some closure wrapper that expects a
+// collection of 'known' signatures, and -> ! is not included in that set.
+//
+// This test is specifically targeted by the unit type fallback when
+// encountering a set of obligations like `?T: Foo` and `Trait::Projection =
+// ?T`. In the code below, these are `R: Bar` and `Fn::Output = R`.
+//
+// revisions: nofallback fallback
+// check-pass
+
+#![cfg_attr(fallback, feature(never_type_fallback))]
+
+trait Bar { }
+impl Bar for () {  }
+impl Bar for u32 {  }
+
+fn foo<R: Bar>(_: impl Fn() -> R) {}
+
+fn main() {
+    foo(|| panic!());
+}
diff --git a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr
new file mode 100644
index 00000000000..78d1a3caf4a
--- /dev/null
+++ b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr
@@ -0,0 +1,17 @@
+error[E0271]: type mismatch resolving `<[closure@$DIR/fallback-closure-wrap.rs:18:40: 21:6] as FnOnce<()>>::Output == ()`
+  --> $DIR/fallback-closure-wrap.rs:18:31
+   |
+LL |       let error = Closure::wrap(Box::new(move || {
+   |  _______________________________^
+LL | |
+LL | |         panic!("Can't connect to server.");
+LL | |     }) as Box<dyn FnMut()>);
+   | |______^ expected `()`, found `!`
+   |
+   = note: expected unit type `()`
+                   found type `!`
+   = note: required for the cast to the object type `dyn FnMut()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/never_type/fallback-closure-wrap.rs b/src/test/ui/never_type/fallback-closure-wrap.rs
new file mode 100644
index 00000000000..af0577ac060
--- /dev/null
+++ b/src/test/ui/never_type/fallback-closure-wrap.rs
@@ -0,0 +1,30 @@
+// This is a minified example from Crater breakage observed when attempting to
+// stabilize never type, nstoddard/webgl-gui @ 22f0169f.
+//
+// This particular test case currently fails as the inference to `()` rather
+// than `!` happens as a result of an `as` cast, which is not currently tracked.
+// Crater did not find many cases of this occuring, but it is included for
+// awareness.
+//
+// revisions: nofallback fallback
+//[nofallback] check-pass
+//[fallback] check-fail
+
+#![cfg_attr(fallback, feature(never_type_fallback))]
+
+use std::marker::PhantomData;
+
+fn main() {
+    let error = Closure::wrap(Box::new(move || {
+        //[fallback]~^ ERROR type mismatch resolving
+        panic!("Can't connect to server.");
+    }) as Box<dyn FnMut()>);
+}
+
+struct Closure<T: ?Sized>(PhantomData<T>);
+
+impl<T: ?Sized> Closure<T> {
+    fn wrap(data: Box<T>) -> Closure<T> {
+        todo!()
+    }
+}
diff --git a/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
new file mode 100644
index 00000000000..f374266626b
--- /dev/null
+++ b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `E: From<()>` is not satisfied
+  --> $DIR/never-value-fallback-issue-66757.rs:27:5
+   |
+LL |     <E as From<_>>::from(never);
+   |     ^^^^^^^^^^^^^^^^^^^^ the trait `From<()>` is not implemented for `E`
+   |
+   = help: the following implementations were found:
+             <E as From<!>>
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/never_type/never-value-fallback-issue-66757.rs b/src/test/ui/never_type/never-value-fallback-issue-66757.rs
index f2e9e087307..6dc7e6ad2d9 100644
--- a/src/test/ui/never_type/never-value-fallback-issue-66757.rs
+++ b/src/test/ui/never_type/never-value-fallback-issue-66757.rs
@@ -4,12 +4,13 @@
 // never) and an uninferred variable (here the argument to `From`) it
 // doesn't fallback to `()` but rather `!`.
 //
-// run-pass
+// revisions: nofallback fallback
+//[fallback] run-pass
+//[nofallback] check-fail
 
 #![feature(never_type)]
 
-// FIXME(#67225) -- this should be true even without the fallback gate.
-#![feature(never_type_fallback)]
+#![cfg_attr(fallback, feature(never_type_fallback))]
 
 struct E;
 
@@ -23,7 +24,7 @@ impl From<!> for E {
 #[allow(dead_code)]
 fn foo(never: !) {
     <E as From<!>>::from(never);  // Ok
-    <E as From<_>>::from(never);  // Inference fails here
+    <E as From<_>>::from(never);  //[nofallback]~ ERROR trait bound `E: From<()>` is not satisfied
 }
 
 fn main() { }
diff --git a/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs b/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs
index 03cb3e24b7d..4fd5622b062 100644
--- a/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs
+++ b/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs
@@ -1,8 +1,8 @@
 //~ ERROR cycle detected when computing layout of `S`
-//~| NOTE ...which requires computing layout of `std::option::Option<<S as Mirror>::It>`...
-//~| NOTE ...which requires computing layout of `std::option::Option<S>`...
+//~| NOTE ...which requires computing layout of `core::option::Option<<S as Mirror>::It>`...
+//~| NOTE ...which requires computing layout of `core::option::Option<S>`...
 //~| NOTE ...which again requires computing layout of `S`, completing the cycle
-//~| NOTE cycle used when computing layout of `std::option::Option<S>`
+//~| NOTE cycle used when computing layout of `core::option::Option<S>`
 
 // build-fail
 
diff --git a/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr b/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr
index 21c0e1e6de5..6042379a918 100644
--- a/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr
+++ b/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr
@@ -1,9 +1,9 @@
 error[E0391]: cycle detected when computing layout of `S`
    |
-   = note: ...which requires computing layout of `std::option::Option<<S as Mirror>::It>`...
-   = note: ...which requires computing layout of `std::option::Option<S>`...
+   = note: ...which requires computing layout of `core::option::Option<<S as Mirror>::It>`...
+   = note: ...which requires computing layout of `core::option::Option<S>`...
    = note: ...which again requires computing layout of `S`, completing the cycle
-   = note: cycle used when computing layout of `std::option::Option<S>`
+   = note: cycle used when computing layout of `core::option::Option<S>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/missing-type-param-used-in-param.fixed b/src/test/ui/suggestions/missing-type-param-used-in-param.fixed
new file mode 100644
index 00000000000..cc4120041b9
--- /dev/null
+++ b/src/test/ui/suggestions/missing-type-param-used-in-param.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn two_type_params<A, B>(_: B) {}
+
+fn main() {
+    two_type_params::<String, _>(100); //~ ERROR this function takes 2 generic arguments
+    two_type_params::<String, _>(100);
+}
diff --git a/src/test/ui/suggestions/missing-type-param-used-in-param.rs b/src/test/ui/suggestions/missing-type-param-used-in-param.rs
new file mode 100644
index 00000000000..19286331b60
--- /dev/null
+++ b/src/test/ui/suggestions/missing-type-param-used-in-param.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn two_type_params<A, B>(_: B) {}
+
+fn main() {
+    two_type_params::<String>(100); //~ ERROR this function takes 2 generic arguments
+    two_type_params::<String, _>(100);
+}
diff --git a/src/test/ui/suggestions/missing-type-param-used-in-param.stderr b/src/test/ui/suggestions/missing-type-param-used-in-param.stderr
new file mode 100644
index 00000000000..4f7058a6492
--- /dev/null
+++ b/src/test/ui/suggestions/missing-type-param-used-in-param.stderr
@@ -0,0 +1,21 @@
+error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
+  --> $DIR/missing-type-param-used-in-param.rs:6:5
+   |
+LL |     two_type_params::<String>(100);
+   |     ^^^^^^^^^^^^^^^   ------ supplied 1 generic argument
+   |     |
+   |     expected 2 generic arguments
+   |
+note: function defined here, with 2 generic parameters: `A`, `B`
+  --> $DIR/missing-type-param-used-in-param.rs:3:4
+   |
+LL | fn two_type_params<A, B>(_: B) {}
+   |    ^^^^^^^^^^^^^^^ -  -
+help: add missing generic argument
+   |
+LL |     two_type_params::<String, _>(100);
+   |                             +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
index 86b3f87d34d..c0147e56c93 100644
--- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
+++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
@@ -9,7 +9,7 @@ note: ...which requires type-checking `m::bar`...
    |
 LL |         is_send(foo());
    |         ^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `impl std::fmt::Debug: std::marker::Send`...
+   = note: ...which requires evaluating trait selection obligation `impl core::fmt::Debug: core::marker::Send`...
    = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in module `m`
   --> $DIR/auto-trait-leakage3.rs:6:1
diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
index 4c5921c7f66..e1212466477 100644
--- a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
+++ b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
@@ -9,7 +9,7 @@ note: ...which requires type-checking `m::bar`...
    |
 LL |         is_send(foo()); // Today: error
    |         ^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `impl std::fmt::Debug: std::marker::Send`...
+   = note: ...which requires evaluating trait selection obligation `impl core::fmt::Debug: core::marker::Send`...
    = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in module `m`
   --> $DIR/inference-cycle.rs:4:1