Skip to content

Commit 7cc0ad8

Browse files
committed
min_exhaustive_patterns
1 parent 61afc9c commit 7cc0ad8

File tree

9 files changed

+783
-145
lines changed

9 files changed

+783
-145
lines changed

compiler/rustc_feature/src/unstable.rs

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

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

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

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,7 @@ impl ConstructorSet {
12491249
// In the absence of the `exhaustive_patterns` feature however, we don't count nested empty
12501250
// types as empty. Only non-nested `!` or `enum Foo {}` are considered empty.
12511251
if !pcx.cx.tcx.features().exhaustive_patterns
1252+
&& !pcx.cx.tcx.features().min_exhaustive_patterns
12521253
&& !(pcx.is_top_level && matches!(self, Self::NoConstructors))
12531254
{
12541255
// Treat all missing constructors as nonempty.
@@ -1328,7 +1329,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
13281329
// `field.ty()` doesn't normalize after substituting.
13291330
let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
13301331
let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
1331-
let is_uninhabited = cx.tcx.features().exhaustive_patterns && cx.is_uninhabited(ty);
1332+
let is_uninhabited = (cx.tcx.features().exhaustive_patterns
1333+
|| cx.tcx.features().min_exhaustive_patterns)
1334+
&& cx.is_uninhabited(ty);
13321335

13331336
if is_uninhabited && (!is_visible || is_non_exhaustive) {
13341337
None

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

+11-4
Original file line numberDiff line numberDiff line change
@@ -1238,15 +1238,22 @@ fn compute_exhaustiveness_and_usefulness<'p, 'tcx>(
12381238

12391239
debug!("ty: {ty:?}");
12401240
let pcx = &PatCtxt { cx, ty, is_top_level };
1241+
let ctors_for_ty = ConstructorSet::for_ty(cx, ty);
12411242

12421243
// Whether the place/column we are inspecting is known to contain valid data.
1243-
let place_validity = matrix.place_validity[0];
1244-
// For backwards compability we allow omitting some empty arms that we ideally shouldn't.
1245-
let place_validity = place_validity.allow_omitting_side_effecting_arms();
1244+
let mut place_validity = matrix.place_validity[0];
1245+
if !pcx.cx.tcx.features().min_exhaustive_patterns
1246+
|| (is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors))
1247+
{
1248+
// For backwards compability we allow omitting some empty arms that we ideally shouldn't.
1249+
place_validity = place_validity.allow_omitting_side_effecting_arms();
1250+
}
12461251

12471252
// Analyze the constructors present in this column.
12481253
let ctors = matrix.heads().map(|p| p.ctor());
1249-
let split_set = ConstructorSet::for_ty(cx, ty).split(pcx, ctors);
1254+
let split_set = ctors_for_ty.split(pcx, ctors);
1255+
1256+
// Decide what constructors to report.
12501257
let all_missing = split_set.present.is_empty();
12511258

12521259
// 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
@@ -1012,6 +1012,7 @@ symbols! {
10121012
min_const_fn,
10131013
min_const_generics,
10141014
min_const_unsafe_fn,
1015+
min_exhaustive_patterns,
10151016
min_specialization,
10161017
min_type_alias_impl_trait,
10171018
minnumf32,

0 commit comments

Comments
 (0)