diff options
| author | Nadrieril <nadrieril+git@gmail.com> | 2023-12-15 16:53:29 +0100 |
|---|---|---|
| committer | Nadrieril <nadrieril+git@gmail.com> | 2023-12-15 16:58:38 +0100 |
| commit | 4bcf66f875d77d0d5897c5b0b9d6bbd985d03a31 (patch) | |
| tree | 34cb871f1251205e9f51505a76de13f02859d9b3 /compiler/rustc_pattern_analysis | |
| parent | 60ea14bfaab32d2d1d5f956acfd08d72a2a79e1c (diff) | |
| download | rust-4bcf66f875d77d0d5897c5b0b9d6bbd985d03a31.tar.gz rust-4bcf66f875d77d0d5897c5b0b9d6bbd985d03a31.zip | |
Introduce `MatchCtxt`
Diffstat (limited to 'compiler/rustc_pattern_analysis')
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/constructor.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/lib.rs | 46 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/lints.rs | 56 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/pat.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/rustc.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/usefulness.rs | 52 |
6 files changed, 93 insertions, 77 deletions
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index ec1ddd56b1c..99044e00aeb 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -718,7 +718,7 @@ impl<Cx: MatchCx> Constructor<Cx> { /// The number of fields for this constructor. This must be kept in sync with /// `Fields::wildcards`. pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, '_, Cx>) -> usize { - pcx.cx.ctor_arity(self, pcx.ty) + pcx.ctor_arity(self) } /// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`. @@ -729,7 +729,8 @@ impl<Cx: MatchCx> Constructor<Cx> { pub(crate) fn is_covered_by<'p>(&self, pcx: &PlaceCtxt<'_, 'p, Cx>, other: &Self) -> bool { match (self, other) { (Wildcard, _) => pcx - .cx + .mcx + .tycx .bug(format_args!("Constructor splitting should not have returned `Wildcard`")), // Wildcards cover anything (_, Wildcard) => true, @@ -771,7 +772,7 @@ impl<Cx: MatchCx> Constructor<Cx> { (Opaque(self_id), Opaque(other_id)) => self_id == other_id, (Opaque(..), _) | (_, Opaque(..)) => false, - _ => pcx.cx.bug(format_args!( + _ => pcx.mcx.tycx.bug(format_args!( "trying to compare incompatible constructors {self:?} and {other:?}" )), } @@ -1007,7 +1008,7 @@ impl<Cx: MatchCx> ConstructorSet<Cx> { // We have now grouped all the constructors into 3 buckets: present, missing, missing_empty. // In the absence of the `exhaustive_patterns` feature however, we don't count nested empty // types as empty. Only non-nested `!` or `enum Foo {}` are considered empty. - if !pcx.cx.is_exhaustive_patterns_feature_on() + if !pcx.mcx.tycx.is_exhaustive_patterns_feature_on() && !(pcx.is_scrutinee && matches!(self, Self::NoConstructors)) { // Treat all missing constructors as nonempty. diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 12d2e0fc18b..44bc09d07fe 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -36,6 +36,19 @@ use crate::rustc::RustcMatchCheckCtxt; #[cfg(feature = "rustc")] use crate::usefulness::{compute_match_usefulness, ValidityConstraint}; +// It's not possible to only enable the `typed_arena` dependency when the `rustc` feature is off, so +// we use another feature instead. The crate won't compile if one of these isn't enabled. +#[cfg(feature = "rustc")] +pub(crate) use rustc_arena::TypedArena; +#[cfg(feature = "stable")] +pub(crate) use typed_arena::Arena as TypedArena; + +pub trait Captures<'a> {} +impl<'a, T: ?Sized> Captures<'a> for T {} + +/// Context that provides type information about constructors. +/// +/// Most of the crate is parameterized on a type that implements this trait. pub trait MatchCx: Sized + Clone + fmt::Debug { /// The type of a pattern. type Ty: Copy + Clone + fmt::Debug; // FIXME: remove Copy @@ -71,10 +84,20 @@ pub trait MatchCx: Sized + Clone + fmt::Debug { fn bug(&self, fmt: fmt::Arguments<'_>) -> !; } +/// Context that provides information global to a match. +#[derive(Clone)] +pub struct MatchCtxt<'a, 'p, Cx: MatchCx> { + /// The context for type information. + pub tycx: &'a Cx, + /// An arena to store the wildcards we produce during analysis. + pub wildcard_arena: &'a TypedArena<DeconstructedPat<'p, Cx>>, +} + +impl<'a, 'p, Cx: MatchCx> Copy for MatchCtxt<'a, 'p, Cx> {} + /// The arm of a match expression. #[derive(Clone, Debug)] pub struct MatchArm<'p, Cx: MatchCx> { - /// The pattern must have been lowered through `check_match::MatchVisitor::lower_pattern`. pub pat: &'p DeconstructedPat<'p, Cx>, pub has_guard: bool, pub arm_data: Cx::ArmData, @@ -82,31 +105,30 @@ pub struct MatchArm<'p, Cx: MatchCx> { impl<'p, Cx: MatchCx> Copy for MatchArm<'p, Cx> {} -pub trait Captures<'a> {} -impl<'a, T: ?Sized> Captures<'a> for T {} - /// The entrypoint for this crate. Computes whether a match is exhaustive and which of its arms are /// useful, and runs some lints. #[cfg(feature = "rustc")] pub fn analyze_match<'p, 'tcx>( - cx: &RustcMatchCheckCtxt<'p, 'tcx>, + tycx: &RustcMatchCheckCtxt<'p, 'tcx>, arms: &[rustc::MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>, ) -> rustc::UsefulnessReport<'p, 'tcx> { // Arena to store the extra wildcards we construct during analysis. - let wildcard_arena = cx.pattern_arena; - let pat_column = PatternColumn::new(arms); + let wildcard_arena = tycx.pattern_arena; + let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee); + let cx = MatchCtxt { tycx, wildcard_arena }; + + let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity); - let scrut_validity = ValidityConstraint::from_bool(cx.known_valid_scrutinee); - let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity, wildcard_arena); + let pat_column = PatternColumn::new(arms); // Lint on ranges that overlap on their endpoints, which is likely a mistake. - lint_overlapping_range_endpoints(cx, &pat_column, wildcard_arena); + lint_overlapping_range_endpoints(cx, &pat_column); // 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 cx.refutable && report.non_exhaustiveness_witnesses.is_empty() { - lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty, wildcard_arena) + if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() { + lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty) } report diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 2d4b06669b5..f1287b1b4d2 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -1,4 +1,3 @@ -use rustc_arena::TypedArena; use smallvec::SmallVec; use rustc_data_structures::captures::Captures; @@ -13,8 +12,8 @@ use crate::errors::{ OverlappingRangeEndpoints, Uncovered, }; use crate::rustc::{ - Constructor, DeconstructedPat, MatchArm, PlaceCtxt, RustcMatchCheckCtxt, SplitConstructorSet, - WitnessPat, + Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RustcMatchCheckCtxt, + SplitConstructorSet, WitnessPat, }; use crate::MatchCx; @@ -70,7 +69,7 @@ impl<'a, 'p, 'tcx> PatternColumn<'a, 'p, 'tcx> { /// Do constructor splitting on the constructors of the column. fn analyze_ctors(&self, pcx: &PlaceCtxt<'_, 'p, 'tcx>) -> SplitConstructorSet<'p, 'tcx> { let column_ctors = self.patterns.iter().map(|p| p.ctor()); - pcx.cx.ctors_for_ty(pcx.ty).split(pcx, column_ctors) + pcx.ctors_for_ty().split(pcx, column_ctors) } fn iter<'b>(&'b self) -> impl Iterator<Item = &'a DeconstructedPat<'p, 'tcx>> + Captures<'b> { @@ -121,16 +120,15 @@ impl<'a, 'p, 'tcx> PatternColumn<'a, 'p, 'tcx> { /// Traverse the patterns to collect any variants of a non_exhaustive enum that fail to be mentioned /// in a given column. -#[instrument(level = "debug", skip(cx, wildcard_arena), ret)] +#[instrument(level = "debug", skip(cx), ret)] fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( - cx: &RustcMatchCheckCtxt<'p, 'tcx>, + cx: MatchCtxt<'a, 'p, 'tcx>, column: &PatternColumn<'a, 'p, 'tcx>, - wildcard_arena: &TypedArena<DeconstructedPat<'p, 'tcx>>, ) -> Vec<WitnessPat<'p, 'tcx>> { let Some(ty) = column.head_ty() else { return Vec::new(); }; - let pcx = &PlaceCtxt::new_dummy(cx, ty, wildcard_arena); + let pcx = &PlaceCtxt::new_dummy(cx, ty); let set = column.analyze_ctors(pcx); if set.present.is_empty() { @@ -141,7 +139,7 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( } let mut witnesses = Vec::new(); - if cx.is_foreign_non_exhaustive_enum(ty) { + if cx.tycx.is_foreign_non_exhaustive_enum(ty) { witnesses.extend( set.missing .into_iter() @@ -157,7 +155,7 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( let wild_pat = WitnessPat::wild_from_ctor(pcx, ctor); for (i, col_i) in specialized_columns.iter().enumerate() { // Compute witnesses for each column. - let wits_for_col_i = collect_nonexhaustive_missing_variants(cx, col_i, wildcard_arena); + let wits_for_col_i = collect_nonexhaustive_missing_variants(cx, col_i); // For each witness, we build a new pattern in the shape of `ctor(_, _, wit, _, _)`, // adding enough wildcards to match `arity`. for wit in wits_for_col_i { @@ -171,29 +169,29 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( } pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>( - cx: &RustcMatchCheckCtxt<'p, 'tcx>, + cx: MatchCtxt<'a, 'p, 'tcx>, arms: &[MatchArm<'p, 'tcx>], pat_column: &PatternColumn<'a, 'p, 'tcx>, scrut_ty: Ty<'tcx>, - wildcard_arena: &TypedArena<DeconstructedPat<'p, 'tcx>>, ) { + let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx; if !matches!( - cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, cx.match_lint_level).0, + rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).0, rustc_session::lint::Level::Allow ) { - let witnesses = collect_nonexhaustive_missing_variants(cx, pat_column, wildcard_arena); + let witnesses = collect_nonexhaustive_missing_variants(cx, pat_column); if !witnesses.is_empty() { // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns` // is not exhaustive enough. // // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`. - cx.tcx.emit_spanned_lint( + rcx.tcx.emit_spanned_lint( NON_EXHAUSTIVE_OMITTED_PATTERNS, - cx.match_lint_level, - cx.scrut_span, + rcx.match_lint_level, + rcx.scrut_span, NonExhaustiveOmittedPattern { scrut_ty, - uncovered: Uncovered::new(cx.scrut_span, cx, witnesses), + uncovered: Uncovered::new(rcx.scrut_span, rcx, witnesses), }, ); } @@ -203,17 +201,17 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>( // usage of the lint. for arm in arms { let (lint_level, lint_level_source) = - cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.arm_data); + rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.arm_data); if !matches!(lint_level, rustc_session::lint::Level::Allow) { let decorator = NonExhaustiveOmittedPatternLintOnArm { lint_span: lint_level_source.span(), - suggest_lint_on_match: cx.whole_match_span.map(|span| span.shrink_to_lo()), + suggest_lint_on_match: rcx.whole_match_span.map(|span| span.shrink_to_lo()), lint_level: lint_level.as_str(), lint_name: "non_exhaustive_omitted_patterns", }; use rustc_errors::DecorateLint; - let mut err = cx.tcx.sess.struct_span_warn(*arm.pat.data(), ""); + let mut err = rcx.tcx.sess.struct_span_warn(*arm.pat.data(), ""); err.set_primary_message(decorator.msg()); decorator.decorate_lint(&mut err); err.emit(); @@ -223,30 +221,30 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>( } /// Traverse the patterns to warn the user about ranges that overlap on their endpoints. -#[instrument(level = "debug", skip(cx, wildcard_arena))] +#[instrument(level = "debug", skip(cx))] pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>( - cx: &RustcMatchCheckCtxt<'p, 'tcx>, + cx: MatchCtxt<'a, 'p, 'tcx>, column: &PatternColumn<'a, 'p, 'tcx>, - wildcard_arena: &TypedArena<DeconstructedPat<'p, 'tcx>>, ) { let Some(ty) = column.head_ty() else { return; }; - let pcx = &PlaceCtxt::new_dummy(cx, ty, wildcard_arena); + let pcx = &PlaceCtxt::new_dummy(cx, ty); + let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx; let set = column.analyze_ctors(pcx); if matches!(ty.kind(), ty::Char | ty::Int(_) | ty::Uint(_)) { let emit_lint = |overlap: &IntRange, this_span: Span, overlapped_spans: &[Span]| { - let overlap_as_pat = cx.hoist_pat_range(overlap, ty); + let overlap_as_pat = rcx.hoist_pat_range(overlap, ty); let overlaps: Vec<_> = overlapped_spans .iter() .copied() .map(|span| Overlap { range: overlap_as_pat.clone(), span }) .collect(); - cx.tcx.emit_spanned_lint( + rcx.tcx.emit_spanned_lint( lint::builtin::OVERLAPPING_RANGE_ENDPOINTS, - cx.match_lint_level, + rcx.match_lint_level, this_span, OverlappingRangeEndpoints { overlap: overlaps, range: this_span }, ); @@ -291,7 +289,7 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>( // Recurse into the fields. for ctor in set.present { for col in column.specialize(pcx, &ctor) { - lint_overlapping_range_endpoints(cx, &col, wildcard_arena); + lint_overlapping_range_endpoints(cx, &col); } } } diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 4ddd5eb630a..defe95d3393 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -81,10 +81,10 @@ impl<'p, Cx: MatchCx> DeconstructedPat<'p, Cx> { other_ctor: &Constructor<Cx>, ) -> SmallVec<[&'a DeconstructedPat<'p, Cx>; 2]> { let wildcard_sub_tys = || { - let tys = pcx.cx.ctor_sub_tys(other_ctor, pcx.ty); + let tys = pcx.ctor_sub_tys(other_ctor); tys.iter() .map(|ty| DeconstructedPat::wildcard(*ty, Cx::PatData::default())) - .map(|pat| pcx.wildcard_arena.alloc(pat) as &_) + .map(|pat| pcx.mcx.wildcard_arena.alloc(pat) as &_) .collect() }; match (&self.ctor, other_ctor) { @@ -179,7 +179,7 @@ impl<Cx: MatchCx> WitnessPat<Cx> { /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern /// `Some(_)`. pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, '_, Cx>, ctor: Constructor<Cx>) -> Self { - let field_tys = pcx.cx.ctor_sub_tys(&ctor, pcx.ty); + let field_tys = pcx.ctor_sub_tys(&ctor); let fields = field_tys.iter().map(|ty| Self::wildcard(*ty)).collect(); Self::new(ctor, fields, pcx.ty) } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index d9b8b3a39c0..e5d43ff09a1 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -31,6 +31,7 @@ pub type ConstructorSet<'p, 'tcx> = 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, 'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub(crate) type PlaceCtxt<'a, 'p, 'tcx> = crate::usefulness::PlaceCtxt<'a, 'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub(crate) type SplitConstructorSet<'p, 'tcx> = diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 9742507fef2..f9f6c7c637d 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -555,16 +555,9 @@ use smallvec::{smallvec, SmallVec}; use std::fmt; -// It's not possible to only enable the `typed_arena` dependency when the `rustc` feature is off, so -// we use another feature instead. The crate won't compile if one of these isn't enabled. -#[cfg(feature = "rustc")] -use rustc_arena::TypedArena; -#[cfg(feature = "stable")] -use typed_arena::Arena as TypedArena; - use crate::constructor::{Constructor, ConstructorSet}; use crate::pat::{DeconstructedPat, WitnessPat}; -use crate::{Captures, MatchArm, MatchCx}; +use crate::{Captures, MatchArm, MatchCtxt, MatchCx, TypedArena}; use self::ValidityConstraint::*; @@ -578,9 +571,7 @@ pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R { /// Context that provides information local to a place under investigation. #[derive(Clone)] pub(crate) struct PlaceCtxt<'a, 'p, Cx: MatchCx> { - pub(crate) cx: &'a Cx, - /// An arena to store the wildcards we produce during analysis. - pub(crate) wildcard_arena: &'a TypedArena<DeconstructedPat<'p, Cx>>, + pub(crate) mcx: MatchCtxt<'a, 'p, Cx>, /// Type of the place under investigation. pub(crate) ty: Cx::Ty, /// Whether the place is the original scrutinee place, as opposed to a subplace of it. @@ -590,12 +581,18 @@ pub(crate) struct PlaceCtxt<'a, 'p, Cx: MatchCx> { impl<'a, 'p, Cx: MatchCx> PlaceCtxt<'a, 'p, Cx> { /// A `PlaceCtxt` when code other than `is_useful` needs one. #[cfg_attr(not(feature = "rustc"), allow(dead_code))] - pub(crate) fn new_dummy( - cx: &'a Cx, - ty: Cx::Ty, - wildcard_arena: &'a TypedArena<DeconstructedPat<'p, Cx>>, - ) -> Self { - PlaceCtxt { cx, ty, is_scrutinee: false, wildcard_arena } + pub(crate) fn new_dummy(mcx: MatchCtxt<'a, 'p, Cx>, ty: Cx::Ty) -> Self { + PlaceCtxt { mcx, ty, is_scrutinee: false } + } + + pub(crate) fn ctor_arity(&self, ctor: &Constructor<Cx>) -> usize { + self.mcx.tycx.ctor_arity(ctor, self.ty) + } + pub(crate) fn ctor_sub_tys(&self, ctor: &Constructor<Cx>) -> &[Cx::Ty] { + self.mcx.tycx.ctor_sub_tys(ctor, self.ty) + } + pub(crate) fn ctors_for_ty(&self) -> ConstructorSet<Cx> { + self.mcx.tycx.ctors_for_ty(self.ty) } } @@ -1176,11 +1173,10 @@ impl<Cx: MatchCx> WitnessMatrix<Cx> { /// - unspecialization, where we lift the results from the previous step into results for this step /// (using `apply_constructor` and by updating `row.useful` for each parent row). /// This is all explained at the top of the file. -#[instrument(level = "debug", skip(cx, is_top_level, wildcard_arena), ret)] +#[instrument(level = "debug", skip(mcx, is_top_level), ret)] fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: MatchCx>( - cx: &'a Cx, + mcx: MatchCtxt<'a, 'p, Cx>, matrix: &mut Matrix<'a, 'p, Cx>, - wildcard_arena: &'a TypedArena<DeconstructedPat<'p, Cx>>, is_top_level: bool, ) -> WitnessMatrix<Cx> { debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count())); @@ -1202,7 +1198,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: MatchCx>( }; debug!("ty: {ty:?}"); - let pcx = &PlaceCtxt { cx, ty, is_scrutinee: is_top_level, wildcard_arena }; + let pcx = &PlaceCtxt { mcx, ty, is_scrutinee: is_top_level }; // Whether the place/column we are inspecting is known to contain valid data. let place_validity = matrix.place_validity[0]; @@ -1211,7 +1207,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: MatchCx>( // Analyze the constructors present in this column. let ctors = matrix.heads().map(|p| p.ctor()); - let ctors_for_ty = &cx.ctors_for_ty(ty); + let ctors_for_ty = pcx.ctors_for_ty(); let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); // For diagnostics. let split_set = ctors_for_ty.split(pcx, ctors); let all_missing = split_set.present.is_empty(); @@ -1245,7 +1241,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: MatchCx>( // Dig into rows that match `ctor`. let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor); let mut witnesses = ensure_sufficient_stack(|| { - compute_exhaustiveness_and_usefulness(cx, &mut spec_matrix, wildcard_arena, false) + compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false) }); let counts_for_exhaustiveness = match ctor { @@ -1307,17 +1303,15 @@ pub struct UsefulnessReport<'p, Cx: MatchCx> { } /// Computes whether a match is exhaustive and which of its arms are useful. -#[instrument(skip(cx, arms, wildcard_arena), level = "debug")] +#[instrument(skip(cx, arms), level = "debug")] pub fn compute_match_usefulness<'p, Cx: MatchCx>( - cx: &Cx, + cx: MatchCtxt<'_, 'p, Cx>, arms: &[MatchArm<'p, Cx>], scrut_ty: Cx::Ty, scrut_validity: ValidityConstraint, - wildcard_arena: &TypedArena<DeconstructedPat<'p, Cx>>, ) -> UsefulnessReport<'p, Cx> { - let mut matrix = Matrix::new(wildcard_arena, arms, scrut_ty, scrut_validity); - let non_exhaustiveness_witnesses = - compute_exhaustiveness_and_usefulness(cx, &mut matrix, wildcard_arena, true); + let mut matrix = Matrix::new(cx.wildcard_arena, arms, scrut_ty, scrut_validity); + 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 |
