about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-16 17:33:12 +0000
committerbors <bors@rust-lang.org>2024-01-16 17:33:12 +0000
commite64f8495e73fbc3653b4bcb73268c58b9c4a0a0d (patch)
tree6b16f77d02262d36feed138a7bebb30dedd74ffe
parentbf2637f4e89aab364d7ab28deb09820363bef86d (diff)
parent91544102aa603a437dae8e1f9a91496a1602a943 (diff)
downloadrust-e64f8495e73fbc3653b4bcb73268c58b9c4a0a0d.tar.gz
rust-e64f8495e73fbc3653b4bcb73268c58b9c4a0a0d.zip
Auto merge of #120025 - matthiaskrgr:rollup-e9ai06k, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #118361 (stabilise bound_map)
 - #119816 (Define hidden types in confirmation)
 - #119900 (Inline `check_closure`, simplify `deduce_sig_from_projection`)
 - #119969 (Simplify `closure_env_ty` and `closure_env_param`)
 - #119990 (Add private `NonZero<T>` type alias.)
 - #119998 (Update books)
 - #120002 (Lint `overlapping_ranges_endpoints` directly instead of collecting into a Vec)
 - #120018 (Don't allow `.html` files in `tests/mir-opt/`)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs67
-rw-r--r--compiler/rustc_middle/src/ty/util.rs14
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs56
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs25
-rw-r--r--compiler/rustc_pattern_analysis/src/lints.rs32
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs37
-rw-r--r--compiler/rustc_pattern_analysis/src/usefulness.rs54
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs2
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs6
-rw-r--r--library/core/src/num/mod.rs18
-rw-r--r--library/core/src/num/nonzero.rs63
-rw-r--r--library/core/src/num/uint_macros.rs4
-rw-r--r--library/core/src/ops/range.rs4
-rw-r--r--library/core/src/slice/iter.rs6
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/tools/miropt-test-tools/src/lib.rs11
-rw-r--r--tests/ui/type-alias-impl-trait/nested_inference_failure.rs28
21 files changed, 216 insertions, 217 deletions
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index addb41ff5fc..ae8a135f090 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -668,7 +668,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     kind: ty::BrEnv,
                 };
                 let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
-                let closure_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap();
+                let closure_ty = tcx.closure_env_ty(
+                    Ty::new_closure(tcx, def_id, args),
+                    args.as_closure().kind(),
+                    env_region,
+                );
 
                 // The "inputs" of the closure in the
                 // signature appear as a tuple. The MIR side
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index b6b33299315..57fdfa4ecb6 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -14,7 +14,7 @@ use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::ArgKind;
@@ -49,7 +49,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr_span: Span,
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        trace!("decl = {:#?}", closure.fn_decl);
+        let tcx = self.tcx;
+        let body = tcx.hir().body(closure.body);
+        let expr_def_id = closure.def_id;
 
         // It's always helpful for inference if we know the kind of
         // closure sooner rather than later, so first examine the expected
@@ -61,24 +63,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             None => (None, None),
         };
 
-        self.check_closure(closure, expr_span, expected_kind, expected_sig)
-    }
-
-    #[instrument(skip(self, closure), level = "debug", ret)]
-    fn check_closure(
-        &self,
-        closure: &hir::Closure<'tcx>,
-        expr_span: Span,
-        opt_kind: Option<ty::ClosureKind>,
-        expected_sig: Option<ExpectedSig<'tcx>>,
-    ) -> Ty<'tcx> {
-        let tcx = self.tcx;
-        let body = tcx.hir().body(closure.body);
-
-        trace!("decl = {:#?}", closure.fn_decl);
-        let expr_def_id = closure.def_id;
-        debug!(?expr_def_id);
-
         let ClosureSignatures { bound_sig, liberated_sig } =
             self.sig_of_closure(expr_def_id, closure.fn_decl, closure.kind, expected_sig);
 
@@ -139,9 +123,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         };
 
-        let mut fcx = FnCtxt::new(self, self.param_env, closure.def_id);
         check_fn(
-            &mut fcx,
+            &mut FnCtxt::new(self, self.param_env, closure.def_id),
             liberated_sig,
             coroutine_types,
             closure.fn_decl,
@@ -174,9 +157,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     )
                 });
 
