Skip to content

Commit b15141a

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 6351247 commit b15141a

File tree

5 files changed

+24
-17
lines changed

5 files changed

+24
-17
lines changed

compiler/rustc_pattern_analysis/src/constructor.rs

+17-10
Original file line numberDiff line numberDiff line change
@@ -733,12 +733,17 @@ impl<Cx: TypeCx> Constructor<Cx> {
733733
/// this checks for inclusion.
734734
// We inline because this has a single call site in `Matrix::specialize_constructor`.
735735
#[inline]
736-
pub(crate) fn is_covered_by(&self, pcx: &PlaceCtxt<'_, Cx>, other: &Self) -> bool {
737-
match (self, other) {
738-
(Wildcard, _) => pcx
739-
.mcx
740-
.tycx
741-
.bug(format_args!("Constructor splitting should not have returned `Wildcard`")),
736+
pub(crate) fn is_covered_by(
737+
&self,
738+
pcx: &PlaceCtxt<'_, Cx>,
739+
other: &Self,
740+
) -> Result<bool, Cx::Error> {
741+
Ok(match (self, other) {
742+
(Wildcard, _) => {
743+
return Err(pcx.mcx.tycx.bug(format_args!(
744+
"Constructor splitting should not have returned `Wildcard`"
745+
)));
746+
}
742747
// Wildcards cover anything
743748
(_, Wildcard) => true,
744749
// Only a wildcard pattern can match these special constructors.
@@ -779,10 +784,12 @@ impl<Cx: TypeCx> Constructor<Cx> {
779784
(Opaque(self_id), Opaque(other_id)) => self_id == other_id,
780785
(Opaque(..), _) | (_, Opaque(..)) => false,
781786

782-
_ => pcx.mcx.tycx.bug(format_args!(
783-
"trying to compare incompatible constructors {self:?} and {other:?}"
784-
)),
785-
}
787+
_ => {
788+
return Err(pcx.mcx.tycx.bug(format_args!(
789+
"trying to compare incompatible constructors {self:?} and {other:?}"
790+
)));
791+
}
792+
})
786793
}
787794
}
788795

compiler/rustc_pattern_analysis/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ pub trait TypeCx: Sized + fmt::Debug {
121121
) -> fmt::Result;
122122

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

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

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) {

compiler/rustc_pattern_analysis/src/rustc.rs

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

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

compiler/rustc_pattern_analysis/src/usefulness.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10591059
pcx: &PlaceCtxt<'_, Cx>,
10601060
ctor: &Constructor<Cx>,
10611061
ctor_is_relevant: bool,
1062-
) -> Matrix<'p, Cx> {
1062+
) -> Result<Matrix<'p, Cx>, Cx::Error> {
10631063
let ctor_sub_tys = pcx.ctor_sub_tys(ctor);
10641064
let arity = ctor_sub_tys.len();
10651065
let specialized_place_ty = ctor_sub_tys.chain(self.place_ty[1..].iter().cloned()).collect();
@@ -1075,12 +1075,12 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10751075
wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant,
10761076
};
10771077
for (i, row) in self.rows().enumerate() {
1078-
if ctor.is_covered_by(pcx, row.head().ctor()) {
1078+
if ctor.is_covered_by(pcx, row.head().ctor())? {
10791079
let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i);
10801080
matrix.expand_and_push(new_row);
10811081
}
10821082
}
1083-
matrix
1083+
Ok(matrix)
10841084
}
10851085
}
10861086

@@ -1490,7 +1490,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
14901490
// strictly fewer rows. In that case we can sometimes skip it. See the top of the file for
14911491
// details.
14921492
let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty();
1493-
let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant);
1493+
let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant)?;
14941494
let mut witnesses = ensure_sufficient_stack(|| {
14951495
compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false)
14961496
})?;

0 commit comments

Comments
 (0)