Skip to content

Commit 95a14d4

Browse files
committed
Implement feature gate logic
1 parent 886108b commit 95a14d4

File tree

7 files changed

+797
-149
lines changed

7 files changed

+797
-149
lines changed

compiler/rustc_pattern_analysis/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pub trait TypeCx: Sized + fmt::Debug {
9595
type PatData: Clone;
9696

9797
fn is_exhaustive_patterns_feature_on(&self) -> bool;
98+
fn is_min_exhaustive_patterns_feature_on(&self) -> bool;
9899

99100
/// The number of fields for this constructor.
100101
fn ctor_arity(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> usize;

compiler/rustc_pattern_analysis/src/rustc.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,9 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
182182
// `field.ty()` doesn't normalize after substituting.
183183
let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
184184
let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
185-
let is_uninhabited = cx.tcx.features().exhaustive_patterns && cx.is_uninhabited(ty);
185+
let is_uninhabited = (cx.tcx.features().exhaustive_patterns
186+
|| cx.tcx.features().min_exhaustive_patterns)
187+
&& cx.is_uninhabited(ty);
186188

187189
if is_uninhabited && (!is_visible || is_non_exhaustive) {
188190
None
@@ -960,6 +962,9 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
960962
fn is_exhaustive_patterns_feature_on(&self) -> bool {
961963
self.tcx.features().exhaustive_patterns
962964
}
965+
fn is_min_exhaustive_patterns_feature_on(&self) -> bool {
966+
self.tcx.features().min_exhaustive_patterns
967+
}
963968

964969
fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: &Self::Ty) -> usize {
965970
self.ctor_arity(ctor, *ty)

compiler/rustc_pattern_analysis/src/usefulness.rs

+17-9
Original file line numberDiff line numberDiff line change
@@ -548,11 +548,12 @@
548548
//! [`ValidityConstraint::specialize`].
549549
//!
550550
//! Having said all that, in practice we don't fully follow what's been presented in this section.
551-
//! Under `exhaustive_patterns`, we allow omitting empty arms even in `!known_valid` places, for
552-
//! backwards-compatibility until we have a better alternative. Without `exhaustive_patterns`, we
553-
//! mostly treat empty types as inhabited, except specifically a non-nested `!` or empty enum. In
554-
//! this specific case we also allow the empty match regardless of place validity, for
555-
//! backwards-compatibility. Hopefully we can eventually deprecate this.
551+
//! Let's call "toplevel exception" the case where the match scrutinee itself has type `!` or
552+
//! `EmptyEnum`. First, on stable rust, we require `_` patterns for empty types in all cases apart
553+
//! from the toplevel exception. The `exhaustive_patterns` and `min_exaustive_patterns` allow
554+
//! omitting patterns in the cases described above. There's a final detail: in the toplevel
555+
//! exception or with the `exhaustive_patterns` feature, we ignore place validity when checking
556+
//! whether a pattern is required for exhaustiveness. I (Nadrieril) hope to deprecate this behavior.
556557
//!
557558
//!
558559
//!
@@ -1440,10 +1441,17 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
14401441
// We treat match scrutinees of type `!` or `EmptyEnum` differently.
14411442
let is_toplevel_exception =
14421443
is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors);
1443-
// Whether empty patterns can be omitted for exhaustiveness.
1444-
let can_omit_empty_arms = is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on();
1445-
// Whether empty patterns are counted as useful or not.
1446-
let empty_arms_are_unreachable = place_validity.is_known_valid() && can_omit_empty_arms;
1444+
// Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if
1445+
// it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`).
1446+
let empty_arms_are_unreachable = place_validity.is_known_valid()
1447+
&& (is_toplevel_exception
1448+
|| mcx.tycx.is_exhaustive_patterns_feature_on()
1449+
|| mcx.tycx.is_min_exhaustive_patterns_feature_on());
1450+
// Whether empty patterns can be omitted for exhaustiveness. We ignore place validity in the
1451+
// toplevel exception and `exhaustive_patterns` cases for backwards compatibility.
1452+
let can_omit_empty_arms = empty_arms_are_unreachable
1453+
|| is_toplevel_exception
1454+
|| mcx.tycx.is_exhaustive_patterns_feature_on();
14471455

14481456
// Analyze the constructors present in this column.
14491457
let ctors = matrix.heads().map(|p| p.ctor());

0 commit comments

Comments
 (0)