@@ -560,13 +560,6 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
560
560
}
561
561
}
562
562
563
- fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
564
- match ty.kind {
565
- ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(),
566
- _ => false,
567
- }
568
- }
569
-
570
563
fn is_local(&self, ty: Ty<'tcx>) -> bool {
571
564
match ty.kind {
572
565
ty::Adt(adt_def, ..) => adt_def.did.is_local(),
@@ -1133,7 +1126,7 @@ fn all_constructors<'a, 'tcx>(
1133
1126
pcx: PatCtxt<'tcx>,
1134
1127
) -> Vec<Constructor<'tcx>> {
1135
1128
debug!("all_constructors({:?})", pcx.ty);
1136
- let ctors = match pcx.ty.kind {
1129
+ match pcx.ty.kind {
1137
1130
ty::Bool => [true, false]
1138
1131
.iter()
1139
1132
.map(|&b| ConstantValue(ty::Const::from_bool(cx.tcx, b), pcx.span))
@@ -1150,17 +1143,49 @@ fn all_constructors<'a, 'tcx>(
1150
1143
vec![VarLenSlice(0, 0)]
1151
1144
}
1152
1145
}
1153
- ty::Adt(def, substs) if def.is_enum() => def
1154
- .variants
1155
- .iter()
1156
- .filter(|v| {
1157
- !cx.tcx.features().exhaustive_patterns
1158
- || !v
1159
- .uninhabited_from(cx.tcx, substs, def.adt_kind())
1160
- .contains(cx.tcx, cx.module)
1161
- })
1162
- .map(|v| Variant(v.def_id))
1163
- .collect(),
1146
+ ty::Adt(def, substs) if def.is_enum() => {
1147
+ let ctors: Vec<_> = def
1148
+ .variants
1149
+ .iter()
1150
+ .filter(|v| {
1151
+ !cx.tcx.features().exhaustive_patterns
1152
+ || !v
1153
+ .uninhabited_from(cx.tcx, substs, def.adt_kind())
1154
+ .contains(cx.tcx, cx.module)
1155
+ })
1156
+ .map(|v| Variant(v.def_id))
1157
+ .collect();
1158
+
1159
+ // If our scrutinee is *privately* an empty enum, we must treat it as though it had an
1160
+ // "unknown" constructor (in that case, all other patterns obviously can't be variants)
1161
+ // to avoid exposing its emptyness. See the `match_privately_empty` test for details.
1162
+ // FIXME: currently the only way I know of something can be a privately-empty enum is
1163
+ // when the exhaustive_patterns feature flag is not present, so this is only needed for
1164
+ // that case.
1165
+ let is_privately_empty = ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
1166
+ // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
1167
+ // additionnal "unknown" constructor.
1168
+ let is_declared_nonexhaustive =
1169
+ def.is_variant_list_non_exhaustive() && !cx.is_local(pcx.ty);
1170
+
1171
+ if is_privately_empty || is_declared_nonexhaustive {
1172
+ // There is no point in enumerating all possible variants, because the user can't
1173
+ // actually match against them themselves. So we return only the fictitious
1174
+ // constructor.
1175
+ // E.g., in an example like:
1176
+ // ```
1177
+ // let err: io::ErrorKind = ...;
1178
+ // match err {
1179
+ // io::ErrorKind::NotFound => {},
1180
+ // }
1181
+ // ```
1182
+ // we don't want to show every possible IO error, but instead have only `_` as the
1183
+ // witness.
1184
+ vec![NonExhaustive]
1185
+ } else {
1186
+ ctors
1187
+ }
1188
+ }
1164
1189
ty::Char => {
1165
1190
vec![
1166
1191
// The valid Unicode Scalar Value ranges.
@@ -1180,6 +1205,15 @@ fn all_constructors<'a, 'tcx>(
1180
1205
),
1181
1206
]
1182
1207
}
1208
+ ty::Int(_) | ty::Uint(_)
1209
+ if pcx.ty.is_ptr_sized_integral()
1210
+ && !cx.tcx.features().precise_pointer_size_matching =>
1211
+ {
1212
+ // `usize`/`isize` are not allowed to be matched exhaustively unless the
1213
+ // `precise_pointer_size_matching` feature is enabled. So we treat those types like
1214
+ // `#[non_exhaustive]` enums by returning a special unmatcheable constructor.
1215
+ vec![NonExhaustive]
1216
+ }
1183
1217
ty::Int(ity) => {
1184
1218
let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128;
1185
1219
let min = 1u128 << (bits - 1);
@@ -1198,38 +1232,7 @@ fn all_constructors<'a, 'tcx>(
1198
1232
vec![Single]
1199
1233
}
1200
1234
}
1201
- };
1202
-
1203
- // FIXME: currently the only way I know of something can
1204
- // be a privately-empty enum is when the exhaustive_patterns
1205
- // feature flag is not present, so this is only
1206
- // needed for that case.
1207
- let is_privately_empty = ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
1208
- let is_declared_nonexhaustive = cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty);
1209
- let is_non_exhaustive = is_privately_empty
1210
- || is_declared_nonexhaustive
1211
- || (pcx.ty.is_ptr_sized_integral() && !cx.tcx.features().precise_pointer_size_matching);
1212
- if is_non_exhaustive {
1213
- // If our scrutinee is *privately* an empty enum, we must treat it as though it had an
1214
- // "unknown" constructor (in that case, all other patterns obviously can't be variants) to
1215
- // avoid exposing its emptyness. See the `match_privately_empty` test for details.
1216
- //
1217
- // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an additionnal
1218
- // "unknown" constructor. However there is no point in enumerating all possible variants,
1219
- // because the user can't actually match against them themselves. So we return only the
1220
- // fictitious constructor.
1221
- // E.g., in an example like:
1222
- // ```
1223
- // let err: io::ErrorKind = ...;
1224
- // match err {
1225
- // io::ErrorKind::NotFound => {},
1226
- // }
1227
- // ```
1228
- // we don't want to show every possible IO error, but instead have only `_` as the witness.
1229
- return vec![NonExhaustive];
1230
- }
1231
-
1232
- ctors
1235
+ }
1233
1236
}
1234
1237
1235
1238
/// An inclusive interval, used for precise integer exhaustiveness checking.
0 commit comments