Skip to content

Commit 6630df5

Browse files
committed
Clarify splitting by moving wildcard handling out of it
1 parent a0aba33 commit 6630df5

File tree

2 files changed

+27
-29
lines changed

2 files changed

+27
-29
lines changed

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

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -947,21 +947,16 @@ impl ConstructorSet {
947947
/// For this we first need to know about the full set of constructors for this type, which is
948948
/// represented by this `ConstructorSet`. We then construct two lists of constructors.
949949
///
950-
/// Formally, this returns two vecs `split` and `missing`, respecting the following constraints:
951-
/// - `split` covers the whole type
952-
/// - `split` is made of:
953-
/// - at most one wildcard (`Wildcard` or `Missing`)
954-
/// - non-wildcard constructors that are each covered by some non-wildcard constructor in `ctors`
955-
/// - together, the non-wildcard constructors in `split` cover all the non-wildcard
956-
/// constructor in `ctors`, including `Opaques`
950+
/// Formally, this returns two vecs `present` and `missing`, respecting the following constraints:
951+
/// - the union of `present` and `missing` covers the whole type
952+
/// - `present` and `missing` are disjoint
953+
/// - neither contains any wildcard
954+
/// - each constructor in `present` is covered by some non-wildcard constructor in `ctors`
955+
/// - together, the constructors in `present` cover all the non-wildcard constructor in `ctors`, including `Opaques`
957956
/// - non-wildcards in `ctors` do no cover anything in `missing`
958-
/// - if we replace the `Wildcard`/`Missing` in `split` with all of `missing`, this also
959-
/// covers the whole type
960-
/// - constructors in `split` and `missing` are split for the `ctors` list; in other words,
957+
/// - constructors in `present` and `missing` are split for the `ctors` list; in other words,
961958
/// they are either fully included in or disjoint from each constructor in `ctors`
962959
///
963-
/// Note in particular that wildcards in `ctors` are irrelevant; they do not change which
964-
/// constructors are present.
965960
/// FIXME(Nadrieril): examples?
966961
pub(super) fn split<'a, 'tcx>(
967962
&self,
@@ -975,14 +970,15 @@ impl ConstructorSet {
975970
'tcx: 'a,
976971
{
977972
let mut missing = Vec::new();
978-
let mut split = Vec::new();
973+
let mut present = Vec::new();
979974
// Constructors in `ctors`, except wildcards and opaques.
980975
let mut seen = Vec::new();
981976
for ctor in ctors.cloned() {
982977
match ctor {
978+
// Wildcards in `ctors` are irrelevant to splitting
983979
Wildcard => {}
984980
Constructor::Opaque(..) => {
985-
split.push(ctor);
981+
present.push(ctor);
986982
}
987983
_ => {
988984
seen.push(ctor);
@@ -994,7 +990,7 @@ impl ConstructorSet {
994990
if seen.is_empty() {
995991
missing.push(Single);
996992
} else {
997-
split.push(Single);
993+
present.push(Single);
998994
}
999995
}
1000996
ConstructorSet::Variants { variants, non_exhaustive } => {
@@ -1003,7 +999,7 @@ impl ConstructorSet {
1003999
for variant in variants {
10041000
let ctor = Variant(*variant);
10051001
if seen_set.contains(&variant) {
1006-
split.push(ctor);
1002+
present.push(ctor);
10071003
} else if ctor.is_doc_hidden_variant(pcx) || ctor.is_unstable_variant(pcx) {
10081004
// We don't want to mention any variants that are `doc(hidden)` or
10091005
// behind an unstable feature gate.
@@ -1029,7 +1025,7 @@ impl ConstructorSet {
10291025
let ctor = IntRange(splitted_range);
10301026
match seen {
10311027
Presence::Unseen => missing.push(ctor),
1032-
Presence::Seen => split.push(ctor),
1028+
Presence::Seen => present.push(ctor),
10331029
}
10341030
}
10351031
if *non_exhaustive {
@@ -1042,7 +1038,7 @@ impl ConstructorSet {
10421038
let ctor = Slice(splitted_slice);
10431039
match seen {
10441040
Presence::Unseen => missing.push(ctor),
1045-
Presence::Seen => split.push(ctor),
1041+
Presence::Seen => present.push(ctor),
10461042
}
10471043
}
10481044
}
@@ -1052,13 +1048,13 @@ impl ConstructorSet {
10521048
if seen.is_empty() {
10531049
missing.push(slice);
10541050
} else {
1055-
split.push(slice);
1051+
present.push(slice);
10561052
}
10571053
}
10581054
ConstructorSet::Unlistable => {
10591055
// Since we can't list constructors, we take the ones in the matrix. This might list
10601056
// some constructors several times but there's not much we can do.
1061-
split.extend(seen);
1057+
present.extend(seen);
10621058
missing.push(NonExhaustive);
10631059
}
10641060
// If `exhaustive_patterns` is disabled and our scrutinee is an empty type, we cannot
@@ -1071,14 +1067,7 @@ impl ConstructorSet {
10711067
}
10721068
ConstructorSet::Uninhabited => {}
10731069
}
1074-
if !missing.is_empty() {
1075-
if split.is_empty() {
1076-
split.push(Wildcard);
1077-
} else {
1078-
split.push(Missing);
1079-
}
1080-
}
1081-
(split, missing)
1070+
(present, missing)
10821071
}
10831072
}
10841073

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -786,8 +786,17 @@ fn compute_usefulness<'p, 'tcx>(
786786
let pcx = &PatCtxt { cx, ty };
787787

788788
let ctor_set = ConstructorSet::new(pcx);
789-
let (split_ctors, missing_ctors) =
789+
let (mut split_ctors, missing_ctors) =
790790
ctor_set.split(pcx, matrix.heads().map(|p| p.ctor()), is_top_level);
791+
792+
// We want to iterate over a full set of constructors, so if any is missing we add a wildcard.
793+
if !missing_ctors.is_empty() {
794+
if split_ctors.is_empty() {
795+
split_ctors.push(Constructor::Wildcard);
796+
} else {
797+
split_ctors.push(Constructor::Missing);
798+
}
799+
}
791800
// At the top level, we prefer to list all constructors when `_` could be reported as missing.
792801
let report_when_all_missing =
793802
is_top_level && !matches!(ctor_set, ConstructorSet::Integers { .. });

0 commit comments

Comments
 (0)