Skip to content

Commit b6782a0

Browse files
committed
Simplify empty pattern logic a bit
1 parent 8710b20 commit b6782a0

File tree

1 file changed

+13
-14
lines changed

1 file changed

+13
-14
lines changed

compiler/rustc_pattern_analysis/src/usefulness.rs

+13-14
Original file line numberDiff line numberDiff line change
@@ -1354,39 +1354,38 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
13541354

13551355
debug!("ty: {ty:?}");
13561356
let pcx = &PlaceCtxt { mcx, ty };
1357+
let ctors_for_ty = pcx.ctors_for_ty()?;
13571358

13581359
// Whether the place/column we are inspecting is known to contain valid data.
13591360
let place_validity = matrix.place_validity[0];
1361+
// We treat match scrutinees of type `!` or `EmptyEnum` differently.
1362+
let is_toplevel_exception =
1363+
is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors);
1364+
// Whether empty patterns can be omitted for exhaustiveness.
1365+
let can_omit_empty_arms = is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on();
13601366

13611367
// Analyze the constructors present in this column.
13621368
let ctors = matrix.heads().map(|p| p.ctor());
1363-
let ctors_for_ty = pcx.ctors_for_ty()?;
1364-
let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); // For diagnostics.
13651369
let mut split_set = ctors_for_ty.split(ctors);
1366-
// We have now grouped all the constructors into 3 buckets: present, missing, missing_empty.
1367-
// In the absence of the `exhaustive_patterns` feature however, we don't count nested empty
1368-
// types as empty. Only non-nested `!` or `enum Foo {}` are considered empty.
1369-
if !pcx.mcx.tycx.is_exhaustive_patterns_feature_on()
1370-
&& !(is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors))
1371-
{
1370+
if !can_omit_empty_arms {
13721371
// Treat all missing constructors as nonempty.
13731372
// This clears `missing_empty`.
13741373
split_set.missing.append(&mut split_set.missing_empty);
13751374
}
13761375
let all_missing = split_set.present.is_empty();
13771376

13781377
// Build the set of constructors we will specialize with. It must cover the whole type.
1378+
// We need to iterate over a full set of constructors, so we add `Missing` to represent the
1379+
// missing ones. This is explained under "Constructor Splitting" at the top of this file.
13791380
let mut split_ctors = split_set.present;
1380-
if !split_set.missing.is_empty() {
1381-
// We need to iterate over a full set of constructors, so we add `Missing` to represent the
1382-
// missing ones. This is explained under "Constructor Splitting" at the top of this file.
1383-
split_ctors.push(Constructor::Missing);
1384-
} else if !split_set.missing_empty.is_empty() && !place_validity.is_known_valid() {
1385-
// The missing empty constructors are reachable if the place can contain invalid data.
1381+
if !(split_set.missing.is_empty()
1382+
&& (split_set.missing_empty.is_empty() || place_validity.is_known_valid()))
1383+
{
13861384
split_ctors.push(Constructor::Missing);
13871385
}
13881386

13891387
// Decide what constructors to report.
1388+
let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. });
13901389
let always_report_all = is_top_level && !is_integers;
13911390
// Whether we should report "Enum::A and Enum::C are missing" or "_ is missing".
13921391
let report_individual_missing_ctors = always_report_all || !all_missing;

0 commit comments

Comments
 (0)