Skip to content

Commit 86fb2ef

Browse files
committed
Clarify handling of exhaustive_patterns in all_constructors
This is logically equivalent to the previous code.
1 parent 7fa0465 commit 86fb2ef

File tree

1 file changed

+39
-31
lines changed

1 file changed

+39
-31
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,43 +1235,51 @@ fn all_constructors<'a, 'tcx>(
12351235
vec![Slice(Slice { array_len: None, kind })]
12361236
}
12371237
ty::Adt(def, substs) if def.is_enum() => {
1238-
let ctors: Vec<_> = def
1239-
.variants
1240-
.iter()
1241-
.filter(|v| {
1242-
!cx.tcx.features().exhaustive_patterns
1243-
|| !v
1244-
.uninhabited_from(cx.tcx, substs, def.adt_kind())
1238+
let ctors: Vec<_> = if cx.tcx.features().exhaustive_patterns {
1239+
// If `exhaustive_patterns` is enabled, we exclude variants known to be
1240+
// uninhabited.
1241+
def.variants
1242+
.iter()
1243+
.filter(|v| {
1244+
!v.uninhabited_from(cx.tcx, substs, def.adt_kind())
12451245
.contains(cx.tcx, cx.module)
1246-
})
1247-
.map(|v| Variant(v.def_id))
1248-
.collect();
1249-
1250-
// If our scrutinee is *privately* an empty enum, we must treat it as though it had an
1251-
// "unknown" constructor (in that case, all other patterns obviously can't be variants)
1252-
// to avoid exposing its emptyness. See the `match_privately_empty` test for details.
1253-
// FIXME: currently the only way I know of something can be a privately-empty enum is
1254-
// when the exhaustive_patterns feature flag is not present, so this is only needed for
1255-
// that case.
1256-
let is_privately_empty = ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
1246+
})
1247+
.map(|v| Variant(v.def_id))
1248+
.collect()
1249+
} else {
1250+
def.variants.iter().map(|v| Variant(v.def_id)).collect()
1251+
};
1252+
12571253
// If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
1258-
// additionnal "unknown" constructor.
1254+
// additional "unknown" constructor.
1255+
// There is no point in enumerating all possible variants, because the user can't
1256+
// actually match against them all themselves. So we always return only the fictitious
1257+
// constructor.
1258+
// E.g., in an example like:
1259+
// ```
1260+
// let err: io::ErrorKind = ...;
1261+
// match err {
1262+
// io::ErrorKind::NotFound => {},
1263+
// }
1264+
// ```
1265+
// we don't want to show every possible IO error, but instead have only `_` as the
1266+
// witness.
12591267
let is_declared_nonexhaustive =
12601268
def.is_variant_list_non_exhaustive() && !cx.is_local(pcx.ty);
12611269

1270+
// If our scrutinee is *privately* an empty enum, we must treat it as though it had
1271+
// an "unknown" constructor (in that case, all other patterns obviously can't be
1272+
// variants) to avoid exposing its emptyness. See the `match_privately_empty` test
1273+
// for details.
1274+
let is_privately_empty = if cx.tcx.features().exhaustive_patterns {
1275+
// This cannot happen because we have already filtered out uninhabited variants.
1276+
false
1277+
} else {
1278+
// FIXME: this is fishy
1279+
def.variants.is_empty()
1280+
};
1281+
12621282
if is_privately_empty || is_declared_nonexhaustive {
1263-
// There is no point in enumerating all possible variants, because the user can't
1264-
// actually match against them themselves. So we return only the fictitious
1265-
// constructor.
1266-
// E.g., in an example like:
1267-
// ```
1268-
// let err: io::ErrorKind = ...;
1269-
// match err {
1270-
// io::ErrorKind::NotFound => {},
1271-
// }
1272-
// ```
1273-
// we don't want to show every possible IO error, but instead have only `_` as the
1274-
// witness.
12751283
vec![NonExhaustive]
12761284
} else {
12771285
ctors

0 commit comments

Comments
 (0)