Skip to content

Commit 7d53726

Browse files
committed
Gracefully abort on type incompatibility
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.
1 parent 5903142 commit 7d53726

File tree

5 files changed

+18
-14
lines changed

5 files changed

+18
-14
lines changed

compiler/rustc_pattern_analysis/src/constructor.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -826,10 +826,12 @@ impl<Cx: TypeCx> Constructor<Cx> {
826826
/// this checks for inclusion.
827827
// We inline because this has a single call site in `Matrix::specialize_constructor`.
828828
#[inline]
829-
pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> bool {
830-
match (self, other) {
829+
pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> Result<bool, Cx::Error> {
830+
Ok(match (self, other) {
831831
(Wildcard, _) => {
832-
cx.bug(format_args!("Constructor splitting should not have returned `Wildcard`"))
832+
return Err(cx.bug(format_args!(
833+
"Constructor splitting should not have returned `Wildcard`"
834+
)));
833835
}
834836
// Wildcards cover anything
835837
(_, Wildcard) => true,
@@ -871,10 +873,12 @@ impl<Cx: TypeCx> Constructor<Cx> {
871873
(Opaque(self_id), Opaque(other_id)) => self_id == other_id,
872874
(Opaque(..), _) | (_, Opaque(..)) => false,
873875

874-
_ => cx.bug(format_args!(
875-
"trying to compare incompatible constructors {self:?} and {other:?}"
876-
)),
877-
}
876+
_ => {
877+
return Err(cx.bug(format_args!(
878+
"trying to compare incompatible constructors {self:?} and {other:?}"
879+
)));
880+
}
881+
})
878882
}
879883
}
880884

compiler/rustc_pattern_analysis/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ pub trait TypeCx: Sized + fmt::Debug {
123123
) -> fmt::Result;
124124

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

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

compiler/rustc_pattern_analysis/src/pat_column.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
7878
let mut specialized_columns: Vec<_> =
7979
(0..arity).map(|_| Self { patterns: Vec::new() }).collect();
8080
let relevant_patterns =
81-
self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor()));
81+
self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor()).unwrap_or(false));
8282
for pat in relevant_patterns {
8383
let specialized = pat.specialize(ctor, arity);
8484
for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) {

compiler/rustc_pattern_analysis/src/rustc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
900900
Ok(())
901901
}
902902

903-
fn bug(&self, fmt: fmt::Arguments<'_>) -> ! {
903+
fn bug(&self, fmt: fmt::Arguments<'_>) -> Self::Error {
904904
span_bug!(self.scrut_span, "{}", fmt)
905905
}
906906

compiler/rustc_pattern_analysis/src/usefulness.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1082,7 +1082,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10821082
pcx: &PlaceCtxt<'_, Cx>,
10831083
ctor: &Constructor<Cx>,
10841084
ctor_is_relevant: bool,
1085-
) -> Matrix<'p, Cx> {
1085+
) -> Result<Matrix<'p, Cx>, Cx::Error> {
10861086
let ctor_sub_tys = pcx.ctor_sub_tys(ctor);
10871087
let arity = ctor_sub_tys.len();
10881088
let specialized_place_ty = ctor_sub_tys.chain(self.place_ty[1..].iter().cloned()).collect();
@@ -1098,12 +1098,12 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10981098
wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant,
10991099
};
11001100
for (i, row) in self.rows().enumerate() {
1101-
if ctor.is_covered_by(pcx.cx, row.head().ctor()) {
1101+
if ctor.is_covered_by(pcx.cx, row.head().ctor())? {
11021102
let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i);
11031103
matrix.expand_and_push(new_row);
11041104
}
11051105
}
1106-
matrix
1106+
Ok(matrix)
11071107
}
11081108
}
11091109

@@ -1533,7 +1533,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
15331533
// strictly fewer rows. In that case we can sometimes skip it. See the top of the file for
15341534
// details.
15351535
let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty();
1536-
let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant);
1536+
let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant)?;
15371537
let mut witnesses = ensure_sufficient_stack(|| {
15381538
compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false)
15391539
})?;

0 commit comments

Comments
 (0)