-                debug!(?sig, ?opt_kind);
+                debug!(?sig, ?expected_kind);
 
-                let closure_kind_ty = match opt_kind {
+                let closure_kind_ty = match expected_kind {
                     Some(kind) => Ty::from_closure_kind(tcx, kind),
 
                     // Create a type variable (for now) to represent the closure kind.
@@ -204,11 +187,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let Some(CoroutineTypes { resume_ty, yield_ty }) = coroutine_types else {
                     bug!("expected coroutine to have yield/resume types");
                 };
-                let interior = fcx.next_ty_var(TypeVariableOrigin {
+                let interior = self.next_ty_var(TypeVariableOrigin {
                     kind: TypeVariableOriginKind::MiscVariable,
                     span: body.value.span,
                 });
-                fcx.deferred_coroutine_interiors.borrow_mut().push((
+                self.deferred_coroutine_interiors.borrow_mut().push((
                     expr_def_id,
                     body.id(),
                     interior,
@@ -364,36 +347,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let tcx = self.tcx;
 
         let trait_def_id = projection.trait_def_id(tcx);
-
-        let is_fn = tcx.is_fn_trait(trait_def_id);
-
-        let coroutine_trait = tcx.lang_items().coroutine_trait();
-        let is_gen = coroutine_trait == Some(trait_def_id);
-
-        if !is_fn && !is_gen {
-            debug!("not fn or coroutine");
+        // For now, we only do signature deduction based off of the `Fn` traits.
+        if !tcx.is_fn_trait(trait_def_id) {
             return None;
         }
 
-        // Check that we deduce the signature from the `<_ as std::ops::Coroutine>::Return`
-        // associated item and not yield.
-        if is_gen && self.tcx.associated_item(projection.projection_def_id()).name != sym::Return {
-            debug!("not `Return` assoc item of `Coroutine`");
-            return None;
-        }
-
-        let input_tys = if is_fn {
-            let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1);
-            let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty);
-            debug!(?arg_param_ty);
+        let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1);
+        let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty);
+        debug!(?arg_param_ty);
 
-            match arg_param_ty.kind() {
-                &ty::Tuple(tys) => tys,
-                _ => return None,
-            }
-        } else {
-            // Coroutines with a `()` resume type may be defined with 0 or 1 explicit arguments,
-            // else they must have exactly 1 argument. For now though, just give up in this case.
+        let ty::Tuple(input_tys) = *arg_param_ty.kind() else {
             return None;
         };
 
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 372f11a5acc..ef621f29bfd 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -604,19 +604,15 @@ impl<'tcx> TyCtxt<'tcx> {
     /// wrapped in a binder.
     pub fn closure_env_ty(
         self,
-        closure_def_id: DefId,
-        closure_args: GenericArgsRef<'tcx>,
+        closure_ty: Ty<'tcx>,
+        closure_kind: ty::ClosureKind,
         env_region: ty::Region<'tcx>,
-    ) -> Option<Ty<'tcx>> {
-        let closure_ty = Ty::new_closure(self, closure_def_id, closure_args);
-        let closure_kind_ty = closure_args.as_closure().kind_ty();
-        let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
-        let env_ty = match closure_kind {
+    ) -> Ty<'tcx> {
+        match closure_kind {
             ty::ClosureKind::Fn => Ty::new_imm_ref(self, env_region, closure_ty),
             ty::ClosureKind::FnMut => Ty::new_mut_ref(self, env_region, closure_ty),
             ty::ClosureKind::FnOnce => closure_ty,
-        };
-        Some(env_ty)
+        }
     }
 
     /// Returns `true` if the node pointed to by `def_id` is a `static` item.
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index fa3dd2afa85..5d0bb3954cc 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -117,50 +117,32 @@ impl<'tcx> Cx<'tcx> {
         pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
     }
 
-    fn closure_env_param(&self, owner_def: LocalDefId, owner_id: HirId) -> Option<Param<'tcx>> {
-        match self.tcx.def_kind(owner_def) {
-            DefKind::Closure if self.tcx.is_coroutine(owner_def.to_def_id()) => {
-                let coroutine_ty = self.typeck_results.node_type(owner_id);
-                let coroutine_param = Param {
-                    ty: coroutine_ty,
-                    pat: None,
-                    ty_span: None,
-                    self_kind: None,
-                    hir_id: None,
-                };
-                Some(coroutine_param)
+    fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option<Param<'tcx>> {
+        if self.tcx.def_kind(owner_def) != DefKind::Closure {
+            return None;
+        }
+
+        let closure_ty = self.typeck_results.node_type(expr_id);
+        Some(match *closure_ty.kind() {
+            ty::Coroutine(..) => {
+                Param { ty: closure_ty, pat: None, ty_span: None, self_kind: None, hir_id: None }
             }
-            DefKind::Closure => {
-                let closure_ty = self.typeck_results.node_type(owner_id);
-
-                let ty::Closure(closure_def_id, closure_args) = *closure_ty.kind() else {
-                    bug!("closure expr does not have closure type: {:?}", closure_ty);
-                };
-
-                let bound_vars =
-                    self.tcx.mk_bound_variable_kinds(&[ty::BoundVariableKind::Region(ty::BrEnv)]);
-                let br = ty::BoundRegion {
-                    var: ty::BoundVar::from_usize(bound_vars.len() - 1),
-                    kind: ty::BrEnv,
-                };
-                let env_region = ty::Region::new_bound(self.tcx, ty::INNERMOST, br);
-                let closure_env_ty =
-                    self.tcx.closure_env_ty(closure_def_id, closure_args, env_region).unwrap();
-                let liberated_closure_env_ty = self.tcx.instantiate_bound_regions_with_erased(
-                    ty::Binder::bind_with_vars(closure_env_ty, bound_vars),
+            ty::Closure(_, closure_args) => {
+                let closure_env_ty = self.tcx.closure_env_ty(
+                    closure_ty,
+                    closure_args.as_closure().kind(),
+                    self.tcx.lifetimes.re_erased,
                 );
-                let env_param = Param {
-                    ty: liberated_closure_env_ty,
+                Param {
+                    ty: closure_env_ty,
                     pat: None,
                     ty_span: None,
                     self_kind: None,
                     hir_id: None,
-                };
-
-                Some(env_param)
+                }
             }
-            _ => None,
-        }
+            _ => bug!("unexpected closure type: {closure_ty}"),
+        })
     }
 
     fn explicit_params<'a>(
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index ed10a515508..0bc432fa6f0 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -27,11 +27,9 @@ use rustc_middle::ty::Ty;
 #[cfg(feature = "rustc")]
 use rustc_span::ErrorGuaranteed;
 
-use crate::constructor::{Constructor, ConstructorSet};
+use crate::constructor::{Constructor, ConstructorSet, IntRange};
 #[cfg(feature = "rustc")]
-use crate::lints::{
-    lint_nonexhaustive_missing_variants, lint_overlapping_range_endpoints, PatternColumn,
-};
+use crate::lints::{lint_nonexhaustive_missing_variants, PatternColumn};
 use crate::pat::DeconstructedPat;
 #[cfg(feature = "rustc")]
 use crate::rustc::RustcMatchCheckCtxt;
@@ -77,6 +75,17 @@ pub trait TypeCx: Sized + fmt::Debug {
 
     /// Raise a bug.
     fn bug(&self, fmt: fmt::Arguments<'_>) -> !;
+
+    /// Lint that the range `pat` overlapped with all the ranges in `overlaps_with`, where the range
+    /// they overlapped over is `overlaps_on`. We only detect singleton overlaps.
+    /// The default implementation does nothing.
+    fn lint_overlapping_range_endpoints(
+        &self,
+        _pat: &DeconstructedPat<'_, Self>,
+        _overlaps_on: IntRange,
+        _overlaps_with: &[&DeconstructedPat<'_, Self>],
+    ) {
+    }
 }
 
 /// Context that provides information global to a match.
@@ -111,16 +120,10 @@ pub fn analyze_match<'p, 'tcx>(
 
     let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity)?;
 
-    let pat_column = PatternColumn::new(arms);
-
-    // Lint ranges that overlap on their endpoints, which is likely a mistake.
-    if !report.overlapping_range_endpoints.is_empty() {
-        lint_overlapping_range_endpoints(cx, &report.overlapping_range_endpoints);
-    }
-
     // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
     // `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
     if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() {
+        let pat_column = PatternColumn::new(arms);
         lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty)?;
     }
 
diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs
index cfe4ca3ce93..4266e2a405e 100644
--- a/compiler/rustc_pattern_analysis/src/lints.rs
+++ b/compiler/rustc_pattern_analysis/src/lints.rs
@@ -1,14 +1,11 @@
-use rustc_session::lint;
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::ErrorGuaranteed;
 
-use crate::errors::{
-    self, NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered,
-};
+use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered};
 use crate::pat::PatOrWild;
 use crate::rustc::{
-    self, Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy,
-    RustcMatchCheckCtxt, SplitConstructorSet, WitnessPat,
+    Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, RustcMatchCheckCtxt,
+    SplitConstructorSet, WitnessPat,
 };
 
 /// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that
@@ -196,26 +193,3 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
     }
     Ok(())
 }
-
-pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
-    cx: MatchCtxt<'a, 'p, 'tcx>,
-    overlapping_range_endpoints: &[rustc::OverlappingRanges<'p, 'tcx>],
-) {
-    let rcx = cx.tycx;
-    for overlap in overlapping_range_endpoints {
-        let overlap_as_pat = rcx.hoist_pat_range(&overlap.overlaps_on, overlap.pat.ty());
-        let overlaps: Vec<_> = overlap
-            .overlaps_with
-            .iter()
-            .map(|pat| pat.data().unwrap().span)
-            .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span })
-            .collect();
-        let pat_span = overlap.pat.data().unwrap().span;
-        rcx.tcx.emit_spanned_lint(
-            lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
-            rcx.match_lint_level,
-            pat_span,
-            errors::OverlappingRangeEndpoints { overlap: overlaps, range: pat_span },
-        );
-    }
-}
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index e82d6666b1a..87e70d68c1b 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -1,3 +1,4 @@
+use smallvec::SmallVec;
 use std::fmt;
 use std::iter::once;
 
@@ -5,24 +6,21 @@ use rustc_arena::{DroplessArena, TypedArena};
 use rustc_data_structures::captures::Captures;
 use rustc_hir::def_id::DefId;
 use rustc_hir::HirId;
-use rustc_index::Idx;
-use rustc_index::IndexVec;
+use rustc_index::{Idx, IndexVec};
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::{self, Const};
 use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
 use rustc_middle::ty::layout::IntegerExt;
-use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, VariantDef};
-use rustc_span::ErrorGuaranteed;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef};
+use rustc_session::lint;
+use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT};
-use smallvec::SmallVec;
 
 use crate::constructor::{
     IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility,
 };
