Rollup merge of #67280 - shalzz:patch-1, r=jonas-schievink
docs: std::convert::From: Fix typo
Fix a minor typo
diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs
index ebd3f01..9136136 100644
--- a/src/liballoc/collections/vec_deque.rs
+++ b/src/liballoc/collections/vec_deque.rs
@@ -144,11 +144,23 @@
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T> Drop for VecDeque<T> {
fn drop(&mut self) {
+ /// Runs the destructor for all items in the slice when it gets dropped (normally or
+ /// during unwinding).
+ struct Dropper<'a, T>(&'a mut [T]);
+
+ impl<'a, T> Drop for Dropper<'a, T> {
+ fn drop(&mut self) {
+ unsafe {
+ ptr::drop_in_place(self.0);
+ }
+ }
+ }
+
let (front, back) = self.as_mut_slices();
unsafe {
+ let _back_dropper = Dropper(back);
// use drop for [T]
ptr::drop_in_place(front);
- ptr::drop_in_place(back);
}
// RawVec handles deallocation
}
diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs
index ebcc832..1ab3694 100644
--- a/src/liballoc/tests/vec_deque.rs
+++ b/src/liballoc/tests/vec_deque.rs
@@ -2,6 +2,7 @@
use std::collections::{vec_deque::Drain, VecDeque};
use std::fmt::Debug;
use std::mem::size_of;
+use std::panic::catch_unwind;
use std::{isize, usize};
use crate::hash;
@@ -710,6 +711,39 @@
}
#[test]
+fn test_drop_panic() {
+ static mut DROPS: i32 = 0;
+
+ struct D(bool);
+
+ impl Drop for D {
+ fn drop(&mut self) {
+ unsafe {
+ DROPS += 1;
+ }
+
+ if self.0 {
+ panic!("panic in `drop`");
+ }
+ }
+ }
+
+ let mut q = VecDeque::new();
+ q.push_back(D(false));
+ q.push_back(D(false));
+ q.push_back(D(false));
+ q.push_back(D(false));
+ q.push_back(D(false));
+ q.push_front(D(false));
+ q.push_front(D(false));
+ q.push_front(D(true));
+
+ catch_unwind(move || drop(q)).ok();
+
+ assert_eq!(unsafe { DROPS }, 8);
+}
+
+#[test]
fn test_reserve_grow() {
// test growth path A
// [T o o H] -> [T o o H . . . . ]
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs
index bba4414..ec926aa 100644
--- a/src/libcore/mem/mod.rs
+++ b/src/libcore/mem/mod.rs
@@ -510,7 +510,9 @@
/// **This function is deprecated.** Use [`MaybeUninit<T>`] instead.
///
/// The reason for deprecation is that the function basically cannot be used
-/// correctly: [the Rust compiler assumes][inv] that values are properly initialized.
+/// correctly: it has the same effect as [`MaybeUninit::uninit().assume_init()`][uninit].
+/// As the [`assume_init` documentation][assume_init] explains,
+/// [the Rust compiler assumes][inv] that values are properly initialized.
/// As a consequence, calling e.g. `mem::uninitialized::<bool>()` causes immediate
/// undefined behavior for returning a `bool` that is not definitely either `true`
/// or `false`. Worse, truly uninitialized memory like what gets returned here
@@ -521,6 +523,8 @@
/// until they are, it is advisable to avoid them.)
///
/// [`MaybeUninit<T>`]: union.MaybeUninit.html
+/// [uninit]: union.MaybeUninit.html#method.uninit
+/// [assume_init]: union.MaybeUninit.html#method.assume_init
/// [inv]: union.MaybeUninit.html#initialization-invariant
#[inline]
#[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")]
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 37a9381..c372032 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -238,7 +238,7 @@
use rustc::hir::def_id::DefId;
use rustc::hir::{HirId, RangeEnd};
use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx};
-use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef};
use rustc::lint;
use rustc::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar};
@@ -354,7 +354,7 @@
}
impl<'tcx> Pat<'tcx> {
- fn is_wildcard(&self) -> bool {
+ pub(super) fn is_wildcard(&self) -> bool {
match *self.kind {
PatKind::Binding { subpattern: None, .. } | PatKind::Wild => true,
_ => false,
@@ -596,9 +596,21 @@
}
}
- fn is_local(&self, ty: Ty<'tcx>) -> bool {
+ // Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
+ pub fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
match ty.kind {
- ty::Adt(adt_def, ..) => adt_def.did.is_local(),
+ ty::Adt(def, ..) => {
+ def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did.is_local()
+ }
+ _ => false,
+ }
+ }
+
+ // Returns whether the given variant is from another crate and has its fields declared
+ // `#[non_exhaustive]`.
+ fn is_foreign_non_exhaustive_variant(&self, ty: Ty<'tcx>, variant: &VariantDef) -> bool {
+ match ty.kind {
+ ty::Adt(def, ..) => variant.is_field_list_non_exhaustive() && !def.did.is_local(),
_ => false,
}
}
@@ -758,6 +770,10 @@
// Returns the set of constructors covered by `self` but not by
// anything in `other_ctors`.
fn subtract_ctors(&self, other_ctors: &Vec<Constructor<'tcx>>) -> Vec<Constructor<'tcx>> {
+ if other_ctors.is_empty() {
+ return vec![self.clone()];
+ }
+
match self {
// Those constructors can only match themselves.
Single | Variant(_) | ConstantValue(..) | FloatRange(..) => {
@@ -858,8 +874,7 @@
vec![Pat::wildcard_from_ty(substs.type_at(0))]
} else {
let variant = &adt.variants[self.variant_index_for_adt(cx, adt)];
- let is_non_exhaustive =
- variant.is_field_list_non_exhaustive() && !cx.is_local(ty);
+ let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(ty, variant);
variant
.fields
.iter()
@@ -1205,6 +1220,8 @@
///
/// We make sure to omit constructors that are statically impossible. E.g., for
/// `Option<!>`, we do not include `Some(_)` in the returned list of constructors.
+/// Invariant: this returns an empty `Vec` if and only if the type is uninhabited (as determined by
+/// `cx.is_uninhabited()`).
fn all_constructors<'a, 'tcx>(
cx: &mut MatchCheckCtxt<'a, 'tcx>,
pcx: PatCtxt<'tcx>,
@@ -1235,47 +1252,45 @@
vec![Slice(Slice { array_len: None, kind })]
}
ty::Adt(def, substs) if def.is_enum() => {
- let ctors: Vec<_> = def
- .variants
- .iter()
- .filter(|v| {
- !cx.tcx.features().exhaustive_patterns
- || !v
- .uninhabited_from(cx.tcx, substs, def.adt_kind())
+ let ctors: Vec<_> = if cx.tcx.features().exhaustive_patterns {
+ // If `exhaustive_patterns` is enabled, we exclude variants known to be
+ // uninhabited.
+ def.variants
+ .iter()
+ .filter(|v| {
+ !v.uninhabited_from(cx.tcx, substs, def.adt_kind())
.contains(cx.tcx, cx.module)
- })
- .map(|v| Variant(v.def_id))
- .collect();
-
- // If our scrutinee is *privately* an empty enum, we must treat it as though it had an
- // "unknown" constructor (in that case, all other patterns obviously can't be variants)
- // to avoid exposing its emptyness. See the `match_privately_empty` test for details.
- // FIXME: currently the only way I know of something can be a privately-empty enum is
- // when the exhaustive_patterns feature flag is not present, so this is only needed for
- // that case.
- let is_privately_empty = ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
- // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
- // additionnal "unknown" constructor.
- let is_declared_nonexhaustive =
- def.is_variant_list_non_exhaustive() && !cx.is_local(pcx.ty);
-
- if is_privately_empty || is_declared_nonexhaustive {
- // There is no point in enumerating all possible variants, because the user can't
- // actually match against them themselves. So we return only the fictitious
- // constructor.
- // E.g., in an example like:
- // ```
- // let err: io::ErrorKind = ...;
- // match err {
- // io::ErrorKind::NotFound => {},
- // }
- // ```
- // we don't want to show every possible IO error, but instead have only `_` as the
- // witness.
- vec![NonExhaustive]
+ })
+ .map(|v| Variant(v.def_id))
+ .collect()
} else {
- ctors
- }
+ def.variants.iter().map(|v| Variant(v.def_id)).collect()
+ };
+
+ // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
+ // additional "unknown" constructor.
+ // There is no point in enumerating all possible variants, because the user can't
+ // actually match against them all themselves. So we always return only the fictitious
+ // constructor.
+ // E.g., in an example like:
+ // ```
+ // let err: io::ErrorKind = ...;
+ // match err {
+ // io::ErrorKind::NotFound => {},
+ // }
+ // ```
+ // we don't want to show every possible IO error, but instead have only `_` as the
+ // witness.
+ let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty);
+
+ // If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
+ // as though it had an "unknown" constructor to avoid exposing its emptyness. Note that
+ // an empty match will still be considered exhaustive because that case is handled
+ // separately in `check_match`.
+ let is_secretly_empty =
+ def.variants.is_empty() && !cx.tcx.features().exhaustive_patterns;
+
+ if is_secretly_empty || is_declared_nonexhaustive { vec![NonExhaustive] } else { ctors }
}
ty::Char => {
vec![
@@ -1605,6 +1620,7 @@
v: &PatStack<'p, 'tcx>,
witness_preference: WitnessPreference,
hir_id: HirId,
+ is_top_level: bool,
) -> Usefulness<'tcx, 'p> {
let &Matrix(ref rows) = matrix;
debug!("is_useful({:#?}, {:#?})", matrix, v);
@@ -1632,7 +1648,7 @@
let mut unreachable_pats = Vec::new();
let mut any_is_useful = false;
for v in vs {
- let res = is_useful(cx, &matrix, &v, witness_preference, hir_id);
+ let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, false);
match res {
Useful(pats) => {
any_is_useful = true;
@@ -1732,7 +1748,7 @@
} else {
let matrix = matrix.specialize_wildcard();
let v = v.to_tail();
- let usefulness = is_useful(cx, &matrix, &v, witness_preference, hir_id);
+ let usefulness = is_useful(cx, &matrix, &v, witness_preference, hir_id, false);
// In this case, there's at least one "free"
// constructor that is only matched against by
@@ -1761,7 +1777,10 @@
// `(<direction-1>, <direction-2>, true)` - we are
// satisfied with `(_, _, true)`. In this case,
// `used_ctors` is empty.
- if missing_ctors.all_ctors_are_missing() {
+ // The exception is: if we are at the top-level, for example in an empty match, we
+ // sometimes prefer reporting the list of constructors instead of just `_`.
+ let report_ctors_rather_than_wildcard = is_top_level && !IntRange::is_integral(pcx.ty);
+ if missing_ctors.all_ctors_are_missing() && !report_ctors_rather_than_wildcard {
// All constructors are unused. Add a wild pattern
// rather than each individual constructor.
usefulness.apply_wildcard(pcx.ty)
@@ -1793,7 +1812,7 @@
cx.pattern_arena.alloc_from_iter(ctor.wildcard_subpatterns(cx, lty));
let matrix = matrix.specialize_constructor(cx, &ctor, ctor_wild_subpatterns);
v.specialize_constructor(cx, &ctor, ctor_wild_subpatterns)
- .map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id))
+ .map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id, false))
.map(|u| u.apply_constructor(cx, &ctor, lty))
.unwrap_or(NotUseful)
}
@@ -2308,7 +2327,7 @@
PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
let ref variant = adt_def.variants[variant_index];
- let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !cx.is_local(pat.ty);
+ let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(pat.ty, variant);
Some(Variant(variant.def_id))
.filter(|variant_constructor| variant_constructor == constructor)
.map(|_| {
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 737af3e..8156cfe 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -148,8 +148,8 @@
self.tables,
);
patcx.include_lint_checks();
- let pattern: &_ =
- cx.pattern_arena.alloc(expand_pattern(cx, patcx.lower_pattern(&arm.pat)));
+ let pattern = patcx.lower_pattern(&arm.pat);
+ let pattern: &_ = cx.pattern_arena.alloc(expand_pattern(cx, pattern));
if !patcx.errors.is_empty() {
patcx.report_inlining_errors(arm.pat.span);
have_errors = true;
@@ -166,73 +166,12 @@
// Fourth, check for unreachable arms.
let matrix = check_arms(cx, &inlined_arms, source);
- // Then, if the match has no arms, check whether the scrutinee
- // is uninhabited.
- let pat_ty = self.tables.node_type(scrut.hir_id);
- let module = self.tcx.hir().get_module_parent(scrut.hir_id);
- let mut def_span = None;
- let mut missing_variants = vec![];
- if inlined_arms.is_empty() {
- let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns {
- self.tcx.is_ty_uninhabited_from(module, pat_ty)
- } else {
- match pat_ty.kind {
- ty::Never => true,
- ty::Adt(def, _) => {
- def_span = self.tcx.hir().span_if_local(def.did);
- if def.variants.len() < 4 && !def.variants.is_empty() {
- // keep around to point at the definition of non-covered variants
- missing_variants =
- def.variants.iter().map(|variant| variant.ident).collect();
- }
-
- let is_non_exhaustive_and_non_local =
- def.is_variant_list_non_exhaustive() && !def.did.is_local();
-
- !(is_non_exhaustive_and_non_local) && def.variants.is_empty()
- }
- _ => false,
- }
- };
- if !scrutinee_is_uninhabited {
- // We know the type is inhabited, so this must be wrong
- let mut err = create_e0004(
- self.tcx.sess,
- scrut.span,
- format!(
- "non-exhaustive patterns: {}",
- match missing_variants.len() {
- 0 => format!("type `{}` is non-empty", pat_ty),
- 1 => format!(
- "pattern `{}` of type `{}` is not handled",
- missing_variants[0].name, pat_ty,
- ),
- _ => format!(
- "multiple patterns of type `{}` are not handled",
- pat_ty
- ),
- }
- ),
- );
- err.help(
- "ensure that all possible cases are being handled, \
- possibly by adding wildcards or more match arms",
- );
- if let Some(sp) = def_span {
- err.span_label(sp, format!("`{}` defined here", pat_ty));
- }
- // point at the definition of non-covered enum variants
- for variant in &missing_variants {
- err.span_label(variant.span, "variant not covered");
- }
- err.emit();
- }
- // If the type *is* uninhabited, it's vacuously exhaustive
- return;
- }
-
+ // Fifth, check if the match is exhaustive.
let scrut_ty = self.tables.node_type(scrut.hir_id);
- check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id);
+ // Note: An empty match isn't the same as an empty matrix for diagnostics purposes,
+ // since an empty matrix can occur when there are arms, if those arms all have guards.
+ let is_empty_match = inlined_arms.is_empty();
+ check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id, is_empty_match);
})
}
@@ -390,7 +329,7 @@
for (arm_index, (pat, hir_pat, has_guard)) in arms.iter().enumerate() {
let v = PatStack::from_pattern(pat);
- match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id) {
+ match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id, true) {
NotUseful => {
match source {
hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => bug!(),
@@ -478,7 +417,8 @@
hir_id: HirId,
) -> Result<(), Vec<super::Pat<'tcx>>> {
let wild_pattern = cx.pattern_arena.alloc(super::Pat::wildcard_from_ty(ty));
- match is_useful(cx, matrix, &PatStack::from_pattern(wild_pattern), ConstructWitness, hir_id) {
+ let v = PatStack::from_pattern(wild_pattern);
+ match is_useful(cx, matrix, &v, ConstructWitness, hir_id, true) {
NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
UsefulWithWitness(pats) => Err(if pats.is_empty() {
bug!("Exhaustiveness check returned no witnesses")
@@ -495,25 +435,60 @@
sp: Span,
matrix: &Matrix<'p, 'tcx>,
hir_id: HirId,
+ is_empty_match: bool,
) {
+ // In the absence of the `exhaustive_patterns` feature, empty matches are not detected by
+ // `is_useful` to exhaustively match uninhabited types, so we manually check here.
+ if is_empty_match && !cx.tcx.features().exhaustive_patterns {
+ let scrutinee_is_visibly_uninhabited = match scrut_ty.kind {
+ ty::Never => true,
+ ty::Adt(def, _) => {
+ def.is_enum()
+ && def.variants.is_empty()
+ && !cx.is_foreign_non_exhaustive_enum(scrut_ty)
+ }
+ _ => false,
+ };
+ if scrutinee_is_visibly_uninhabited {
+ // If the type *is* uninhabited, an empty match is vacuously exhaustive.
+ return;
+ }
+ }
+
let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) {
Ok(_) => return,
Err(err) => err,
};
- let joined_patterns = joined_uncovered_patterns(&witnesses);
- let mut err = create_e0004(
- cx.tcx.sess,
- sp,
- format!("non-exhaustive patterns: {} not covered", joined_patterns),
- );
- err.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
+ let non_empty_enum = match scrut_ty.kind {
+ ty::Adt(def, _) => def.is_enum() && !def.variants.is_empty(),
+ _ => false,
+ };
+ // In the case of an empty match, replace the '`_` not covered' diagnostic with something more
+ // informative.
+ let mut err;
+ if is_empty_match && !non_empty_enum {
+ err = create_e0004(
+ cx.tcx.sess,
+ sp,
+ format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty),
+ );
+ } else {
+ let joined_patterns = joined_uncovered_patterns(&witnesses);
+ err = create_e0004(
+ cx.tcx.sess,
+ sp,
+ format!("non-exhaustive patterns: {} not covered", joined_patterns),
+ );
+ err.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
+ };
+
adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
err.help(
"ensure that all possible cases are being handled, \
possibly by adding wildcards or more match arms",
- )
- .emit();
+ );
+ err.emit();
}
fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String {
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index efa0d26..916ea3dc 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -140,7 +140,18 @@
let fn_sig = drop_instance.ty(*self.tcx).fn_sig(*self.tcx);
let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig);
// The drop function takes `*mut T` where `T` is the type being dropped, so get that.
- let ty = fn_sig.inputs()[0].builtin_deref(true).unwrap().ty;
+ let args = fn_sig.inputs();
+ if args.len() != 1 {
+ throw_ub_format!(
+ "drop fn should have 1 argument, but signature is {:?}", fn_sig
+ );
+ }
+ let ty = args[0].builtin_deref(true)
+ .ok_or_else(|| err_ub_format!(
+ "drop fn argument type {} is not a pointer type",
+ args[0]
+ ))?
+ .ty;
Ok((drop_instance, ty))
}
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index e358df2..1dbcfe5 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -22,28 +22,23 @@
macro_rules! throw_validation_failure {
($what:expr, $where:expr, $details:expr) => {{
- let where_ = path_format(&$where);
- let where_ = if where_.is_empty() {
- String::new()
- } else {
- format!(" at {}", where_)
- };
- throw_unsup!(ValidationFailure(format!(
- "encountered {}{}, but expected {}",
- $what, where_, $details,
- )))
+ let mut msg = format!("encountered {}", $what);
+ let where_ = &$where;
+ if !where_.is_empty() {
+ msg.push_str(" at ");
+ write_path(&mut msg, where_);
+ }
+ write!(&mut msg, ", but expected {}", $details).unwrap();
+ throw_unsup!(ValidationFailure(msg))
}};
($what:expr, $where:expr) => {{
- let where_ = path_format(&$where);
- let where_ = if where_.is_empty() {
- String::new()
- } else {
- format!(" at {}", where_)
- };
- throw_unsup!(ValidationFailure(format!(
- "encountered {}{}",
- $what, where_,
- )))
+ let mut msg = format!("encountered {}", $what);
+ let where_ = &$where;
+ if !where_.is_empty() {
+ msg.push_str(" at ");
+ write_path(&mut msg, where_);
+ }
+ throw_unsup!(ValidationFailure(msg))
}};
}
@@ -60,7 +55,7 @@
Ok(x) => x,
Err(_) => throw_validation_failure!($what, $where),
}
- }}
+ }};
}
/// We want to show a nice path to the invalid field for diagnostics,
@@ -113,10 +108,9 @@
}
/// Format a path
-fn path_format(path: &Vec<PathElem>) -> String {
+fn write_path(out: &mut String, path: &Vec<PathElem>) {
use self::PathElem::*;
- let mut out = String::new();
for elem in path.iter() {
match elem {
Field(name) => write!(out, ".{}", name),
@@ -135,7 +129,6 @@
DynDowncast => write!(out, ".<dyn-downcast>"),
}.unwrap()
}
- out
}
// Test if a range that wraps at overflow contains `test`
@@ -428,7 +421,7 @@
err_unsup!(InvalidNullPointerUsage) =>
throw_validation_failure!("NULL reference", self.path),
err_unsup!(AlignmentCheckFailed { required, has }) =>
- throw_validation_failure!(format!("unaligned reference \
+ throw_validation_failure!(format_args!("unaligned reference \
(required {} byte alignment but found {})",
required.bytes(), has.bytes()), self.path),
err_unsup!(ReadBytesAsPointer) =>
@@ -519,7 +512,7 @@
let value = try_validation!(value.not_undef(),
value,
self.path,
- format!(
+ format_args!(
"something {}",
wrapping_range_format(&layout.valid_range, max_hi),
)
@@ -532,7 +525,7 @@
throw_validation_failure!(
"a potentially NULL pointer",
self.path,
- format!(
+ format_args!(
"something that cannot possibly fail to be {}",
wrapping_range_format(&layout.valid_range, max_hi)
)
@@ -545,7 +538,7 @@
throw_validation_failure!(
"a pointer",
self.path,
- format!(
+ format_args!(
"something that cannot possibly fail to be {}",
wrapping_range_format(&layout.valid_range, max_hi)
)
@@ -562,7 +555,7 @@
throw_validation_failure!(
bits,
self.path,
- format!("something {}", wrapping_range_format(&layout.valid_range, max_hi))
+ format_args!("something {}", wrapping_range_format(&layout.valid_range, max_hi))
)
}
}
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 253fc55..726b3ba 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1289,8 +1289,20 @@
}
// Error possibly reported in `check_assign` so avoid emitting error again.
- err.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected))
- .is_some());
+ let assign_to_bool = expression
+ // #67273: Use initial expected type as opposed to `expected`.
+ // Otherwise we end up using prior coercions in e.g. a `match` expression:
+ // ```
+ // match i {
+ // 0 => true, // Because of this...
+ // 1 => i = 1, // ...`expected == bool` now, but not when checking `i = 1`.
+ // _ => (),
+ // };
+ // ```
+ .filter(|e| fcx.is_assign_to_bool(e, self.expected_ty()))
+ .is_some();
+
+ err.emit_unless(assign_to_bool);
self.final_ty = Some(fcx.tcx.types.err);
}
diff --git a/src/test/ui/error-codes/E0004-2.stderr b/src/test/ui/error-codes/E0004-2.stderr
index db0a2b5..f5b41cd 100644
--- a/src/test/ui/error-codes/E0004-2.stderr
+++ b/src/test/ui/error-codes/E0004-2.stderr
@@ -1,8 +1,8 @@
-error[E0004]: non-exhaustive patterns: multiple patterns of type `std::option::Option<i32>` are not handled
+error[E0004]: non-exhaustive patterns: `None` and `Some(_)` not covered
--> $DIR/E0004-2.rs:4:11
|
LL | match x { }
- | ^
+ | ^ patterns `None` and `Some(_)` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
diff --git a/src/test/ui/issues/issue-3601.stderr b/src/test/ui/issues/issue-3601.stderr
index fa0fa334..445eb41 100644
--- a/src/test/ui/issues/issue-3601.stderr
+++ b/src/test/ui/issues/issue-3601.stderr
@@ -1,8 +1,8 @@
-error[E0004]: non-exhaustive patterns: `_` not covered
+error[E0004]: non-exhaustive patterns: `Box(_)` not covered
--> $DIR/issue-3601.rs:30:44
|
LL | box NodeKind::Element(ed) => match ed.kind {
- | ^^^^^^^ pattern `_` not covered
+ | ^^^^^^^ pattern `Box(_)` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
index 792ab6f..1b1096c 100644
--- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
+++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
@@ -9,8 +9,13 @@
error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
--> $DIR/always-inhabited-union-ref.rs:27:11
|
-LL | match uninhab_union() {
- | ^^^^^^^^^^^^^^^
+LL | / pub union Foo {
+LL | | foo: !,
+LL | | }
+ | |_- `Foo` defined here
+...
+LL | match uninhab_union() {
+ | ^^^^^^^^^^^^^^^
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
diff --git a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs
new file mode 100644
index 0000000..57b6b91
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs
@@ -0,0 +1,93 @@
+#![feature(never_type)]
+#![feature(exhaustive_patterns)]
+#![deny(unreachable_patterns)]
+enum Foo {}
+
+struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here
+union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here
+ foo: (),
+}
+union NonEmptyUnion2 { //~ `NonEmptyUnion2` defined here
+ foo: (),
+ bar: (),
+}
+enum NonEmptyEnum1 { //~ `NonEmptyEnum1` defined here
+ Foo(bool),
+ //~^ not covered
+ //~| not covered
+}
+enum NonEmptyEnum2 { //~ `NonEmptyEnum2` defined here
+ Foo(bool),
+ //~^ not covered
+ //~| not covered
+ Bar,
+ //~^ not covered
+ //~| not covered
+}
+enum NonEmptyEnum5 { //~ `NonEmptyEnum5` defined here
+ V1, V2, V3, V4, V5,
+}
+
+macro_rules! match_empty {
+ ($e:expr) => {
+ match $e {}
+ };
+}
+macro_rules! match_false {
+ ($e:expr) => {
+ match $e {
+ _ if false => {}
+ }
+ };
+}
+
+fn foo(x: Foo) {
+ match_empty!(x); // ok
+ match x {
+ _ => {}, //~ ERROR unreachable pattern
+ }
+ match x {
+ _ if false => {}, //~ ERROR unreachable pattern
+ }
+}
+
+fn main() {
+ match None::<!> {
+ None => {}
+ Some(_) => {} //~ ERROR unreachable pattern
+ }
+ match None::<Foo> {
+ None => {}
+ Some(_) => {} //~ ERROR unreachable pattern
+ }
+
+ match_empty!(0u8);
+ //~^ ERROR type `u8` is non-empty
+ match_empty!(NonEmptyStruct(true));
+ //~^ ERROR type `NonEmptyStruct` is non-empty
+ match_empty!((NonEmptyUnion1 { foo: () }));
+ //~^ ERROR type `NonEmptyUnion1` is non-empty
+ match_empty!((NonEmptyUnion2 { foo: () }));
+ //~^ ERROR type `NonEmptyUnion2` is non-empty
+ match_empty!(NonEmptyEnum1::Foo(true));
+ //~^ ERROR `Foo(_)` not covered
+ match_empty!(NonEmptyEnum2::Foo(true));
+ //~^ ERROR `Foo(_)` and `Bar` not covered
+ match_empty!(NonEmptyEnum5::V1);
+ //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
+
+ match_false!(0u8);
+ //~^ ERROR `_` not covered
+ match_false!(NonEmptyStruct(true));
+ //~^ ERROR `NonEmptyStruct(_)` not covered
+ match_false!((NonEmptyUnion1 { foo: () }));
+ //~^ ERROR `NonEmptyUnion1 { .. }` not covered
+ match_false!((NonEmptyUnion2 { foo: () }));
+ //~^ ERROR `NonEmptyUnion2 { .. }` not covered
+ match_false!(NonEmptyEnum1::Foo(true));
+ //~^ ERROR `Foo(_)` not covered
+ match_false!(NonEmptyEnum2::Foo(true));
+ //~^ ERROR `Foo(_)` and `Bar` not covered
+ match_false!(NonEmptyEnum5::V1);
+ //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
+}
diff --git a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr
new file mode 100644
index 0000000..f242ecf
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr
@@ -0,0 +1,223 @@
+error: unreachable pattern
+ --> $DIR/match-empty-exhaustive_patterns.rs:47:9
+ |
+LL | _ => {},
+ | ^
+ |
+note: lint level defined here
+ --> $DIR/match-empty-exhaustive_patterns.rs:3:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-empty-exhaustive_patterns.rs:50:9
+ |
+LL | _ if false => {},
+ | ^
+
+error: unreachable pattern
+ --> $DIR/match-empty-exhaustive_patterns.rs:57:9
+ |
+LL | Some(_) => {}
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-empty-exhaustive_patterns.rs:61:9
+ |
+LL | Some(_) => {}
+ | ^^^^^^^
+
+error[E0004]: non-exhaustive patterns: type `u8` is non-empty
+ --> $DIR/match-empty-exhaustive_patterns.rs:64:18
+ |
+LL | match_empty!(0u8);
+ | ^^^
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct` is non-empty
+ --> $DIR/match-empty-exhaustive_patterns.rs:66:18
+ |
+LL | struct NonEmptyStruct(bool);
+ | ---------------------------- `NonEmptyStruct` defined here
+...
+LL | match_empty!(NonEmptyStruct(true));
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
+ --> $DIR/match-empty-exhaustive_patterns.rs:68:18
+ |
+LL | / union NonEmptyUnion1 {
+LL | | foo: (),
+LL | | }
+ | |_- `NonEmptyUnion1` defined here
+...
+LL | match_empty!((NonEmptyUnion1 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
+ --> $DIR/match-empty-exhaustive_patterns.rs:70:18
+ |
+LL | / union NonEmptyUnion2 {
+LL | | foo: (),
+LL | | bar: (),
+LL | | }
+ | |_- `NonEmptyUnion2` defined here
+...
+LL | match_empty!((NonEmptyUnion2 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
+ --> $DIR/match-empty-exhaustive_patterns.rs:72:18
+ |
+LL | / enum NonEmptyEnum1 {
+LL | | Foo(bool),
+ | | --- not covered
+LL | |
+LL | |
+LL | | }
+ | |_- `NonEmptyEnum1` defined here
+...
+LL | match_empty!(NonEmptyEnum1::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
+ --> $DIR/match-empty-exhaustive_patterns.rs:74:18
+ |
+LL | / enum NonEmptyEnum2 {
+LL | | Foo(bool),
+ | | --- not covered
+LL | |
+LL | |
+LL | | Bar,
+ | | --- not covered
+LL | |
+LL | |
+LL | | }
+ | |_- `NonEmptyEnum2` defined here
+...
+LL | match_empty!(NonEmptyEnum2::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
+ --> $DIR/match-empty-exhaustive_patterns.rs:76:18
+ |
+LL | / enum NonEmptyEnum5 {
+LL | | V1, V2, V3, V4, V5,
+LL | | }
+ | |_- `NonEmptyEnum5` defined here
+...
+LL | match_empty!(NonEmptyEnum5::V1);
+ | ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/match-empty-exhaustive_patterns.rs:79:18
+ |
+LL | match_false!(0u8);
+ | ^^^ pattern `_` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct(_)` not covered
+ --> $DIR/match-empty-exhaustive_patterns.rs:81:18
+ |
+LL | struct NonEmptyStruct(bool);
+ | ---------------------------- `NonEmptyStruct` defined here
+...
+LL | match_false!(NonEmptyStruct(true));
+ | ^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct(_)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
+ --> $DIR/match-empty-exhaustive_patterns.rs:83:18
+ |
+LL | / union NonEmptyUnion1 {
+LL | | foo: (),
+LL | | }
+ | |_- `NonEmptyUnion1` defined here
+...
+LL | match_false!((NonEmptyUnion1 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
+ --> $DIR/match-empty-exhaustive_patterns.rs:85:18
+ |
+LL | / union NonEmptyUnion2 {
+LL | | foo: (),
+LL | | bar: (),
+LL | | }
+ | |_- `NonEmptyUnion2` defined here
+...
+LL | match_false!((NonEmptyUnion2 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
+ --> $DIR/match-empty-exhaustive_patterns.rs:87:18
+ |
+LL | / enum NonEmptyEnum1 {
+LL | | Foo(bool),
+ | | --- not covered
+LL | |
+LL | |
+LL | | }
+ | |_- `NonEmptyEnum1` defined here
+...
+LL | match_false!(NonEmptyEnum1::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
+ --> $DIR/match-empty-exhaustive_patterns.rs:89:18
+ |
+LL | / enum NonEmptyEnum2 {
+LL | | Foo(bool),
+ | | --- not covered
+LL | |
+LL | |
+LL | | Bar,
+ | | --- not covered
+LL | |
+LL | |
+LL | | }
+ | |_- `NonEmptyEnum2` defined here
+...
+LL | match_false!(NonEmptyEnum2::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
+ --> $DIR/match-empty-exhaustive_patterns.rs:91:18
+ |
+LL | / enum NonEmptyEnum5 {
+LL | | V1, V2, V3, V4, V5,
+LL | | }
+ | |_- `NonEmptyEnum5` defined here
+...
+LL | match_false!(NonEmptyEnum5::V1);
+ | ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 18 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/match-empty.rs b/src/test/ui/pattern/usefulness/match-empty.rs
new file mode 100644
index 0000000..f757712
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-empty.rs
@@ -0,0 +1,92 @@
+#![feature(never_type)]
+#![deny(unreachable_patterns)]
+enum Foo {}
+
+struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here
+union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here
+ foo: (),
+}
+union NonEmptyUnion2 { //~ `NonEmptyUnion2` defined here
+ foo: (),
+ bar: (),
+}
+enum NonEmptyEnum1 { //~ `NonEmptyEnum1` defined here
+ Foo(bool),
+ //~^ not covered
+ //~| not covered
+}
+enum NonEmptyEnum2 { //~ `NonEmptyEnum2` defined here
+ Foo(bool),
+ //~^ not covered
+ //~| not covered
+ Bar,
+ //~^ not covered
+ //~| not covered
+}
+enum NonEmptyEnum5 { //~ `NonEmptyEnum5` defined here
+ V1, V2, V3, V4, V5,
+}
+
+macro_rules! match_empty {
+ ($e:expr) => {
+ match $e {}
+ };
+}
+macro_rules! match_false {
+ ($e:expr) => {
+ match $e {
+ _ if false => {}
+ }
+ };
+}
+
+fn foo(x: Foo) {
+ match_empty!(x); // ok
+ match_false!(x); // Not detected as unreachable nor exhaustive.
+ //~^ ERROR non-exhaustive patterns: `_` not covered
+ match x {
+ _ => {}, // Not detected as unreachable, see #55123.
+ }
+}
+
+fn main() {
+ // `exhaustive_patterns` is not on, so uninhabited branches are not detected as unreachable.
+ match None::<!> {
+ None => {}
+ Some(_) => {}
+ }
+ match None::<Foo> {
+ None => {}
+ Some(_) => {}
+ }
+
+ match_empty!(0u8);
+ //~^ ERROR type `u8` is non-empty
+ match_empty!(NonEmptyStruct(true));
+ //~^ ERROR type `NonEmptyStruct` is non-empty
+ match_empty!((NonEmptyUnion1 { foo: () }));
+ //~^ ERROR type `NonEmptyUnion1` is non-empty
+ match_empty!((NonEmptyUnion2 { foo: () }));
+ //~^ ERROR type `NonEmptyUnion2` is non-empty
+ match_empty!(NonEmptyEnum1::Foo(true));
+ //~^ ERROR `Foo(_)` not covered
+ match_empty!(NonEmptyEnum2::Foo(true));
+ //~^ ERROR `Foo(_)` and `Bar` not covered
+ match_empty!(NonEmptyEnum5::V1);
+ //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
+
+ match_false!(0u8);
+ //~^ ERROR `_` not covered
+ match_false!(NonEmptyStruct(true));
+ //~^ ERROR `NonEmptyStruct(_)` not covered
+ match_false!((NonEmptyUnion1 { foo: () }));
+ //~^ ERROR `NonEmptyUnion1 { .. }` not covered
+ match_false!((NonEmptyUnion2 { foo: () }));
+ //~^ ERROR `NonEmptyUnion2 { .. }` not covered
+ match_false!(NonEmptyEnum1::Foo(true));
+ //~^ ERROR `Foo(_)` not covered
+ match_false!(NonEmptyEnum2::Foo(true));
+ //~^ ERROR `Foo(_)` and `Bar` not covered
+ match_false!(NonEmptyEnum5::V1);
+ //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
+}
diff --git a/src/test/ui/pattern/usefulness/match-empty.stderr b/src/test/ui/pattern/usefulness/match-empty.stderr
new file mode 100644
index 0000000..72e3fc0
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-empty.stderr
@@ -0,0 +1,204 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/match-empty.rs:45:18
+ |
+LL | enum Foo {}
+ | ----------- `Foo` defined here
+...
+LL | match_false!(x); // Not detected as unreachable nor exhaustive.
+ | ^ pattern `_` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `u8` is non-empty
+ --> $DIR/match-empty.rs:63:18
+ |
+LL | match_empty!(0u8);
+ | ^^^
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct` is non-empty
+ --> $DIR/match-empty.rs:65:18
+ |
+LL | struct NonEmptyStruct(bool);
+ | ---------------------------- `NonEmptyStruct` defined here
+...
+LL | match_empty!(NonEmptyStruct(true));
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
+ --> $DIR/match-empty.rs:67:18
+ |
+LL | / union NonEmptyUnion1 {
+LL | | foo: (),
+LL | | }
+ | |_- `NonEmptyUnion1` defined here
+...
+LL | match_empty!((NonEmptyUnion1 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
+ --> $DIR/match-empty.rs:69:18
+ |
+LL | / union NonEmptyUnion2 {
+LL | | foo: (),
+LL | | bar: (),
+LL | | }
+ | |_- `NonEmptyUnion2` defined here
+...
+LL | match_empty!((NonEmptyUnion2 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
+ --> $DIR/match-empty.rs:71:18
+ |
+LL | / enum NonEmptyEnum1 {
+LL | | Foo(bool),
+ | | --- not covered
+LL | |
+LL | |
+LL | | }
+ | |_- `NonEmptyEnum1` defined here
+...
+LL | match_empty!(NonEmptyEnum1::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
+ --> $DIR/match-empty.rs:73:18
+ |
+LL | / enum NonEmptyEnum2 {
+LL | | Foo(bool),
+ | | --- not covered
+LL | |
+LL | |
+LL | | Bar,
+ | | --- not covered
+LL | |
+LL | |
+LL | | }
+ | |_- `NonEmptyEnum2` defined here
+...
+LL | match_empty!(NonEmptyEnum2::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
+ --> $DIR/match-empty.rs:75:18
+ |
+LL | / enum NonEmptyEnum5 {
+LL | | V1, V2, V3, V4, V5,
+LL | | }
+ | |_- `NonEmptyEnum5` defined here
+...
+LL | match_empty!(NonEmptyEnum5::V1);
+ | ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/match-empty.rs:78:18
+ |
+LL | match_false!(0u8);
+ | ^^^ pattern `_` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct(_)` not covered
+ --> $DIR/match-empty.rs:80:18
+ |
+LL | struct NonEmptyStruct(bool);
+ | ---------------------------- `NonEmptyStruct` defined here
+...
+LL | match_false!(NonEmptyStruct(true));
+ | ^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct(_)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
+ --> $DIR/match-empty.rs:82:18
+ |
+LL | / union NonEmptyUnion1 {
+LL | | foo: (),
+LL | | }
+ | |_- `NonEmptyUnion1` defined here
+...
+LL | match_false!((NonEmptyUnion1 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
+ --> $DIR/match-empty.rs:84:18
+ |
+LL | / union NonEmptyUnion2 {
+LL | | foo: (),
+LL | | bar: (),
+LL | | }
+ | |_- `NonEmptyUnion2` defined here
+...
+LL | match_false!((NonEmptyUnion2 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
+ --> $DIR/match-empty.rs:86:18
+ |
+LL | / enum NonEmptyEnum1 {
+LL | | Foo(bool),
+ | | --- not covered
+LL | |
+LL | |
+LL | | }
+ | |_- `NonEmptyEnum1` defined here
+...
+LL | match_false!(NonEmptyEnum1::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
+ --> $DIR/match-empty.rs:88:18
+ |
+LL | / enum NonEmptyEnum2 {
+LL | | Foo(bool),
+ | | --- not covered
+LL | |
+LL | |
+LL | | Bar,
+ | | --- not covered
+LL | |
+LL | |
+LL | | }
+ | |_- `NonEmptyEnum2` defined here
+...
+LL | match_false!(NonEmptyEnum2::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
+ --> $DIR/match-empty.rs:90:18
+ |
+LL | / enum NonEmptyEnum5 {
+LL | | V1, V2, V3, V4, V5,
+LL | | }
+ | |_- `NonEmptyEnum5` defined here
+...
+LL | match_false!(NonEmptyEnum5::V1);
+ | ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 15 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
index bbc25d4..8516baf 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
@@ -6,3 +6,6 @@
Tuple(u32),
Struct { field: u32 }
}
+
+#[non_exhaustive]
+pub enum EmptyNonExhaustiveEnum {}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum.rs b/src/test/ui/rfc-2008-non-exhaustive/enum.rs
index 7423a97..802f20b 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/enum.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum.rs
@@ -1,7 +1,14 @@
// aux-build:enums.rs
extern crate enums;
-use enums::NonExhaustiveEnum;
+use enums::{EmptyNonExhaustiveEnum, NonExhaustiveEnum};
+
+fn empty(x: EmptyNonExhaustiveEnum) {
+ match x {} //~ ERROR type `enums::EmptyNonExhaustiveEnum` is non-empty
+ match x {
+ _ => {}, // ok
+ }
+}
fn main() {
let enum_unit = NonExhaustiveEnum::Unit;
@@ -13,6 +20,9 @@
NonExhaustiveEnum::Struct { .. } => "third"
};
+ match enum_unit {};
+ //~^ ERROR non-exhaustive patterns: `_` not covered [E0004]
+
// Everything below this is expected to compile successfully.
let enum_unit = NonExhaustiveEnum::Unit;
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum.stderr
index b5c1a4e..a2bdcba 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/enum.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum.stderr
@@ -1,11 +1,27 @@
+error[E0004]: non-exhaustive patterns: type `enums::EmptyNonExhaustiveEnum` is non-empty
+ --> $DIR/enum.rs:7:11
+ |
+LL | match x {}
+ | ^
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
error[E0004]: non-exhaustive patterns: `_` not covered
- --> $DIR/enum.rs:9:11
+ --> $DIR/enum.rs:16:11
|
LL | match enum_unit {
| ^^^^^^^^^ pattern `_` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error: aborting due to previous error
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/enum.rs:23:11
+ |
+LL | match enum_unit {};
+ | ^^^^^^^^^ pattern `_` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs
new file mode 100644
index 0000000..afd6d99
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs
@@ -0,0 +1,37 @@
+#![deny(unreachable_patterns)]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+ Unit,
+ //~^ not covered
+ Tuple(u32),
+ //~^ not covered
+ Struct { field: u32 }
+ //~^ not covered
+}
+
+pub enum NormalEnum {
+ Unit,
+ //~^ not covered
+ Tuple(u32),
+ //~^ not covered
+ Struct { field: u32 }
+ //~^ not covered
+}
+
+#[non_exhaustive]
+pub enum EmptyNonExhaustiveEnum {}
+
+fn empty_non_exhaustive(x: EmptyNonExhaustiveEnum) {
+ match x {}
+ match x {
+ _ => {} // not detected as unreachable
+ }
+}
+
+fn main() {
+ match NonExhaustiveEnum::Unit {}
+ //~^ ERROR `Unit`, `Tuple(_)` and `Struct { .. }` not covered [E0004]
+ match NormalEnum::Unit {}
+ //~^ ERROR `Unit`, `Tuple(_)` and `Struct { .. }` not covered [E0004]
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
new file mode 100644
index 0000000..a99a690
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
@@ -0,0 +1,45 @@
+error[E0004]: non-exhaustive patterns: `Unit`, `Tuple(_)` and `Struct { .. }` not covered
+ --> $DIR/enum_same_crate_empty_match.rs:33:11
+ |
+LL | / pub enum NonExhaustiveEnum {
+LL | | Unit,
+ | | ---- not covered
+LL | |
+LL | | Tuple(u32),
+ | | ----- not covered
+LL | |
+LL | | Struct { field: u32 }
+ | | ------ not covered
+LL | |
+LL | | }
+ | |_- `NonExhaustiveEnum` defined here
+...
+LL | match NonExhaustiveEnum::Unit {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^ patterns `Unit`, `Tuple(_)` and `Struct { .. }` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Unit`, `Tuple(_)` and `Struct { .. }` not covered
+ --> $DIR/enum_same_crate_empty_match.rs:35:11
+ |
+LL | / pub enum NormalEnum {
+LL | | Unit,
+ | | ---- not covered
+LL | |
+LL | | Tuple(u32),
+ | | ----- not covered
+LL | |
+LL | | Struct { field: u32 }
+ | | ------ not covered
+LL | |
+LL | | }
+ | |_- `NormalEnum` defined here
+...
+LL | match NormalEnum::Unit {}
+ | ^^^^^^^^^^^^^^^^ patterns `Unit`, `Tuple(_)` and `Struct { .. }` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
index b903e9b..0d669a9a 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
@@ -1,4 +1,4 @@
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedEnum` of type `uninhabited::IndirectUninhabitedEnum` is not handled
+error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedEnum` is non-empty
--> $DIR/indirect_match.rs:18:11
|
LL | match x {}
@@ -6,7 +6,7 @@
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedStruct` of type `uninhabited::IndirectUninhabitedStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedStruct` is non-empty
--> $DIR/indirect_match.rs:22:11
|
LL | match x {}
@@ -14,7 +14,7 @@
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedTupleStruct` of type `uninhabited::IndirectUninhabitedTupleStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedTupleStruct` is non-empty
--> $DIR/indirect_match.rs:26:11
|
LL | match x {}
@@ -22,7 +22,7 @@
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedVariants` of type `uninhabited::IndirectUninhabitedVariants` is not handled
+error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedVariants` is non-empty
--> $DIR/indirect_match.rs:32:11
|
LL | match x {}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
index f94616d..41a37cf 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
@@ -1,53 +1,41 @@
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedEnum` of type `IndirectUninhabitedEnum` is not handled
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty
--> $DIR/indirect_match_same_crate.rs:32:11
|
LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
- | ----------------------------------------------------
- | | |
- | | variant not covered
- | `IndirectUninhabitedEnum` defined here
+ | ---------------------------------------------------- `IndirectUninhabitedEnum` defined here
...
LL | match x {}
| ^
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedStruct` of type `IndirectUninhabitedStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
--> $DIR/indirect_match_same_crate.rs:36:11
|
LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
- | --------------------------------------------------------
- | | |
- | | variant not covered
- | `IndirectUninhabitedStruct` defined here
+ | -------------------------------------------------------- `IndirectUninhabitedStruct` defined here
...
LL | match x {}
| ^
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedTupleStruct` of type `IndirectUninhabitedTupleStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
--> $DIR/indirect_match_same_crate.rs:40:11
|
LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
- | ------------------------------------------------------------------
- | | |
- | | variant not covered
- | `IndirectUninhabitedTupleStruct` defined here
+ | ------------------------------------------------------------------ `IndirectUninhabitedTupleStruct` defined here
...
LL | match x {}
| ^
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedVariants` of type `IndirectUninhabitedVariants` is not handled
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
--> $DIR/indirect_match_same_crate.rs:46:11
|
LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
- | ------------------------------------------------------------
- | | |
- | | variant not covered
- | `IndirectUninhabitedVariants` defined here
+ | ------------------------------------------------------------ `IndirectUninhabitedVariants` defined here
...
LL | match x {}
| ^
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr
index de3fa90..10a456a 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr
@@ -6,7 +6,7 @@
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: pattern `UninhabitedStruct` of type `uninhabited::UninhabitedStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedStruct` is non-empty
--> $DIR/match.rs:22:11
|
LL | match x {}
@@ -14,7 +14,7 @@
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: pattern `UninhabitedTupleStruct` of type `uninhabited::UninhabitedTupleStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedTupleStruct` is non-empty
--> $DIR/match.rs:26:11
|
LL | match x {}
@@ -22,11 +22,11 @@
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: multiple patterns of type `uninhabited::UninhabitedVariants` are not handled
+error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered
--> $DIR/match.rs:30:11
|
LL | match x {}
- | ^
+ | ^ patterns `Tuple(_)` and `Struct { .. }` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
index 3dd1a91..148af8c 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
@@ -1,10 +1,7 @@
-error[E0004]: non-exhaustive patterns: pattern `UninhabitedStruct` of type `UninhabitedStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
--> $DIR/match_same_crate.rs:28:11
|
-LL | pub struct UninhabitedStruct {
- | - ----------------- variant not covered
- | _|
- | |
+LL | / pub struct UninhabitedStruct {
LL | | _priv: !,
LL | | }
| |_- `UninhabitedStruct` defined here
@@ -14,33 +11,30 @@
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: pattern `UninhabitedTupleStruct` of type `UninhabitedTupleStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
--> $DIR/match_same_crate.rs:32:11
|
LL | pub struct UninhabitedTupleStruct(!);
- | -------------------------------------
- | | |
- | | variant not covered
- | `UninhabitedTupleStruct` defined here
+ | ------------------------------------- `UninhabitedTupleStruct` defined here
...
LL | match x {}
| ^
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: multiple patterns of type `UninhabitedVariants` are not handled
+error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered
--> $DIR/match_same_crate.rs:36:11
|
LL | / pub enum UninhabitedVariants {
LL | | #[non_exhaustive] Tuple(!),
- | | ----- variant not covered
+ | | ----- not covered
LL | | #[non_exhaustive] Struct { x: ! }
- | | ------ variant not covered
+ | | ------ not covered
LL | | }
| |_- `UninhabitedVariants` defined here
...
LL | match x {}
- | ^
+ | ^ patterns `Tuple(_)` and `Struct { .. }` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
index 3b56c68..2fc09c8 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
@@ -22,11 +22,11 @@
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedVariants` is non-empty
+error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered
--> $DIR/match_with_exhaustive_patterns.rs:33:11
|
LL | match x {}
- | ^
+ | ^ patterns `Tuple(_)` and `Struct { .. }` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
diff --git a/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs b/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs
new file mode 100644
index 0000000..e23c0d0
--- /dev/null
+++ b/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs
@@ -0,0 +1,27 @@
+fn main() {
+ let mut i: i64;
+ // Expected type is an inference variable `?T`
+ // because the `match` is used as a statement.
+ // This is the "initial" type of the `coercion`.
+ match i {
+ // Add `bool` to the overall `coercion`.
+ 0 => true,
+
+ // Necessary to cause the ICE:
+ 1 => true,
+
+ // Suppose that we had `let _: bool = match i { ... }`.
+ // In that case, as the expected type would be `bool`,
+ // we would suggest `i == 1` as a fix.
+ //
+ // However, no type error happens when checking `i = 1` because `expected == ?T`,
+ // which will unify with `typeof(i = 1) == ()`.
+ //
+ // However, in #67273, we would delay the unification of this arm with the above
+ // because we used the hitherto accumulated coercion as opposed to the "initial" type.
+ 2 => i = 1,
+ //~^ ERROR match arms have incompatible types
+
+ _ => (),
+ }
+}
diff --git a/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr b/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr
new file mode 100644
index 0000000..3547285
--- /dev/null
+++ b/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr
@@ -0,0 +1,22 @@
+error[E0308]: match arms have incompatible types
+ --> $DIR/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs:22:14
+ |
+LL | / match i {
+LL | | // Add `bool` to the overall `coercion`.
+LL | | 0 => true,
+ | | ---- this is found to be of type `bool`
+LL | |
+LL | | // Necessary to cause the ICE:
+LL | | 1 => true,
+ | | ---- this is found to be of type `bool`
+... |
+LL | | 2 => i = 1,
+ | | ^^^^^ expected `bool`, found `()`
+... |
+LL | | _ => (),
+LL | | }
+ | |_____- `match` arms have incompatible types
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
index 7af6075..18ffdcc 100644
--- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -9,6 +9,9 @@
error[E0004]: non-exhaustive patterns: type `&Void` is non-empty
--> $DIR/uninhabited-matches-feature-gated.rs:12:19
|
+LL | enum Void {}
+ | ------------ `Void` defined here
+...
LL | let _ = match x {};
| ^
|