Skip to content

Commit 8710b20

Browse files
committed
Make all the empty pattern decisions in usefulness
1 parent b877ef2 commit 8710b20

File tree

3 files changed

+19
-20
lines changed

3 files changed

+19
-20
lines changed

compiler/rustc_pattern_analysis/src/constructor.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -858,12 +858,14 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
858858
/// any) are missing; 2/ split constructors to handle non-trivial intersections e.g. on ranges
859859
/// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation
860860
/// and its invariants.
861-
#[instrument(level = "debug", skip(self, pcx, ctors), ret)]
861+
#[instrument(level = "debug", skip(self, ctors), ret)]
862862
pub(crate) fn split<'a>(
863863
&self,
864-
pcx: &PlaceCtxt<'a, '_, Cx>,
865864
ctors: impl Iterator<Item = &'a Constructor<Cx>> + Clone,
866-
) -> SplitConstructorSet<Cx> {
865+
) -> SplitConstructorSet<Cx>
866+
where
867+
Cx: 'a,
868+
{
867869
let mut present: SmallVec<[_; 1]> = SmallVec::new();
868870
// Empty constructors found missing.
869871
let mut missing_empty = Vec::new();
@@ -1003,17 +1005,6 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
10031005
}
10041006
}
10051007

1006-
// We have now grouped all the constructors into 3 buckets: present, missing, missing_empty.
1007-
// In the absence of the `exhaustive_patterns` feature however, we don't count nested empty
1008-
// types as empty. Only non-nested `!` or `enum Foo {}` are considered empty.
1009-
if !pcx.mcx.tycx.is_exhaustive_patterns_feature_on()
1010-
&& !(pcx.is_scrutinee && matches!(self, Self::NoConstructors))
1011-
{
1012-
// Treat all missing constructors as nonempty.
1013-
// This clears `missing_empty`.
1014-
missing.append(&mut missing_empty);
1015-
}
1016-
10171008
SplitConstructorSet { present, missing, missing_empty }
10181009
}
10191010
}

compiler/rustc_pattern_analysis/src/lints.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
6565
) -> Result<SplitConstructorSet<'p, 'tcx>, ErrorGuaranteed> {
6666
let column_ctors = self.patterns.iter().map(|p| p.ctor());
6767
let ctors_for_ty = &pcx.ctors_for_ty()?;
68-
Ok(ctors_for_ty.split(pcx, column_ctors))
68+
Ok(ctors_for_ty.split(column_ctors))
6969
}
7070

7171
fn iter(&self) -> impl Iterator<Item = &'p DeconstructedPat<'p, 'tcx>> + Captures<'_> {

compiler/rustc_pattern_analysis/src/usefulness.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -736,15 +736,13 @@ pub(crate) struct PlaceCtxt<'a, 'p, Cx: TypeCx> {
736736
pub(crate) mcx: MatchCtxt<'a, 'p, Cx>,
737737
/// Type of the place under investigation.
738738
pub(crate) ty: Cx::Ty,
739-
/// Whether the place is the original scrutinee place, as opposed to a subplace of it.
740-
pub(crate) is_scrutinee: bool,
741739
}
742740

743741
impl<'a, 'p, Cx: TypeCx> PlaceCtxt<'a, 'p, Cx> {
744742
/// A `PlaceCtxt` when code other than `is_useful` needs one.
745743
#[cfg_attr(not(feature = "rustc"), allow(dead_code))]
746744
pub(crate) fn new_dummy(mcx: MatchCtxt<'a, 'p, Cx>, ty: Cx::Ty) -> Self {
747-
PlaceCtxt { mcx, ty, is_scrutinee: false }
745+
PlaceCtxt { mcx, ty }
748746
}
749747

750748
pub(crate) fn ctor_arity(&self, ctor: &Constructor<Cx>) -> usize {
@@ -1355,7 +1353,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
13551353
};
13561354

13571355
debug!("ty: {ty:?}");
1358-
let pcx = &PlaceCtxt { mcx, ty, is_scrutinee: is_top_level };
1356+
let pcx = &PlaceCtxt { mcx, ty };
13591357

13601358
// Whether the place/column we are inspecting is known to contain valid data.
13611359
let place_validity = matrix.place_validity[0];
@@ -1364,7 +1362,17 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
13641362
let ctors = matrix.heads().map(|p| p.ctor());
13651363
let ctors_for_ty = pcx.ctors_for_ty()?;
13661364
let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); // For diagnostics.
1367-
let split_set = ctors_for_ty.split(pcx, ctors);
1365+
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+
{
1372+
// Treat all missing constructors as nonempty.
1373+
// This clears `missing_empty`.
1374+
split_set.missing.append(&mut split_set.missing_empty);
1375+
}
13681376
let all_missing = split_set.present.is_empty();
13691377

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

0 commit comments

Comments
 (0)