|
222 | 222 | /// wildcards. Thus this mostly extends the original algorithm to ranges and variable-length
|
223 | 223 | /// slices, while removing the special-casing of the wildcard pattern. We also additionally
|
224 | 224 | /// support uninhabited types.
|
| 225 | +/// |
| 226 | +/// |
| 227 | +/// # Handling of missing constructors (MISSING-CTOR) |
| 228 | +/// |
| 229 | +/// This algorithm can be seen to essentially explore the full decision tree of patterns, except in |
| 230 | +/// the case where it "takes a shortcut" to find a "missing" constructor - that is, a constructor |
| 231 | +/// that is not covered by any of the non-wildcard patterns. |
| 232 | +/// |
| 233 | +/// For example, in the following case: |
| 234 | +/// ```rust |
| 235 | +/// match x { |
| 236 | +/// (_, false) => {} |
| 237 | +/// (None, false) => {} |
| 238 | +/// } |
| 239 | +/// ``` |
| 240 | +/// |
| 241 | +/// The algorithm proceeds as follows: |
| 242 | +/// ``` |
| 243 | +/// M = [ [(_, false)], |
| 244 | +/// [(None, false)]] |
| 245 | +/// p = [_] |
| 246 | +/// -- expand tuple (ctor = Simple) |
| 247 | +/// M = [ [_, false], |
| 248 | +/// [None, false]] |
| 249 | +/// p = [_, _] |
| 250 | +/// -- `Some(_)` is a missing ctor, dropping all the non-wildcard arms |
| 251 | +/// M = [ [false]] |
| 252 | +/// p = [_] |
| 253 | +/// -- `true` is a possible witness |
| 254 | +/// M = [] |
| 255 | +/// p = [] |
| 256 | +/// return "[]" |
| 257 | +/// return "[true]" |
| 258 | +/// return "[Some(_), true]" |
| 259 | +/// return "[(Some(_), true)]" |
| 260 | +/// ``` |
| 261 | +/// |
| 262 | +/// Once it finds that `Some(_)` is a missing constructor, it does not need to look any further - |
| 263 | +/// any witness using a non-missing constructor can be transformed to a witness using a missing |
| 264 | +/// constructor - and therefore it does not try to look for witnesses involving the other |
| 265 | +/// constructors - in this case, the `(None, true)` witness (which can be "transformed" to |
| 266 | +/// `(Some(_), true)`). |
| 267 | +/// |
| 268 | +/// In the code, missing constructors are represented by the `Wildcard` and `MissingConstructors` |
| 269 | +/// variants of `Constructor`, with the difference between them being down to error reporting: |
| 270 | +/// `MissingConstructors` "remembers" the set of constructors it contains for error reporting (so |
| 271 | +/// we can show the `... not covered` error message), while `Wildcard` doesn't. |
| 272 | +/// |
| 273 | +/// Therefore, `Wildcard` is used in cases where the exact constructor doesn't matter - either |
| 274 | +/// where the head column of the matrix contains only wildcards (and therefore, *every* constructor |
| 275 | +/// will work) or when the enum is `#[non_exhaustive]`, and therefore from a user POV there can |
| 276 | +/// always assumed to be an "fresh" constructor that will be useful for the witness. |
| 277 | +/// `MissingConstructors` is used in the other cases. |
225 | 278 | use self::Constructor::*;
|
226 | 279 | use self::Usefulness::*;
|
227 | 280 | use self::WitnessPreference::*;
|
@@ -1821,6 +1874,7 @@ fn pat_constructors<'tcx>(
|
1821 | 1874 | Variant(adt_def.variants[variant_index].def_id)
|
1822 | 1875 | }
|
1823 | 1876 | PatKind::Constant { value } => {
|
| 1877 | + // FIXME: consts are not handled properly; see #65413 |
1824 | 1878 | if let Some(range) = IntRange::from_const(tcx, param_env, value) {
|
1825 | 1879 | IntRange(range)
|
1826 | 1880 | } else {
|
@@ -2005,12 +2059,9 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
|
2005 | 2059 | }
|
2006 | 2060 |
|
2007 | 2061 | if let Wildcard | MissingConstructors(_) = constructor {
|
2008 |
| - // If `constructor` is `Wildcard`: either there were only wildcards in the first component |
2009 |
| - // of the matrix, or we are in a special non_exhaustive case where we pretend the type has |
2010 |
| - // an extra `_` constructor to prevent exhaustive matching. In both cases, all non-wildcard |
2011 |
| - // constructors should be discarded. |
2012 |
| - // If `constructor` is `MissingConstructors(_)`: by the invariant of MissingConstructors, |
2013 |
| - // we know that all non-wildcard constructors should be discarded. |
| 2062 | + // Both those cases capture a set of constructors that are not present in the head of |
| 2063 | + // current matrix. This means that we discard all non-wildcard constructors. |
| 2064 | + // See (MISSING-CTOR) at the top of the file for more details. |
2014 | 2065 | return match *pat.kind {
|
2015 | 2066 | PatKind::Binding { .. } | PatKind::Wild => Some(PatStack::empty()),
|
2016 | 2067 | _ => None,
|
@@ -2057,7 +2108,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
|
2057 | 2108 | (data, Size::from_bytes(start as u64), (end - start) as u64, t)
|
2058 | 2109 | }
|
2059 | 2110 | ConstValue::ByRef { .. } => {
|
2060 |
| - // FIXME(oli-obk): implement `deref` for `ConstValue` |
| 2111 | + // FIXME(oli-obk): implement `deref` for `ConstValue`. See #53708 |
2061 | 2112 | return None;
|
2062 | 2113 | }
|
2063 | 2114 | _ => span_bug!(
|
|
0 commit comments