about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNadrieril <nadrieril+git@gmail.com>2019-11-30 14:36:41 +0000
committerNadrieril <nadrieril+git@gmail.com>2019-12-04 16:43:20 +0000
commit86fb2ef2e1ee14741fdb38e15f8d530d863c2628 (patch)
treeaa4692f771734ddb2dbd608e87f21cf0d27a3423
parent7fa046534e944193cc47b795b9396a7fcf411d9f (diff)
downloadrust-86fb2ef2e1ee14741fdb38e15f8d530d863c2628.tar.gz
rust-86fb2ef2e1ee14741fdb38e15f8d530d863c2628.zip
Clarify handling of `exhaustive_patterns` in `all_constructors`
This is logically equivalent to the previous code.
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs70
1 files changed, 39 insertions, 31 deletions
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 37a9381271a..8ee942e53e0 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -1235,43 +1235,51 @@ fn all_constructors<'a, 'tcx>(
             vec![Slice(Slice { array_len: None, kind })]
         }
         ty::Adt(def, substs) if def.is_enum() => {
-            let ctors: Vec<_> = def
-                .variants
-                .iter()
-                .filter(|v| {
-                    !cx.tcx.features().exhaustive_patterns
-                        || !v
-                            .uninhabited_from(cx.tcx, substs, def.adt_kind())
+            let ctors: Vec<_> = if cx.tcx.features().exhaustive_patterns {
+                // If `exhaustive_patterns` is enabled, we exclude variants known to be
+                // uninhabited.
+                def.variants
+                    .iter()
+                    .filter(|v| {
+                        !v.uninhabited_from(cx.tcx, substs, def.adt_kind())
                             .contains(cx.tcx, cx.module)
-                })
-                .map(|v| Variant(v.def_id))
-                .collect();
-
-            // If our scrutinee is *privately* an empty enum, we must treat it as though it had an
-            // "unknown" constructor (in that case, all other patterns obviously can't be variants)
-            // to avoid exposing its emptyness. See the `match_privately_empty` test for details.
-            // FIXME: currently the only way I know of something can be a privately-empty enum is
-            // when the exhaustive_patterns feature flag is not present, so this is only needed for
-            // that case.
-            let is_privately_empty = ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
+                    })
+                    .map(|v| Variant(v.def_id))
+                    .collect()
+            } else {
+                def.variants.iter().map(|v| Variant(v.def_id)).collect()
+            };
+
             // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
-            // additionnal "unknown" constructor.
+            // additional "unknown" constructor.
+            // There is no point in enumerating all possible variants, because the user can't
+            // actually match against them all themselves. So we always return only the fictitious
+            // constructor.
+            // E.g., in an example like:
+            // ```
+            //     let err: io::ErrorKind = ...;
+            //     match err {
+            //         io::ErrorKind::NotFound => {},
+            //     }
+            // ```
+            // we don't want to show every possible IO error, but instead have only `_` as the
+            // witness.
             let is_declared_nonexhaustive =
                 def.is_variant_list_non_exhaustive() && !cx.is_local(pcx.ty);
 
+            // If our scrutinee is *privately* an empty enum, we must treat it as though it had
+            // an "unknown" constructor (in that case, all other patterns obviously can't be
+            // variants) to avoid exposing its emptyness. See the `match_privately_empty` test
+            // for details.
+            let is_privately_empty = if cx.tcx.features().exhaustive_patterns {
+                // This cannot happen because we have already filtered out uninhabited variants.
+                false
+            } else {
+                // FIXME: this is fishy
+                def.variants.is_empty()
+            };
+
             if is_privately_empty || is_declared_nonexhaustive {
-                // There is no point in enumerating all possible variants, because the user can't
-                // actually match against them themselves. So we return only the fictitious
-                // constructor.
-                // E.g., in an example like:
-                // ```
-                //     let err: io::ErrorKind = ...;
-                //     match err {
-                //         io::ErrorKind::NotFound => {},
-                //     }
-                // ```
-                // we don't want to show every possible IO error, but instead have only `_` as the
-                // witness.
                 vec![NonExhaustive]
             } else {
                 ctors