Skip to content

Commit a8cc4cf

Browse files
committed
min_exhaustive_patterns
1 parent 21cce21 commit a8cc4cf

File tree

10 files changed

+783
-146
lines changed

10 files changed

+783
-146
lines changed

compiler/rustc_feature/src/unstable.rs

+3
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,9 @@ declare_features! (
512512
(unstable, macro_metavar_expr, "1.61.0", Some(83527)),
513513
/// Allows `#[marker]` on certain traits allowing overlapping implementations.
514514
(unstable, marker_trait_attr, "1.30.0", Some(29864)),
515+
/// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are
516+
/// unambiguously sound.
517+
(unstable, min_exhaustive_patterns, "CURRENT_RUSTC_VERSION", None),
515518
/// A minimal, sound subset of specialization intended to be used by the
516519
/// standard library until the soundness issues with specialization
517520
/// are fixed.

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,8 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
295295
fn is_known_valid_scrutinee(&self, scrutinee: &Expr<'tcx>) -> bool {
296296
use ExprKind::*;
297297
match &scrutinee.kind {
298-
// Both pointers and references can validly point to a place with invalid data.
298+
// Pointers can validly point to a place with invalid data. It is undecided whether
299+
// references can too, so we conservatively assume they can.
299300
Deref { .. } => false,
300301
// Inherit validity of the parent place, unless the parent is an union.
301302
Field { lhs, .. } => {

compiler/rustc_pattern_analysis/src/constructor.rs

+1
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ impl ConstructorSet {
976976
// In the absence of the `exhaustive_patterns` feature however, we don't count nested empty
977977
// types as empty. Only non-nested `!` or `enum Foo {}` are considered empty.
978978
if !pcx.cx.tcx.features().exhaustive_patterns
979+
&& !pcx.cx.tcx.features().min_exhaustive_patterns
979980
&& !(pcx.is_top_level && matches!(self, Self::NoConstructors))
980981
{
981982
// Treat all missing constructors as nonempty.

compiler/rustc_pattern_analysis/src/cx.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
8989
// `field.ty()` doesn't normalize after substituting.
9090
let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
9191
let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
92-
let is_uninhabited = cx.tcx.features().exhaustive_patterns && cx.is_uninhabited(ty);
92+
let is_uninhabited = (cx.tcx.features().exhaustive_patterns
93+
|| cx.tcx.features().min_exhaustive_patterns)
94+
&& cx.is_uninhabited(ty);
9395

9496
if is_uninhabited && (!is_visible || is_non_exhaustive) {
9597
None

compiler/rustc_pattern_analysis/src/usefulness.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -1186,17 +1186,23 @@ fn compute_exhaustiveness_and_usefulness<'p, 'tcx>(
11861186

11871187
debug!("ty: {ty:?}");
11881188
let pcx = &PatCtxt { cx, ty, is_top_level };
1189+
let ctors_for_ty = &cx.ctors_for_ty(ty);
1190+
let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); // For diagnostics.
11891191

11901192
// Whether the place/column we are inspecting is known to contain valid data.
1191-
let place_validity = matrix.place_validity[0];
1192-
// For backwards compability we allow omitting some empty arms that we ideally shouldn't.
1193-
let place_validity = place_validity.allow_omitting_side_effecting_arms();
1193+
let mut place_validity = matrix.place_validity[0];
1194+
if !pcx.cx.tcx.features().min_exhaustive_patterns
1195+
|| (is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors))
1196+
{
1197+
// For backwards compability we allow omitting some empty arms that we ideally shouldn't.
1198+
place_validity = place_validity.allow_omitting_side_effecting_arms();
1199+
}
11941200

11951201
// Analyze the constructors present in this column.
11961202
let ctors = matrix.heads().map(|p| p.ctor());
1197-
let ctors_for_ty = &cx.ctors_for_ty(ty);
1198-
let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); // For diagnostics.
11991203
let split_set = ctors_for_ty.split(pcx, ctors);
1204+
1205+
// Decide what constructors to report.
12001206
let all_missing = split_set.present.is_empty();
12011207

12021208
// Build the set of constructors we will specialize with. It must cover the whole type.

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,7 @@ symbols! {
10151015
min_const_fn,
10161016
min_const_generics,
10171017
min_const_unsafe_fn,
1018+
min_exhaustive_patterns,
10181019
min_specialization,
10191020
min_type_alias_impl_trait,
10201021
minnumf32,

0 commit comments

Comments
 (0)