-use crate::TypeCx;
+use crate::{errors, TypeCx};
 
 use crate::constructor::Constructor::*;
 
@@ -34,8 +32,6 @@ pub type DeconstructedPat<'p, 'tcx> =
     crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>;
-pub type OverlappingRanges<'p, 'tcx> =
-    crate::usefulness::OverlappingRanges<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub(crate) type PlaceCtxt<'a, 'p, 'tcx> =
     crate::usefulness::PlaceCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub(crate) type SplitConstructorSet<'p, 'tcx> =
@@ -991,6 +987,27 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
     fn bug(&self, fmt: fmt::Arguments<'_>) -> ! {
         span_bug!(self.scrut_span, "{}", fmt)
     }
+
+    fn lint_overlapping_range_endpoints(
+        &self,
+        pat: &crate::pat::DeconstructedPat<'_, Self>,
+        overlaps_on: IntRange,
+        overlaps_with: &[&crate::pat::DeconstructedPat<'_, Self>],
+    ) {
+        let overlap_as_pat = self.hoist_pat_range(&overlaps_on, pat.ty());
+        let overlaps: Vec<_> = overlaps_with
+            .iter()
+            .map(|pat| pat.data().unwrap().span)
+            .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span })
+            .collect();
+        let pat_span = pat.data().unwrap().span;
+        self.tcx.emit_spanned_lint(
+            lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
+            self.match_lint_level,
+            pat_span,
+            errors::OverlappingRangeEndpoints { overlap: overlaps, range: pat_span },
+        );
+    }
 }
 
 /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index 6244cf0ff7d..c7894994213 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -1340,10 +1340,10 @@ impl<Cx: TypeCx> WitnessMatrix<Cx> {
 /// We can however get false negatives because exhaustiveness does not explore all cases. See the
 /// section on relevancy at the top of the file.
 fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
+    mcx: MatchCtxt<'_, Cx>,
     overlap_range: IntRange,
     matrix: &Matrix<'p, Cx>,
     specialized_matrix: &Matrix<'p, Cx>,
-    overlapping_range_endpoints: &mut Vec<OverlappingRanges<'p, Cx>>,
 ) {
     let overlap = overlap_range.lo;
     // Ranges that look like `lo..=overlap`.
@@ -1373,11 +1373,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
                     .map(|&(_, pat)| pat)
                     .collect();
                 if !overlaps_with.is_empty() {
-                    overlapping_range_endpoints.push(OverlappingRanges {
-                        pat,
-                        overlaps_on: overlap_range,
-                        overlaps_with,
-                    });
+                    mcx.tycx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with);
                 }
             }
             suffixes.push((child_row_id, pat))
