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.
This commit is contained in:
parent
11f32b73e0
commit
400dc46a05
@ -826,10 +826,12 @@ pub(crate) fn arity(&self, cx: &Cx, ty: &Cx::Ty) -> usize {
|
|||||||
/// this checks for inclusion.
|
/// this checks for inclusion.
|
||||||
// We inline because this has a single call site in `Matrix::specialize_constructor`.
|
// We inline because this has a single call site in `Matrix::specialize_constructor`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> bool {
|
pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> Result<bool, Cx::Error> {
|
||||||
match (self, other) {
|
Ok(match (self, other) {
|
||||||
(Wildcard, _) => {
|
(Wildcard, _) => {
|
||||||
cx.bug(format_args!("Constructor splitting should not have returned `Wildcard`"))
|
return Err(cx.bug(format_args!(
|
||||||
|
"Constructor splitting should not have returned `Wildcard`"
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
// Wildcards cover anything
|
// Wildcards cover anything
|
||||||
(_, Wildcard) => true,
|
(_, Wildcard) => true,
|
||||||
@ -871,10 +873,12 @@ pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> bool {
|
|||||||
(Opaque(self_id), Opaque(other_id)) => self_id == other_id,
|
(Opaque(self_id), Opaque(other_id)) => self_id == other_id,
|
||||||
(Opaque(..), _) | (_, Opaque(..)) => false,
|
(Opaque(..), _) | (_, Opaque(..)) => false,
|
||||||
|
|
||||||
_ => cx.bug(format_args!(
|
_ => {
|
||||||
|
return Err(cx.bug(format_args!(
|
||||||
"trying to compare incompatible constructors {self:?} and {other:?}"
|
"trying to compare incompatible constructors {self:?} and {other:?}"
|
||||||
)),
|
)));
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ fn write_variant_name(
|
|||||||
) -> fmt::Result;
|
) -> fmt::Result;
|
||||||
|
|
||||||
/// Raise a bug.
|
/// Raise a bug.
|
||||||
fn bug(&self, fmt: fmt::Arguments<'_>) -> !;
|
fn bug(&self, fmt: fmt::Arguments<'_>) -> Self::Error;
|
||||||
|
|
||||||
/// Lint that the range `pat` overlapped with all the ranges in `overlaps_with`, where the range
|
/// Lint that the range `pat` overlapped with all the ranges in `overlaps_with`, where the range
|
||||||
/// they overlapped over is `overlaps_on`. We only detect singleton overlaps.
|
/// they overlapped over is `overlaps_on`. We only detect singleton overlaps.
|
||||||
|
@ -78,7 +78,7 @@ pub fn specialize(
|
|||||||
let mut specialized_columns: Vec<_> =
|
let mut specialized_columns: Vec<_> =
|
||||||
(0..arity).map(|_| Self { patterns: Vec::new() }).collect();
|
(0..arity).map(|_| Self { patterns: Vec::new() }).collect();
|
||||||
let relevant_patterns =
|
let relevant_patterns =
|
||||||
self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor()));
|
self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor()).unwrap_or(false));
|
||||||
for pat in relevant_patterns {
|
for pat in relevant_patterns {
|
||||||
let specialized = pat.specialize(ctor, arity);
|
let specialized = pat.specialize(ctor, arity);
|
||||||
for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) {
|
for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) {
|
||||||
|
@ -900,7 +900,7 @@ fn write_variant_name(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bug(&self, fmt: fmt::Arguments<'_>) -> ! {
|
fn bug(&self, fmt: fmt::Arguments<'_>) -> Self::Error {
|
||||||
span_bug!(self.scrut_span, "{}", fmt)
|
span_bug!(self.scrut_span, "{}", fmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1082,7 +1082,7 @@ fn specialize_constructor(
|
|||||||
pcx: &PlaceCtxt<'_, Cx>,
|
pcx: &PlaceCtxt<'_, Cx>,
|
||||||
ctor: &Constructor<Cx>,
|
ctor: &Constructor<Cx>,
|
||||||
ctor_is_relevant: bool,
|
ctor_is_relevant: bool,
|
||||||
) -> Matrix<'p, Cx> {
|
) -> Result<Matrix<'p, Cx>, Cx::Error> {
|
||||||
let ctor_sub_tys = pcx.ctor_sub_tys(ctor);
|
let ctor_sub_tys = pcx.ctor_sub_tys(ctor);
|
||||||
let arity = ctor_sub_tys.len();
|
let arity = ctor_sub_tys.len();
|
||||||
let specialized_place_ty = ctor_sub_tys.chain(self.place_ty[1..].iter().cloned()).collect();
|
let specialized_place_ty = ctor_sub_tys.chain(self.place_ty[1..].iter().cloned()).collect();
|
||||||
@ -1098,12 +1098,12 @@ fn specialize_constructor(
|
|||||||
wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant,
|
wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant,
|
||||||
};
|
};
|
||||||
for (i, row) in self.rows().enumerate() {
|
for (i, row) in self.rows().enumerate() {
|
||||||
if ctor.is_covered_by(pcx.cx, row.head().ctor()) {
|
if ctor.is_covered_by(pcx.cx, row.head().ctor())? {
|
||||||
let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i);
|
let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i);
|
||||||
matrix.expand_and_push(new_row);
|
matrix.expand_and_push(new_row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
matrix
|
Ok(matrix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1533,7 +1533,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
|
|||||||
// strictly fewer rows. In that case we can sometimes skip it. See the top of the file for
|
// strictly fewer rows. In that case we can sometimes skip it. See the top of the file for
|
||||||
// details.
|
// details.
|
||||||
let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty();
|
let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty();
|
||||||
let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant);
|
let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant)?;
|
||||||
let mut witnesses = ensure_sufficient_stack(|| {
|
let mut witnesses = ensure_sufficient_stack(|| {
|
||||||
compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false)
|
compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false)
|
||||||
})?;
|
})?;
|
||||||
|
Loading…
Reference in New Issue
Block a user