Repurpose MatchCtxt for usefulness only

This commit is contained in:
Nadrieril 2024-01-24 20:57:11 +01:00
parent cb0e8c508c
commit 83e88c6dfc
2 changed files with 21 additions and 23 deletions

View File

@ -135,20 +135,6 @@ pub trait TypeCx: Sized + fmt::Debug {
} }
} }
/// Context that provides information global to a match.
pub struct MatchCtxt<'a, Cx: TypeCx> {
/// The context for type information.
pub tycx: &'a Cx,
}
impl<'a, Cx: TypeCx> Clone for MatchCtxt<'a, Cx> {
fn clone(&self) -> Self {
Self { tycx: self.tycx }
}
}
impl<'a, Cx: TypeCx> Copy for MatchCtxt<'a, Cx> {}
/// The arm of a match expression. /// The arm of a match expression.
#[derive(Debug)] #[derive(Debug)]
pub struct MatchArm<'p, Cx: TypeCx> { pub struct MatchArm<'p, Cx: TypeCx> {
@ -175,9 +161,7 @@ pub fn analyze_match<'p, 'tcx>(
) -> Result<rustc::UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> { ) -> Result<rustc::UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> {
let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); let scrut_ty = tycx.reveal_opaque_ty(scrut_ty);
let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee); let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee);
let cx = MatchCtxt { tycx }; let report = compute_match_usefulness(tycx, arms, scrut_ty, scrut_validity)?;
let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity)?;
// Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting // 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 let`s. Only run if the match is exhaustive otherwise the error is redundant.

View File

@ -719,7 +719,7 @@ use std::fmt;
use crate::constructor::{Constructor, ConstructorSet, IntRange}; use crate::constructor::{Constructor, ConstructorSet, IntRange};
use crate::pat::{DeconstructedPat, PatOrWild, WitnessPat}; use crate::pat::{DeconstructedPat, PatOrWild, WitnessPat};
use crate::{Captures, MatchArm, MatchCtxt, TypeCx}; use crate::{Captures, MatchArm, TypeCx};
use self::ValidityConstraint::*; use self::ValidityConstraint::*;
@ -730,9 +730,22 @@ pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
f() f()
} }
/// Context that provides information for usefulness checking.
pub struct UsefulnessCtxt<'a, Cx: TypeCx> {
/// The context for type information.
pub tycx: &'a Cx,
}
impl<'a, Cx: TypeCx> Copy for UsefulnessCtxt<'a, Cx> {}
impl<'a, Cx: TypeCx> Clone for UsefulnessCtxt<'a, Cx> {
fn clone(&self) -> Self {
Self { tycx: self.tycx }
}
}
/// Context that provides information local to a place under investigation. /// Context that provides information local to a place under investigation.
struct PlaceCtxt<'a, Cx: TypeCx> { struct PlaceCtxt<'a, Cx: TypeCx> {
mcx: MatchCtxt<'a, Cx>, mcx: UsefulnessCtxt<'a, Cx>,
/// Type of the place under investigation. /// Type of the place under investigation.
ty: &'a Cx::Ty, ty: &'a Cx::Ty,
} }
@ -1358,7 +1371,7 @@ impl<Cx: TypeCx> WitnessMatrix<Cx> {
/// We can however get false negatives because exhaustiveness does not explore all cases. See the /// We can however get false negatives because exhaustiveness does not explore all cases. See the
/// section on relevancy at the top of the file. /// section on relevancy at the top of the file.
fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
mcx: MatchCtxt<'_, Cx>, mcx: UsefulnessCtxt<'_, Cx>,
overlap_range: IntRange, overlap_range: IntRange,
matrix: &Matrix<'p, Cx>, matrix: &Matrix<'p, Cx>,
specialized_matrix: &Matrix<'p, Cx>, specialized_matrix: &Matrix<'p, Cx>,
@ -1431,7 +1444,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
/// This is all explained at the top of the file. /// This is all explained at the top of the file.
#[instrument(level = "debug", skip(mcx, is_top_level), ret)] #[instrument(level = "debug", skip(mcx, is_top_level), ret)]
fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
mcx: MatchCtxt<'a, Cx>, mcx: UsefulnessCtxt<'a, Cx>,
matrix: &mut Matrix<'p, Cx>, matrix: &mut Matrix<'p, Cx>,
is_top_level: bool, is_top_level: bool,
) -> Result<WitnessMatrix<Cx>, Cx::Error> { ) -> Result<WitnessMatrix<Cx>, Cx::Error> {
@ -1588,13 +1601,14 @@ pub struct UsefulnessReport<'p, Cx: TypeCx> {
} }
/// Computes whether a match is exhaustive and which of its arms are useful. /// Computes whether a match is exhaustive and which of its arms are useful.
#[instrument(skip(cx, arms), level = "debug")] #[instrument(skip(tycx, arms), level = "debug")]
pub fn compute_match_usefulness<'p, Cx: TypeCx>( pub fn compute_match_usefulness<'p, Cx: TypeCx>(
cx: MatchCtxt<'_, Cx>, tycx: &Cx,
arms: &[MatchArm<'p, Cx>], arms: &[MatchArm<'p, Cx>],
scrut_ty: Cx::Ty, scrut_ty: Cx::Ty,
scrut_validity: ValidityConstraint, scrut_validity: ValidityConstraint,
) -> Result<UsefulnessReport<'p, Cx>, Cx::Error> { ) -> Result<UsefulnessReport<'p, Cx>, Cx::Error> {
let cx = UsefulnessCtxt { tycx };
let mut matrix = Matrix::new(arms, scrut_ty, scrut_validity); let mut matrix = Matrix::new(arms, scrut_ty, scrut_validity);
let non_exhaustiveness_witnesses = let non_exhaustiveness_witnesses =
compute_exhaustiveness_and_usefulness(cx, &mut matrix, true)?; compute_exhaustiveness_and_usefulness(cx, &mut matrix, true)?;