@@ -1393,11 +1389,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
                     .map(|&(_, pat)| pat)
                     .collect();
                 if !overlaps_with.is_empty() {
-                    overlapping_range_endpoints.push(OverlappingRanges {
-                        pat,
-                        overlaps_on: overlap_range,
-                        overlaps_with,
-                    });
+                    mcx.tycx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with);
                 }
             }
             prefixes.push((child_row_id, pat))
@@ -1423,7 +1415,6 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
 fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
     mcx: MatchCtxt<'a, Cx>,
     matrix: &mut Matrix<'p, Cx>,
-    overlapping_range_endpoints: &mut Vec<OverlappingRanges<'p, Cx>>,
     is_top_level: bool,
 ) -> Result<WitnessMatrix<Cx>, Cx::Error> {
     debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count()));
@@ -1503,12 +1494,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
         let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty();
         let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant);
         let mut witnesses = ensure_sufficient_stack(|| {
-            compute_exhaustiveness_and_usefulness(
-                mcx,
-                &mut spec_matrix,
-                overlapping_range_endpoints,
-                false,
-            )
+            compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false)
         })?;
 
         // Transform witnesses for `spec_matrix` into witnesses for `matrix`.
@@ -1537,12 +1523,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
                 && spec_matrix.rows.len() >= 2
                 && spec_matrix.rows.iter().any(|row| !row.intersects.is_empty())
             {
-                collect_overlapping_range_endpoints(
-                    overlap_range,
-                    matrix,
-                    &spec_matrix,
-                    overlapping_range_endpoints,
-                );
+                collect_overlapping_range_endpoints(mcx, overlap_range, matrix, &spec_matrix);
             }
         }
     }
