Skip to content

Commit 8d0058e

Browse files
committed
Auto merge of #120313 - Nadrieril:graceful-error, r=<try>
pattern_analysis: Gracefully abort on type incompatibility This leaves the option for a consumer of the crate to return `Err` instead of panicking on type error. rust-analyzer could use that (e.g. rust-lang/rust-analyzer#15808). Since the only use of `TypeCx::bug` is in `Constructor::is_covered_by`, it is tempting to return `false` instead of `Err()`, but that would cause "non-exhaustive match" false positives. r? `@compiler-errors`
2 parents cd6d8f2 + 8ea37ae commit 8d0058e

File tree

5 files changed

+24
-17
lines changed

5 files changed

+24
-17
lines changed

Diff for: compiler/rustc_pattern_analysis/src/constructor.rs

+17-10
Original file line numberDiff line numberDiff line change
@@ -727,12 +727,17 @@ impl<Cx: TypeCx> Constructor<Cx> {
727727
/// this checks for inclusion.
728728
// We inline because this has a single call site in `Matrix::specialize_constructor`.
729729
#[inline]
730-
pub(crate) fn is_covered_by(&self, pcx: &PlaceCtxt<'_, Cx>, other: &Self) -> bool {
731-
match (self, other) {
732-
(Wildcard, _) => pcx
733-
.mcx
734-
.tycx
735-
.bug(format_args!("Constructor splitting should not have returned `Wildcard`")),
730+
pub(crate) fn is_covered_by(
731+
&self,
732+
pcx: &PlaceCtxt<'_, Cx>,
733+
other: &Self,
734+
) -> Result<bool, Cx::Error> {
735+
Ok(match (self, other) {
736+
(Wildcard, _) => {
737+
return Err(pcx.mcx.tycx.bug(format_args!(
738+
"Constructor splitting should not have returned `Wildcard`"
739+
)));
740+
}
736741
// Wildcards cover anything
737742
(_, Wildcard) => true,
738743
// Only a wildcard pattern can match these special constructors.
@@ -773,10 +778,12 @@ impl<Cx: TypeCx> Constructor<Cx> {
773778
(Opaque(self_id), Opaque(other_id)) => self_id == other_id,
774779
(Opaque(..), _) | (_, Opaque(..)) => false,
775780

776-
_ => pcx.mcx.tycx.bug(format_args!(
777-
"trying to compare incompatible constructors {self:?} and {other:?}"
778-
)),
779-
}
781+
_ => {
782+
return Err(pcx.mcx.tycx.bug(format_args!(
783+
"trying to compare incompatible constructors {self:?} and {other:?}"
784+
)));
785+
}
786+
})
780787
}
781788
}
782789

Diff for: compiler/rustc_pattern_analysis/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ pub trait TypeCx: Sized + fmt::Debug {
112112
fn debug_pat(f: &mut fmt::Formatter<'_>, pat: &DeconstructedPat<'_, Self>) -> fmt::Result;
113113

114114
/// Raise a bug.
115-
fn bug(&self, fmt: fmt::Arguments<'_>) -> !;
115+
fn bug(&self, fmt: fmt::Arguments<'_>) -> Self::Error;
116116

117117
/// Lint that the range `pat` overlapped with all the ranges in `overlaps_with`, where the range
118118
/// they overlapped over is `overlaps_on`. We only detect singleton overlaps.

Diff for: compiler/rustc_pattern_analysis/src/lints.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
8080
let mut specialized_columns: Vec<_> =
8181
(0..arity).map(|_| Self { patterns: Vec::new() }).collect();
8282
let relevant_patterns =
83-
self.patterns.iter().filter(|pat| ctor.is_covered_by(pcx, pat.ctor()));
83+
self.patterns.iter().filter(|pat| ctor.is_covered_by(pcx, pat.ctor()).unwrap_or(false));
8484
for pat in relevant_patterns {
8585
let specialized = pat.specialize(ctor, arity);
8686
for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) {

Diff for: compiler/rustc_pattern_analysis/src/rustc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,7 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
984984
) -> fmt::Result {
985985
Self::debug_pat(f, pat)
986986
}
987-
fn bug(&self, fmt: fmt::Arguments<'_>) -> ! {
987+
fn bug(&self, fmt: fmt::Arguments<'_>) -> Self::Error {
988988
span_bug!(self.scrut_span, "{}", fmt)
989989
}
990990

Diff for: compiler/rustc_pattern_analysis/src/usefulness.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1055,7 +1055,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10551055
pcx: &PlaceCtxt<'_, Cx>,
10561056
ctor: &Constructor<Cx>,
10571057
ctor_is_relevant: bool,
1058-
) -> Matrix<'p, Cx> {
1058+
) -> Result<Matrix<'p, Cx>, Cx::Error> {
10591059
let ctor_sub_tys = pcx.ctor_sub_tys(ctor);
10601060
let arity = ctor_sub_tys.len();
10611061
let specialized_place_ty =
@@ -1072,12 +1072,12 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10721072
wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant,
10731073
};
10741074
for (i, row) in self.rows().enumerate() {
1075-
if ctor.is_covered_by(pcx, row.head().ctor()) {
1075+
if ctor.is_covered_by(pcx, row.head().ctor())? {
10761076
let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i);
10771077
matrix.expand_and_push(new_row);
10781078
}
10791079
}
1080-
matrix
1080+
Ok(matrix)
10811081
}
10821082
}
10831083

@@ -1480,7 +1480,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
14801480
// strictly fewer rows. In that case we can sometimes skip it. See the top of the file for
14811481
// details.
14821482
let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty();
1483-
let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant);
1483+
let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant)?;
14841484
let mut witnesses = ensure_sufficient_stack(|| {
14851485
compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false)
14861486
})?;

0 commit comments

Comments
 (0)