@@ -1569,15 +1550,6 @@ pub enum Usefulness<'p, Cx: TypeCx> {
     Redundant,
 }
 
-/// Indicates that the range `pat` overlapped with all the ranges in `overlaps_with`, where the
-/// range they overlapped over is `overlaps_on`. We only detect singleton overlaps.
-#[derive(Clone, Debug)]
-pub struct OverlappingRanges<'p, Cx: TypeCx> {
-    pub pat: &'p DeconstructedPat<'p, Cx>,
-    pub overlaps_on: IntRange,
-    pub overlaps_with: Vec<&'p DeconstructedPat<'p, Cx>>,
-}
-
 /// The output of checking a match for exhaustiveness and arm usefulness.
 pub struct UsefulnessReport<'p, Cx: TypeCx> {
     /// For each arm of the input, whether that arm is useful after the arms above it.
@@ -1585,7 +1557,6 @@ pub struct UsefulnessReport<'p, Cx: TypeCx> {
     /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of
     /// exhaustiveness.
     pub non_exhaustiveness_witnesses: Vec<WitnessPat<Cx>>,
-    pub overlapping_range_endpoints: Vec<OverlappingRanges<'p, Cx>>,
 }
 
 /// Computes whether a match is exhaustive and which of its arms are useful.
@@ -1596,14 +1567,9 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>(
     scrut_ty: Cx::Ty,
     scrut_validity: ValidityConstraint,
 ) -> Result<UsefulnessReport<'p, Cx>, Cx::Error> {
-    let mut overlapping_range_endpoints = Vec::new();
     let mut matrix = Matrix::new(arms, scrut_ty, scrut_validity);
-    let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness(
-        cx,
-        &mut matrix,
-        &mut overlapping_range_endpoints,
-        true,
-    )?;
+    let non_exhaustiveness_witnesses =
+        compute_exhaustiveness_and_usefulness(cx, &mut matrix, true)?;
 
     let non_exhaustiveness_witnesses: Vec<_> = non_exhaustiveness_witnesses.single_column();
     let arm_usefulness: Vec<_> = arms
@@ -1621,9 +1587,5 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>(
         })
         .collect();
 
-    Ok(UsefulnessReport {
-        arm_usefulness,
-        non_exhaustiveness_witnesses,
-        overlapping_range_endpoints,
-    })
+    Ok(UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses })
 }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index dd4e69efe37..abbc2066eac 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -2466,7 +2466,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
     debug!(?cache_projection, ?obligation_projection);
 
     match infcx.at(cause, param_env).eq(
-        DefineOpaqueTypes::No,
+        DefineOpaqueTypes::Yes,
         cache_projection,
         obligation_projection,
     ) {
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 6e8293dac31..333aec1d38d 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -83,7 +83,11 @@ fn fn_sig_for_fn_abi<'tcx>(
                 kind: ty::BoundRegionKind::BrEnv,
             };
             let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
-            let env_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap();
+            let env_ty = tcx.closure_env_ty(
+                Ty::new_closure(tcx, def_id, args),
+                args.as_closure().kind(),
+                env_region,
+            );
 
             let sig = sig.skip_binder();
             ty::Binder::bind_with_vars(
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 695e87aaabf..f5d765e690d 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -59,6 +59,8 @@ pub use dec2flt::ParseFloatError;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use error::ParseIntError;
 
+pub(crate) use nonzero::NonZero;
+
 #[stable(feature = "nonzero", since = "1.28.0")]
 pub use nonzero::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
 
@@ -482,7 +484,7 @@ impl u8 {
         Self = u8,
         ActualT = u8,
         SignedT = i8,
-        NonZeroT = NonZeroU8,
+        NonZeroT = NonZero<u8>,
         BITS = 8,
         MAX = 255,
         rot = 2,
@@ -1097,7 +1099,7 @@ impl u16 {
         Self = u16,
         ActualT = u16,
         SignedT = i16,
-        NonZeroT = NonZeroU16,
+        NonZeroT = NonZero<u16>,
         BITS = 16,
         MAX = 65535,
         rot = 4,
@@ -1146,7 +1148,7 @@ impl u32 {
         Self = u32,
         ActualT = u32,
         SignedT = i32,
-        NonZeroT = NonZeroU32,
+        NonZeroT = NonZero<u32>,
         BITS = 32,
         MAX = 4294967295,
         rot = 8,
@@ -1170,7 +1172,7 @@ impl u64 {
         Self = u64,
         ActualT = u64,
         SignedT = i64,
-        NonZeroT = NonZeroU64,
+        NonZeroT = NonZero<u64>,
         BITS = 64,
         MAX = 18446744073709551615,
         rot = 12,
@@ -1194,7 +1196,7 @@ impl u128 {
         Self = u128,
         ActualT = u128,
         SignedT = i128,
-        NonZeroT = NonZeroU128,
+        NonZeroT = NonZero<u128>,
         BITS = 128,
         MAX = 340282366920938463463374607431768211455,
         rot = 16,
@@ -1220,7 +1222,7 @@ impl usize {
         Self = usize,
         ActualT = u16,
         SignedT = isize,
-        NonZeroT = NonZeroUsize,
+        NonZeroT = NonZero<usize>,
         BITS = 16,
         MAX = 65535,
         rot = 4,
@@ -1245,7 +1247,7 @@ impl usize {
         Self = usize,
         ActualT = u32,
         SignedT = isize,
-        NonZeroT = NonZeroUsize,
+        NonZeroT = NonZero<usize>,
         BITS = 32,
         MAX = 4294967295,
         rot = 8,
@@ -1270,7 +1272,7 @@ impl usize {
         Self = usize,
         ActualT = u64,
         SignedT = isize,
-        NonZeroT = NonZeroUsize,
+        NonZeroT = NonZero<usize>,
         BITS = 64,
         MAX = 18446744073709551615,
         rot = 12,
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 2df38ab5848..715c3a0b8ac 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -8,6 +8,69 @@ use super::from_str_radix;
 use super::{IntErrorKind, ParseIntError};
 use crate::intrinsics;
 
+mod private {
+    #[unstable(
+        feature = "nonzero_internals",
+        reason = "implementation detail which may disappear or be replaced at any time",
+        issue = "none"
+    )]
+    #[const_trait]
+    pub trait Sealed {}
+}
+
+/// A marker trait for primitive types which can be zero.
+///
+/// This is an implementation detail for [`NonZero<T>`](NonZero) which may disappear or be replaced at any time.
+#[unstable(
+    feature = "nonzero_internals",
+    reason = "implementation detail which may disappear or be replaced at any time",
+    issue = "none"
+)]
+#[const_trait]
+pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {
+    type NonZero;
+}
+
+#[unstable(
+    feature = "nonzero_internals",
+    reason = "implementation detail which may disappear or be replaced at any time",
+    issue = "none"
+)]
+pub(crate) type NonZero<T> = <T as ZeroablePrimitive>::NonZero;
+
+macro_rules! impl_zeroable_primitive {
+    ($NonZero:ident ( $primitive:ty )) => {
+        #[unstable(
+            feature = "nonzero_internals",
+            reason = "implementation detail which may disappear or be replaced at any time",
+            issue = "none"
+        )]
+        impl const private::Sealed for $primitive {}
+
+        #[unstable(
+            feature = "nonzero_internals",
+            reason = "implementation detail which may disappear or be replaced at any time",
+            issue = "none"
+        )]
+        impl const ZeroablePrimitive for $primitive {
+            type NonZero = $NonZero;
+        }
+    };
+}
+
+impl_zeroable_primitive!(NonZeroU8(u8));
+impl_zeroable_primitive!(NonZeroU16(u16));
+impl_zeroable_primitive!(NonZeroU32(u32));
+impl_zeroable_primitive!(NonZeroU64(u64));
+impl_zeroable_primitive!(NonZeroU128(u128));
+impl_zeroable_primitive!(NonZeroUsize(usize));
+impl_zeroable_primitive!(NonZeroI8(i8));
+impl_zeroable_primitive!(NonZeroI16(i16));
+impl_zeroable_primitive!(NonZeroI32(i32));
+impl_zeroable_primitive!(NonZeroI64(i64));
+impl_zeroable_primitive!(NonZeroI128(i128));
+impl_zeroable_primitive!(NonZeroIsize(isize));
+
 macro_rules! impl_nonzero_fmt {
     ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
         $(
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 11a53aaf122..bbbbd61c4b1 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -3,7 +3,7 @@ macro_rules! uint_impl {
         Self = $SelfT:ty,
         ActualT = $ActualT:ident,
         SignedT = $SignedT:ident,
-        NonZeroT = $NonZeroT:ident,
+        NonZeroT = $NonZeroT:ty,
 
         // There are all for use *only* in doc comments.
         // As such, they're all passed as literals -- passing them as a string
@@ -842,6 +842,7 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline]
         pub const fn checked_ilog2(self) -> Option<u32> {
+            // FIXME: Simply use `NonZero::new` once it is actually generic.
             if let Some(x) = <$NonZeroT>::new(self) {
                 Some(x.ilog2())
             } else {
@@ -864,6 +865,7 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline]
         pub const fn checked_ilog10(self) -> Option<u32> {
+            // FIXME: Simply use `NonZero::new` once it is actually generic.
             if let Some(x) = <$NonZeroT>::new(self) {
                 Some(x.ilog10())
             } else {
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index b419a738fbe..e809273c9ed 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -710,7 +710,6 @@ impl<T> Bound<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(bound_map)]
     /// use std::ops::Bound::*;
     ///
     /// let bound_string = Included("Hello, World!");
@@ -719,7 +718,6 @@ impl<T> Bound<T> {
     /// ```
     ///
     /// ```
-    /// #![feature(bound_map)]
     /// use std::ops::Bound;
     /// use Bound::*;
     ///
@@ -728,7 +726,7 @@ impl<T> Bound<T> {
     /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded);
     /// ```
     #[inline]
-    #[unstable(feature = "bound_map", issue = "86026")]
+    #[stable(feature = "bound_map", since = "CURRENT_RUSTC_VERSION")]
     pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Bound<U> {
         match self {
             Unbounded => Unbounded,
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 3d58afd26ea..4a64faf9b3f 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -12,7 +12,7 @@ use crate::iter::{
 };
 use crate::marker::PhantomData;
 use crate::mem::{self, SizedTypeProperties};
-use crate::num::NonZeroUsize;
+use crate::num::{NonZero, NonZeroUsize};
 use crate::ptr::{self, invalid, invalid_mut, NonNull};
 
 use super::{from_raw_parts, from_raw_parts_mut};
@@ -1305,12 +1305,12 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] }
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct Windows<'a, T: 'a> {
     v: &'a [T],
-    size: NonZeroUsize,
+    size: NonZero<usize>,
 }
 
 impl<'a, T: 'a> Windows<'a, T> {
     #[inline]
-    pub(super) fn new(slice: &'a [T], size: NonZeroUsize) -> Self {
+    pub(super) fn new(slice: &'a [T], size: NonZero<usize>) -> Self {
         Self { v: slice, size }
     }
 }
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject f6bd083c4ccfc4ce6699b8b4154e3c45c5a27a8
+Subproject 6bc2415218d4dd0cb01433d8320f5ccf79c343a
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 3565c7978cfc9662f5963b135690ff9cbbfa031
+Subproject 8c77e8be9da1a9c70545556218d563c8d061f1f
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject c0be6299e52e4164c30ba6f41bd0ad0aaee6497
+Subproject ddf5cb0e6ee54ba2dd84c8ca3e1314120014e20
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject d13e85152a977cd0bcaf583cf5f49e86225697d
+Subproject 4af29d1a7f64f88a36539662c6a84fe1fbe6cde
diff --git a/src/tools/miropt-test-tools/src/lib.rs b/src/tools/miropt-test-tools/src/lib.rs
index cae96f59319..7d60033c3e8 100644
--- a/src/tools/miropt-test-tools/src/lib.rs
+++ b/src/tools/miropt-test-tools/src/lib.rs
@@ -98,11 +98,12 @@ pub fn files_for_miropt_test(
                 from_file = format!("{}.{}.mir", test_name, first_pass);
                 to_file = Some(second_file);
             } else {
-                let ext_re = regex::Regex::new(r#"(\.(mir|dot|html))$"#).unwrap();
-                let cap = ext_re
-                    .captures_iter(test_name)
-                    .next()
-                    .expect("test_name has an invalid extension");
+                // Allow-list for file extensions that can be produced by MIR dumps.
+                // Other extensions can be added here, as needed by new dump flags.
+                let ext_re = regex::Regex::new(r#"(\.(mir|dot))$"#).unwrap();
+                let cap = ext_re.captures_iter(test_name).next().unwrap_or_else(|| {
+                    panic!("in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}")
+                });
                 let extension = cap.get(1).unwrap().as_str();
 
                 expected_file =
diff --git a/tests/ui/type-alias-impl-trait/nested_inference_failure.rs b/tests/ui/type-alias-impl-trait/nested_inference_failure.rs
new file mode 100644
index 00000000000..d2091ca96ea
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/nested_inference_failure.rs
@@ -0,0 +1,28 @@
+// check-pass
+// revisions: new old
+//[new] compile-flags: -Znext-solver
+
+//! This test checks that we can successfully infer
+//! the hidden type of `FooImpl` to be `Foo<i32, {closure}>`
+//! and `ImplT` to be `i32`. This test used to fail, because
+//! we were unable to make the connection that the closure
+//! argument is the same as the first argument of `Foo`.
+
+#![feature(type_alias_impl_trait)]
+
+use std::fmt::Debug;
+use std::marker::PhantomData;
+
+struct Foo<T: Debug, F: FnOnce(T)> {
+    f: F,
+    _phantom: PhantomData<T>,
+}
+
+type ImplT = impl Debug;
+type FooImpl = Foo<ImplT, impl FnOnce(ImplT)>;
+
+fn bar() -> FooImpl {
+    Foo::<i32, _> { f: |_| (), _phantom: PhantomData }
+}
+
+fn main() {}