rustc_pattern_analysis/
rustc.rs

1use std::cell::Cell;
2use std::fmt;
3use std::iter::once;
4
5use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx};
6use rustc_arena::DroplessArena;
7use rustc_hir::HirId;
8use rustc_hir::def_id::DefId;
9use rustc_index::{Idx, IndexVec};
10use rustc_middle::middle::stability::EvalResult;
11use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary};
12use rustc_middle::ty::layout::IntegerExt;
13use rustc_middle::ty::{
14    self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef,
15};
16use rustc_middle::{bug, span_bug};
17use rustc_session::lint;
18use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
19
20use crate::constructor::Constructor::*;
21use crate::constructor::{
22    IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility,
23};
24use crate::lints::lint_nonexhaustive_missing_variants;
25use crate::pat_column::PatternColumn;
26use crate::rustc::print::EnumInfo;
27use crate::usefulness::{PlaceValidity, compute_match_usefulness};
28use crate::{PatCx, PrivateUninhabitedField, errors};
29
30mod print;
31
32// Re-export rustc-specific versions of all these types.
33pub type Constructor<'p, 'tcx> = crate::constructor::Constructor<RustcPatCtxt<'p, 'tcx>>;
34pub type ConstructorSet<'p, 'tcx> = crate::constructor::ConstructorSet<RustcPatCtxt<'p, 'tcx>>;
35pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat<RustcPatCtxt<'p, 'tcx>>;
36pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcPatCtxt<'p, 'tcx>>;
37pub type RedundancyExplanation<'p, 'tcx> =
38    crate::usefulness::RedundancyExplanation<'p, RustcPatCtxt<'p, 'tcx>>;
39pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcPatCtxt<'p, 'tcx>>;
40pub type UsefulnessReport<'p, 'tcx> =
41    crate::usefulness::UsefulnessReport<'p, RustcPatCtxt<'p, 'tcx>>;
42pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat<RustcPatCtxt<'p, 'tcx>>;
43
44/// A type which has gone through `cx.reveal_opaque_ty`, i.e. if it was opaque it was replaced by
45/// the hidden type if allowed in the current body. This ensures we consistently inspect the hidden
46/// types when we should.
47///
48/// Use `.inner()` or deref to get to the `Ty<'tcx>`.
49#[repr(transparent)]
50#[derive(Clone, Copy, PartialEq, Eq, Hash)]
51pub struct RevealedTy<'tcx>(Ty<'tcx>);
52
53impl<'tcx> fmt::Display for RevealedTy<'tcx> {
54    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
55        self.0.fmt(fmt)
56    }
57}
58
59impl<'tcx> fmt::Debug for RevealedTy<'tcx> {
60    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
61        self.0.fmt(fmt)
62    }
63}
64
65impl<'tcx> std::ops::Deref for RevealedTy<'tcx> {
66    type Target = Ty<'tcx>;
67    fn deref(&self) -> &Self::Target {
68        &self.0
69    }
70}
71
72impl<'tcx> RevealedTy<'tcx> {
73    pub fn inner(self) -> Ty<'tcx> {
74        self.0
75    }
76}
77
78#[derive(Clone)]
79pub struct RustcPatCtxt<'p, 'tcx: 'p> {
80    pub tcx: TyCtxt<'tcx>,
81    pub typeck_results: &'tcx ty::TypeckResults<'tcx>,
82    /// The module in which the match occurs. This is necessary for
83    /// checking inhabited-ness of types because whether a type is (visibly)
84    /// inhabited can depend on whether it was defined in the current module or
85    /// not. E.g., `struct Foo { _private: ! }` cannot be seen to be empty
86    /// outside its module and should not be matchable with an empty match statement.
87    pub module: DefId,
88    pub typing_env: ty::TypingEnv<'tcx>,
89    /// To allocate the result of `self.ctor_sub_tys()`
90    pub dropless_arena: &'p DroplessArena,
91    /// Lint level at the match.
92    pub match_lint_level: HirId,
93    /// The span of the whole match, if applicable.
94    pub whole_match_span: Option<Span>,
95    /// Span of the scrutinee.
96    pub scrut_span: Span,
97    /// Only produce `NON_EXHAUSTIVE_OMITTED_PATTERNS` lint on refutable patterns.
98    pub refutable: bool,
99    /// Whether the data at the scrutinee is known to be valid. This is false if the scrutinee comes
100    /// from a union field, a pointer deref, or a reference deref (pending opsem decisions).
101    pub known_valid_scrutinee: bool,
102    pub internal_state: RustcPatCtxtState,
103}
104
105/// Private fields of [`RustcPatCtxt`], separated out to permit record initialization syntax.
106#[derive(Clone, Default)]
107pub struct RustcPatCtxtState {
108    /// Has a deref pattern been lowered? This is initialized to `false` and is updated by
109    /// [`RustcPatCtxt::lower_pat`] in order to avoid performing deref-pattern-specific validation
110    /// for everything containing patterns.
111    has_lowered_deref_pat: Cell<bool>,
112}
113
114impl<'p, 'tcx: 'p> fmt::Debug for RustcPatCtxt<'p, 'tcx> {
115    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116        f.debug_struct("RustcPatCtxt").finish()
117    }
118}
119
120impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
121    /// Type inference occasionally gives us opaque types in places where corresponding patterns
122    /// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited
123    /// types, we use the corresponding hidden type if possible.
124    // FIXME(#132279): This will be unnecessary once we have a TypingMode which supports revealing
125    // opaque types defined in a body.
126    #[inline]
127    pub fn reveal_opaque_ty(&self, ty: Ty<'tcx>) -> RevealedTy<'tcx> {
128        fn reveal_inner<'tcx>(cx: &RustcPatCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> RevealedTy<'tcx> {
129            let ty::Alias(ty::Opaque, alias_ty) = *ty.kind() else { bug!() };
130            if let Some(local_def_id) = alias_ty.def_id.as_local() {
131                let key = ty::OpaqueTypeKey { def_id: local_def_id, args: alias_ty.args };
132                if let Some(ty) = cx.reveal_opaque_key(key) {
133                    return RevealedTy(ty);
134                }
135            }
136            RevealedTy(ty)
137        }
138        if let ty::Alias(ty::Opaque, _) = ty.kind() {
139            reveal_inner(self, ty)
140        } else {
141            RevealedTy(ty)
142        }
143    }
144
145    /// Returns the hidden type corresponding to this key if the body under analysis is allowed to
146    /// know it.
147    fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>> {
148        self.typeck_results
149            .hidden_types
150            .get(&key.def_id)
151            .map(|x| x.ty.instantiate(self.tcx, key.args))
152    }
153    // This can take a non-revealed `Ty` because it reveals opaques itself.
154    pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
155        !ty.inhabited_predicate(self.tcx).apply_revealing_opaque(
156            self.tcx,
157            self.typing_env,
158            self.module,
159            &|key| self.reveal_opaque_key(key),
160        )
161    }
162
163    /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
164    pub fn is_foreign_non_exhaustive_enum(&self, ty: RevealedTy<'tcx>) -> bool {
165        match ty.kind() {
166            ty::Adt(def, ..) => def.variant_list_has_applicable_non_exhaustive(),
167            _ => false,
168        }
169    }
170
171    /// Whether the range denotes the fictitious values before `isize::MIN` or after
172    /// `usize::MAX`/`isize::MAX` (see doc of [`IntRange::split`] for why these exist).
173    pub fn is_range_beyond_boundaries(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> bool {
174        ty.is_ptr_sized_integral() && {
175            // The two invalid ranges are `NegInfinity..isize::MIN` (represented as
176            // `NegInfinity..0`), and `{u,i}size::MAX+1..PosInfinity`. `hoist_pat_range_bdy`
177            // converts `MAX+1` to `PosInfinity`, and we couldn't have `PosInfinity` in `range.lo`
178            // otherwise.
179            let lo = self.hoist_pat_range_bdy(range.lo, ty);
180            matches!(lo, PatRangeBoundary::PosInfinity)
181                || matches!(range.hi, MaybeInfiniteInt::Finite(0))
182        }
183    }
184
185    pub(crate) fn variant_sub_tys(
186        &self,
187        ty: RevealedTy<'tcx>,
188        variant: &'tcx VariantDef,
189    ) -> impl Iterator<Item = (&'tcx FieldDef, RevealedTy<'tcx>)> {
190        let ty::Adt(_, args) = ty.kind() else { bug!() };
191        variant.fields.iter().map(move |field| {
192            let ty = field.ty(self.tcx, args);
193            // `field.ty()` doesn't normalize after instantiating.
194            let ty =
195                self.tcx.try_normalize_erasing_regions(self.typing_env, ty).unwrap_or_else(|e| {
196                    self.tcx.dcx().span_delayed_bug(
197                        self.scrut_span,
198                        format!(
199                            "Failed to normalize {:?} in typing_env={:?} while getting variant sub tys for {ty:?}",
200                            e.get_type_for_failure(),
201                            self.typing_env,
202                        ),
203                    );
204                    ty
205                });
206            let ty = self.reveal_opaque_ty(ty);
207            (field, ty)
208        })
209    }
210
211    pub(crate) fn variant_index_for_adt(
212        ctor: &Constructor<'p, 'tcx>,
213        adt: ty::AdtDef<'tcx>,
214    ) -> VariantIdx {
215        match *ctor {
216            Variant(idx) => idx,
217            Struct | UnionField => {
218                assert!(!adt.is_enum());
219                FIRST_VARIANT
220            }
221            _ => bug!("bad constructor {:?} for adt {:?}", ctor, adt),
222        }
223    }
224
225    /// Returns the types of the fields for a given constructor. The result must have a length of
226    /// `ctor.arity()`.
227    pub(crate) fn ctor_sub_tys(
228        &self,
229        ctor: &Constructor<'p, 'tcx>,
230        ty: RevealedTy<'tcx>,
231    ) -> impl Iterator<Item = (RevealedTy<'tcx>, PrivateUninhabitedField)> + ExactSizeIterator {
232        fn reveal_and_alloc<'a, 'tcx>(
233            cx: &'a RustcPatCtxt<'_, 'tcx>,
234            iter: impl Iterator<Item = Ty<'tcx>>,
235        ) -> &'a [(RevealedTy<'tcx>, PrivateUninhabitedField)] {
236            cx.dropless_arena.alloc_from_iter(
237                iter.map(|ty| cx.reveal_opaque_ty(ty))
238                    .map(|ty| (ty, PrivateUninhabitedField(false))),
239            )
240        }
241        let cx = self;
242        let slice = match ctor {
243            Struct | Variant(_) | UnionField => match ty.kind() {
244                ty::Tuple(fs) => reveal_and_alloc(cx, fs.iter()),
245                ty::Adt(adt, _) => {
246                    let variant = &adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt));
247                    let tys = cx.variant_sub_tys(ty, variant).map(|(field, ty)| {
248                        let is_visible =
249                            adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
250                        let is_uninhabited = cx.is_uninhabited(*ty);
251                        let skip = is_uninhabited && !is_visible;
252                        (ty, PrivateUninhabitedField(skip))
253                    });
254                    cx.dropless_arena.alloc_from_iter(tys)
255                }
256                _ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"),
257            },
258            Ref => match ty.kind() {
259                ty::Ref(_, rty, _) => reveal_and_alloc(cx, once(*rty)),
260                _ => bug!("Unexpected type for `Ref` constructor: {ty:?}"),
261            },
262            Slice(slice) => match ty.builtin_index() {
263                Some(ty) => {
264                    let arity = slice.arity();
265                    reveal_and_alloc(cx, (0..arity).map(|_| ty))
266                }
267                None => bug!("bad slice pattern {:?} {:?}", ctor, ty),
268            },
269            DerefPattern(pointee_ty) => reveal_and_alloc(cx, once(pointee_ty.inner())),
270            Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
271            | F128Range(..) | Str(..) | Opaque(..) | Never | NonExhaustive | Hidden | Missing
272            | PrivateUninhabited | Wildcard => &[],
273            Or => {
274                bug!("called `Fields::wildcards` on an `Or` ctor")
275            }
276        };
277        slice.iter().copied()
278    }
279
280    /// The number of fields for this constructor.
281    pub(crate) fn ctor_arity(&self, ctor: &Constructor<'p, 'tcx>, ty: RevealedTy<'tcx>) -> usize {
282        match ctor {
283            Struct | Variant(_) | UnionField => match ty.kind() {
284                ty::Tuple(fs) => fs.len(),
285                ty::Adt(adt, ..) => {
286                    let variant_idx = RustcPatCtxt::variant_index_for_adt(&ctor, *adt);
287                    adt.variant(variant_idx).fields.len()
288                }
289                _ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"),
290            },
291            Ref | DerefPattern(_) => 1,
292            Slice(slice) => slice.arity(),
293            Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
294            | F128Range(..) | Str(..) | Opaque(..) | Never | NonExhaustive | Hidden | Missing
295            | PrivateUninhabited | Wildcard => 0,
296            Or => bug!("The `Or` constructor doesn't have a fixed arity"),
297        }
298    }
299
300    /// Creates a set that represents all the constructors of `ty`.
301    ///
302    /// See [`crate::constructor`] for considerations of emptiness.
303    pub fn ctors_for_ty(
304        &self,
305        ty: RevealedTy<'tcx>,
306    ) -> Result<ConstructorSet<'p, 'tcx>, ErrorGuaranteed> {
307        let cx = self;
308        let make_uint_range = |start, end| {
309            IntRange::from_range(
310                MaybeInfiniteInt::new_finite_uint(start),
311                MaybeInfiniteInt::new_finite_uint(end),
312                RangeEnd::Included,
313            )
314        };
315        // Abort on type error.
316        ty.error_reported()?;
317        // This determines the set of all possible constructors for the type `ty`. For numbers,
318        // arrays and slices we use ranges and variable-length slices when appropriate.
319        Ok(match ty.kind() {
320            ty::Bool => ConstructorSet::Bool,
321            ty::Char => {
322                // The valid Unicode Scalar Value ranges.
323                ConstructorSet::Integers {
324                    range_1: make_uint_range('\u{0000}' as u128, '\u{D7FF}' as u128),
325                    range_2: Some(make_uint_range('\u{E000}' as u128, '\u{10FFFF}' as u128)),
326                }
327            }
328            &ty::Int(ity) => {
329                let range = if ty.is_ptr_sized_integral() {
330                    // The min/max values of `isize` are not allowed to be observed.
331                    IntRange {
332                        lo: MaybeInfiniteInt::NegInfinity,
333                        hi: MaybeInfiniteInt::PosInfinity,
334                    }
335                } else {
336                    let size = Integer::from_int_ty(&cx.tcx, ity).size().bits();
337                    let min = 1u128 << (size - 1);
338                    let max = min - 1;
339                    let min = MaybeInfiniteInt::new_finite_int(min, size);
340                    let max = MaybeInfiniteInt::new_finite_int(max, size);
341                    IntRange::from_range(min, max, RangeEnd::Included)
342                };
343                ConstructorSet::Integers { range_1: range, range_2: None }
344            }
345            &ty::Uint(uty) => {
346                let range = if ty.is_ptr_sized_integral() {
347                    // The max value of `usize` is not allowed to be observed.
348                    let lo = MaybeInfiniteInt::new_finite_uint(0);
349                    IntRange { lo, hi: MaybeInfiniteInt::PosInfinity }
350                } else {
351                    let size = Integer::from_uint_ty(&cx.tcx, uty).size();
352                    let max = size.truncate(u128::MAX);
353                    make_uint_range(0, max)
354                };
355                ConstructorSet::Integers { range_1: range, range_2: None }
356            }
357            ty::Slice(sub_ty) => ConstructorSet::Slice {
358                array_len: None,
359                subtype_is_empty: cx.is_uninhabited(*sub_ty),
360            },
361            ty::Array(sub_ty, len) => {
362                // We treat arrays of a constant but unknown length like slices.
363                ConstructorSet::Slice {
364                    array_len: len.try_to_target_usize(cx.tcx).map(|l| l as usize),
365                    subtype_is_empty: cx.is_uninhabited(*sub_ty),
366                }
367            }
368            ty::Adt(def, args) if def.is_enum() => {
369                let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(ty);
370                if def.variants().is_empty() && !is_declared_nonexhaustive {
371                    ConstructorSet::NoConstructors
372                } else {
373                    let mut variants =
374                        IndexVec::from_elem(VariantVisibility::Visible, def.variants());
375                    for (idx, v) in def.variants().iter_enumerated() {
376                        let variant_def_id = def.variant(idx).def_id;
377                        // Visibly uninhabited variants.
378                        let is_inhabited = v
379                            .inhabited_predicate(cx.tcx, *def)
380                            .instantiate(cx.tcx, args)
381                            .apply_revealing_opaque(cx.tcx, cx.typing_env, cx.module, &|key| {
382                                cx.reveal_opaque_key(key)
383                            });
384                        // Variants that depend on a disabled unstable feature.
385                        let is_unstable = matches!(
386                            cx.tcx.eval_stability(variant_def_id, None, DUMMY_SP, None),
387                            EvalResult::Deny { .. }
388                        );
389                        // Foreign `#[doc(hidden)]` variants.
390                        let is_doc_hidden =
391                            cx.tcx.is_doc_hidden(variant_def_id) && !variant_def_id.is_local();
392                        let visibility = if !is_inhabited {
393                            // FIXME: handle empty+hidden
394                            VariantVisibility::Empty
395                        } else if is_unstable || is_doc_hidden {
396                            VariantVisibility::Hidden
397                        } else {
398                            VariantVisibility::Visible
399                        };
400                        variants[idx] = visibility;
401                    }
402
403                    ConstructorSet::Variants { variants, non_exhaustive: is_declared_nonexhaustive }
404                }
405            }
406            ty::Adt(def, _) if def.is_union() => ConstructorSet::Union,
407            ty::Adt(..) | ty::Tuple(..) => {
408                ConstructorSet::Struct { empty: cx.is_uninhabited(ty.inner()) }
409            }
410            ty::Ref(..) => ConstructorSet::Ref,
411            ty::Never => ConstructorSet::NoConstructors,
412            // This type is one for which we cannot list constructors, like `str` or `f64`.
413            // FIXME(Nadrieril): which of these are actually allowed?
414            ty::Float(_)
415            | ty::Str
416            | ty::Foreign(_)
417            | ty::RawPtr(_, _)
418            | ty::FnDef(_, _)
419            | ty::FnPtr(..)
420            | ty::Pat(_, _)
421            | ty::Dynamic(_, _)
422            | ty::Closure(..)
423            | ty::CoroutineClosure(..)
424            | ty::Coroutine(_, _)
425            | ty::UnsafeBinder(_)
426            | ty::Alias(_, _)
427            | ty::Param(_)
428            | ty::Error(_) => ConstructorSet::Unlistable,
429            ty::CoroutineWitness(_, _) | ty::Bound(_, _) | ty::Placeholder(_) | ty::Infer(_) => {
430                bug!("Encountered unexpected type in `ConstructorSet::for_ty`: {ty:?}")
431            }
432        })
433    }
434
435    pub(crate) fn lower_pat_range_bdy(
436        &self,
437        bdy: PatRangeBoundary<'tcx>,
438        ty: RevealedTy<'tcx>,
439    ) -> MaybeInfiniteInt {
440        match bdy {
441            PatRangeBoundary::NegInfinity => MaybeInfiniteInt::NegInfinity,
442            PatRangeBoundary::Finite(value) => {
443                let bits = value.try_to_scalar_int().unwrap().to_bits_unchecked();
444                match *ty.kind() {
445                    ty::Int(ity) => {
446                        let size = Integer::from_int_ty(&self.tcx, ity).size().bits();
447                        MaybeInfiniteInt::new_finite_int(bits, size)
448                    }
449                    _ => MaybeInfiniteInt::new_finite_uint(bits),
450                }
451            }
452            PatRangeBoundary::PosInfinity => MaybeInfiniteInt::PosInfinity,
453        }
454    }
455
456    /// Note: the input patterns must have been lowered through
457    /// `rustc_mir_build::thir::pattern::check_match::MatchVisitor::lower_pattern`.
458    pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
459        let cx = self;
460        let ty = cx.reveal_opaque_ty(pat.ty);
461        let ctor;
462        let arity;
463        let fields: Vec<_>;
464        match &pat.kind {
465            PatKind::AscribeUserType { subpattern, .. }
466            | PatKind::ExpandedConstant { subpattern, .. } => return self.lower_pat(subpattern),
467            PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat),
468            PatKind::Missing | PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
469                ctor = Wildcard;
470                fields = vec![];
471                arity = 0;
472            }
473            PatKind::Deref { subpattern } => {
474                fields = vec![self.lower_pat(subpattern).at_index(0)];
475                arity = 1;
476                ctor = match ty.pinned_ref() {
477                    None if ty.is_ref() => Ref,
478                    Some((inner_ty, _)) => {
479                        self.internal_state.has_lowered_deref_pat.set(true);
480                        DerefPattern(RevealedTy(inner_ty))
481                    }
482                    _ => span_bug!(
483                        pat.span,
484                        "pattern has unexpected type: pat: {:?}, ty: {:?}",
485                        pat.kind,
486                        ty.inner()
487                    ),
488                };
489            }
490            PatKind::DerefPattern { subpattern, .. } => {
491                // NB(deref_patterns): This assumes the deref pattern is matching on a trusted
492                // `DerefPure` type. If the `Deref` impl isn't trusted, exhaustiveness must take
493                // into account that multiple calls to deref may return different results. Hence
494                // multiple deref! patterns cannot be exhaustive together unless each is exhaustive
495                // by itself.
496                fields = vec![self.lower_pat(subpattern).at_index(0)];
497                arity = 1;
498                ctor = DerefPattern(cx.reveal_opaque_ty(subpattern.ty));
499                self.internal_state.has_lowered_deref_pat.set(true);
500            }
501            PatKind::Leaf { subpatterns } | PatKind::Variant { subpatterns, .. } => {
502                match ty.kind() {
503                    ty::Tuple(fs) => {
504                        ctor = Struct;
505                        arity = fs.len();
506                        fields = subpatterns
507                            .iter()
508                            .map(|ipat| self.lower_pat(&ipat.pattern).at_index(ipat.field.index()))
509                            .collect();
510                    }
511                    ty::Adt(adt, _) => {
512                        ctor = match pat.kind {
513                            PatKind::Leaf { .. } if adt.is_union() => UnionField,
514                            PatKind::Leaf { .. } => Struct,
515                            PatKind::Variant { variant_index, .. } => Variant(variant_index),
516                            _ => bug!(),
517                        };
518                        let variant =
519                            &adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt));
520                        arity = variant.fields.len();
521                        fields = subpatterns
522                            .iter()
523                            .map(|ipat| self.lower_pat(&ipat.pattern).at_index(ipat.field.index()))
524                            .collect();
525                    }
526                    _ => span_bug!(
527                        pat.span,
528                        "pattern has unexpected type: pat: {:?}, ty: {}",
529                        pat.kind,
530                        ty.inner()
531                    ),
532                }
533            }
534            PatKind::Constant { value } => {
535                match ty.kind() {
536                    ty::Bool => {
537                        ctor = Bool(value.try_to_bool().unwrap());
538                        fields = vec![];
539                        arity = 0;
540                    }
541                    ty::Char | ty::Int(_) | ty::Uint(_) => {
542                        ctor = {
543                            let bits = value.valtree.unwrap_leaf().to_bits_unchecked();
544                            let x = match *ty.kind() {
545                                ty::Int(ity) => {
546                                    let size = Integer::from_int_ty(&cx.tcx, ity).size().bits();
547                                    MaybeInfiniteInt::new_finite_int(bits, size)
548                                }
549                                _ => MaybeInfiniteInt::new_finite_uint(bits),
550                            };
551                            IntRange(IntRange::from_singleton(x))
552                        };
553                        fields = vec![];
554                        arity = 0;
555                    }
556                    ty::Float(ty::FloatTy::F16) => {
557                        use rustc_apfloat::Float;
558                        let bits = value.valtree.unwrap_leaf().to_u16();
559                        let value = rustc_apfloat::ieee::Half::from_bits(bits.into());
560                        ctor = F16Range(value, value, RangeEnd::Included);
561                        fields = vec![];
562                        arity = 0;
563                    }
564                    ty::Float(ty::FloatTy::F32) => {
565                        use rustc_apfloat::Float;
566                        let bits = value.valtree.unwrap_leaf().to_u32();
567                        let value = rustc_apfloat::ieee::Single::from_bits(bits.into());
568                        ctor = F32Range(value, value, RangeEnd::Included);
569                        fields = vec![];
570                        arity = 0;
571                    }
572                    ty::Float(ty::FloatTy::F64) => {
573                        use rustc_apfloat::Float;
574                        let bits = value.valtree.unwrap_leaf().to_u64();
575                        let value = rustc_apfloat::ieee::Double::from_bits(bits.into());
576                        ctor = F64Range(value, value, RangeEnd::Included);
577                        fields = vec![];
578                        arity = 0;
579                    }
580                    ty::Float(ty::FloatTy::F128) => {
581                        use rustc_apfloat::Float;
582                        let bits = value.valtree.unwrap_leaf().to_u128();
583                        let value = rustc_apfloat::ieee::Quad::from_bits(bits);
584                        ctor = F128Range(value, value, RangeEnd::Included);
585                        fields = vec![];
586                        arity = 0;
587                    }
588                    ty::Ref(_, t, _) if t.is_str() => {
589                        // We want a `&str` constant to behave like a `Deref` pattern, to be compatible
590                        // with other `Deref` patterns. This could have been done in `const_to_pat`,
591                        // but that causes issues with the rest of the matching code.
592                        // So here, the constructor for a `"foo"` pattern is `&` (represented by
593                        // `Ref`), and has one field. That field has constructor `Str(value)` and no
594                        // subfields.
595                        // Note: `t` is `str`, not `&str`.
596                        let ty = self.reveal_opaque_ty(*t);
597                        let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), 0, ty, pat);
598                        ctor = Ref;
599                        fields = vec![subpattern.at_index(0)];
600                        arity = 1;
601                    }
602                    // All constants that can be structurally matched have already been expanded
603                    // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
604                    // opaque.
605                    _ => {
606                        ctor = Opaque(OpaqueId::new());
607                        fields = vec![];
608                        arity = 0;
609                    }
610                }
611            }
612            PatKind::Range(patrange) => {
613                let PatRange { lo, hi, end, .. } = patrange.as_ref();
614                let end = match end {
615                    rustc_hir::RangeEnd::Included => RangeEnd::Included,
616                    rustc_hir::RangeEnd::Excluded => RangeEnd::Excluded,
617                };
618                ctor = match ty.kind() {
619                    ty::Char | ty::Int(_) | ty::Uint(_) => {
620                        let lo = cx.lower_pat_range_bdy(*lo, ty);
621                        let hi = cx.lower_pat_range_bdy(*hi, ty);
622                        IntRange(IntRange::from_range(lo, hi, end))
623                    }
624                    ty::Float(fty) => {
625                        use rustc_apfloat::Float;
626                        let lo = lo
627                            .as_finite()
628                            .map(|c| c.try_to_scalar_int().unwrap().to_bits_unchecked());
629                        let hi = hi
630                            .as_finite()
631                            .map(|c| c.try_to_scalar_int().unwrap().to_bits_unchecked());
632                        match fty {
633                            ty::FloatTy::F16 => {
634                                use rustc_apfloat::ieee::Half;
635                                let lo = lo.map(Half::from_bits).unwrap_or(-Half::INFINITY);
636                                let hi = hi.map(Half::from_bits).unwrap_or(Half::INFINITY);
637                                F16Range(lo, hi, end)
638                            }
639                            ty::FloatTy::F32 => {
640                                use rustc_apfloat::ieee::Single;
641                                let lo = lo.map(Single::from_bits).unwrap_or(-Single::INFINITY);
642                                let hi = hi.map(Single::from_bits).unwrap_or(Single::INFINITY);
643                                F32Range(lo, hi, end)
644                            }
645                            ty::FloatTy::F64 => {
646                                use rustc_apfloat::ieee::Double;
647                                let lo = lo.map(Double::from_bits).unwrap_or(-Double::INFINITY);
648                                let hi = hi.map(Double::from_bits).unwrap_or(Double::INFINITY);
649                                F64Range(lo, hi, end)
650                            }
651                            ty::FloatTy::F128 => {
652                                use rustc_apfloat::ieee::Quad;
653                                let lo = lo.map(Quad::from_bits).unwrap_or(-Quad::INFINITY);
654                                let hi = hi.map(Quad::from_bits).unwrap_or(Quad::INFINITY);
655                                F128Range(lo, hi, end)
656                            }
657                        }
658                    }
659                    _ => span_bug!(pat.span, "invalid type for range pattern: {}", ty.inner()),
660                };
661                fields = vec![];
662                arity = 0;
663            }
664            PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => {
665                let array_len = match ty.kind() {
666                    ty::Array(_, length) => Some(
667                        length
668                            .try_to_target_usize(cx.tcx)
669                            .expect("expected len of array pat to be definite")
670                            as usize,
671                    ),
672                    ty::Slice(_) => None,
673                    _ => span_bug!(pat.span, "bad ty {} for slice pattern", ty.inner()),
674                };
675                let kind = if slice.is_some() {
676                    SliceKind::VarLen(prefix.len(), suffix.len())
677                } else {
678                    SliceKind::FixedLen(prefix.len() + suffix.len())
679                };
680                ctor = Slice(Slice::new(array_len, kind));
681                fields = prefix
682                    .iter()
683                    .chain(suffix.iter())
684                    .map(|p| self.lower_pat(&*p))
685                    .enumerate()
686                    .map(|(i, p)| p.at_index(i))
687                    .collect();
688                arity = kind.arity();
689            }
690            PatKind::Or { .. } => {
691                ctor = Or;
692                let pats = expand_or_pat(pat);
693                fields = pats
694                    .into_iter()
695                    .map(|p| self.lower_pat(p))
696                    .enumerate()
697                    .map(|(i, p)| p.at_index(i))
698                    .collect();
699                arity = fields.len();
700            }
701            PatKind::Never => {
702                // A never pattern matches all the values of its type (namely none). Moreover it
703                // must be compatible with other constructors, since we can use `!` on a type like
704                // `Result<!, !>` which has other constructors. Hence we lower it as a wildcard.
705                ctor = Wildcard;
706                fields = vec![];
707                arity = 0;
708            }
709            PatKind::Error(_) => {
710                ctor = Opaque(OpaqueId::new());
711                fields = vec![];
712                arity = 0;
713            }
714        }
715        DeconstructedPat::new(ctor, fields, arity, ty, pat)
716    }
717
718    /// Convert back to a `thir::PatRangeBoundary` for diagnostic purposes.
719    /// Note: it is possible to get `isize/usize::MAX+1` here, as explained in the doc for
720    /// [`IntRange::split`]. This cannot be represented as a `Const`, so we represent it with
721    /// `PosInfinity`.
722    fn hoist_pat_range_bdy(
723        &self,
724        miint: MaybeInfiniteInt,
725        ty: RevealedTy<'tcx>,
726    ) -> PatRangeBoundary<'tcx> {
727        use MaybeInfiniteInt::*;
728        let tcx = self.tcx;
729        match miint {
730            NegInfinity => PatRangeBoundary::NegInfinity,
731            Finite(_) => {
732                let size = ty.primitive_size(tcx);
733                let bits = match *ty.kind() {
734                    ty::Int(_) => miint.as_finite_int(size.bits()).unwrap(),
735                    _ => miint.as_finite_uint().unwrap(),
736                };
737                match ScalarInt::try_from_uint(bits, size) {
738                    Some(scalar) => {
739                        let valtree = ty::ValTree::from_scalar_int(tcx, scalar);
740                        PatRangeBoundary::Finite(valtree)
741                    }
742                    // The value doesn't fit. Since `x >= 0` and 0 always encodes the minimum value
743                    // for a type, the problem isn't that the value is too small. So it must be too
744                    // large.
745                    None => PatRangeBoundary::PosInfinity,
746                }
747            }
748            PosInfinity => PatRangeBoundary::PosInfinity,
749        }
750    }
751
752    /// Prints an [`IntRange`] to a string for diagnostic purposes.
753    fn print_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> String {
754        use MaybeInfiniteInt::*;
755        let cx = self;
756        if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) {
757            "_".to_string()
758        } else if range.is_singleton() {
759            let lo = cx.hoist_pat_range_bdy(range.lo, ty);
760            let value = ty::Value { ty: ty.inner(), valtree: lo.as_finite().unwrap() };
761            value.to_string()
762        } else {
763            // We convert to an inclusive range for diagnostics.
764            let mut end = rustc_hir::RangeEnd::Included;
765            let mut lo = cx.hoist_pat_range_bdy(range.lo, ty);
766            if matches!(lo, PatRangeBoundary::PosInfinity) {
767                // The only reason to get `PosInfinity` here is the special case where
768                // `hoist_pat_range_bdy` found `{u,i}size::MAX+1`. So the range denotes the
769                // fictitious values after `{u,i}size::MAX` (see [`IntRange::split`] for why we do
770                // this). We show this to the user as `usize::MAX..` which is slightly incorrect but
771                // probably clear enough.
772                let max = ty.numeric_max_val(cx.tcx).unwrap();
773                let max = ty::ValTree::from_scalar_int(cx.tcx, max.try_to_scalar_int().unwrap());
774                lo = PatRangeBoundary::Finite(max);
775            }
776            let hi = if let Some(hi) = range.hi.minus_one() {
777                hi
778            } else {
779                // The range encodes `..ty::MIN`, so we can't convert it to an inclusive range.
780                end = rustc_hir::RangeEnd::Excluded;
781                range.hi
782            };
783            let hi = cx.hoist_pat_range_bdy(hi, ty);
784            PatRange { lo, hi, end, ty: ty.inner() }.to_string()
785        }
786    }
787
788    /// Prints a [`WitnessPat`] to an owned string, for diagnostic purposes.
789    ///
790    /// This panics for patterns that don't appear in diagnostics, like float ranges.
791    pub fn print_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> String {
792        let cx = self;
793        let print = |p| cx.print_witness_pat(p);
794        match pat.ctor() {
795            Bool(b) => b.to_string(),
796            Str(s) => s.to_string(),
797            IntRange(range) => return self.print_pat_range(range, *pat.ty()),
798            Struct | Variant(_) | UnionField => {
799                let enum_info = match *pat.ty().kind() {
800                    ty::Adt(adt_def, _) if adt_def.is_enum() => EnumInfo::Enum {
801                        adt_def,
802                        variant_index: RustcPatCtxt::variant_index_for_adt(pat.ctor(), adt_def),
803                    },
804                    ty::Adt(..) | ty::Tuple(..) => EnumInfo::NotEnum,
805                    _ => bug!("unexpected ctor for type {:?} {:?}", pat.ctor(), *pat.ty()),
806                };
807
808                let subpatterns = pat
809                    .iter_fields()
810                    .enumerate()
811                    .map(|(i, pat)| print::FieldPat {
812                        field: FieldIdx::new(i),
813                        pattern: print(pat),
814                        is_wildcard: would_print_as_wildcard(cx.tcx, pat),
815                    })
816                    .collect::<Vec<_>>();
817
818                let mut s = String::new();
819                print::write_struct_like(
820                    &mut s,
821                    self.tcx,
822                    pat.ty().inner(),
823                    &enum_info,
824                    &subpatterns,
825                )
826                .unwrap();
827                s
828            }
829            Ref => {
830                let mut s = String::new();
831                print::write_ref_like(&mut s, pat.ty().inner(), &print(&pat.fields[0])).unwrap();
832                s
833            }
834            DerefPattern(_) if pat.ty().is_box() && !self.tcx.features().deref_patterns() => {
835                // FIXME(deref_patterns): Remove this special handling once `box_patterns` is gone.
836                // HACK(@dianne): `box _` syntax is exposed on stable in diagnostics, e.g. to
837                // witness non-exhaustiveness of `match Box::new(0) { Box { .. } if false => {} }`.
838                // To avoid changing diagnostics before deref pattern syntax is finalized, let's use
839                // `box _` syntax unless `deref_patterns` is enabled.
840                format!("box {}", print(&pat.fields[0]))
841            }
842            DerefPattern(_) => format!("deref!({})", print(&pat.fields[0])),
843            Slice(slice) => {
844                let (prefix_len, has_dot_dot) = match slice.kind {
845                    SliceKind::FixedLen(len) => (len, false),
846                    SliceKind::VarLen(prefix_len, _) => (prefix_len, true),
847                };
848
849                let (mut prefix, mut suffix) = pat.fields.split_at(prefix_len);
850
851                // If the pattern contains a `..`, but is applied to values of statically-known
852                // length (arrays), then we can slightly simplify diagnostics by merging any
853                // adjacent wildcard patterns into the `..`: `[x, _, .., _, y]` => `[x, .., y]`.
854                // (This simplification isn't allowed for slice values, because in that case
855                // `[x, .., y]` would match some slices that `[x, _, .., _, y]` would not.)
856                if has_dot_dot && slice.array_len.is_some() {
857                    while let [rest @ .., last] = prefix
858                        && would_print_as_wildcard(cx.tcx, last)
859                    {
860                        prefix = rest;
861                    }
862                    while let [first, rest @ ..] = suffix
863                        && would_print_as_wildcard(cx.tcx, first)
864                    {
865                        suffix = rest;
866                    }
867                }
868
869                let prefix = prefix.iter().map(print).collect::<Vec<_>>();
870                let suffix = suffix.iter().map(print).collect::<Vec<_>>();
871
872                let mut s = String::new();
873                print::write_slice_like(&mut s, &prefix, has_dot_dot, &suffix).unwrap();
874                s
875            }
876            Never if self.tcx.features().never_patterns() => "!".to_string(),
877            Never | Wildcard | NonExhaustive | Hidden | PrivateUninhabited => "_".to_string(),
878            Missing { .. } => bug!(
879                "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
880                `Missing` should have been processed in `apply_constructors`"
881            ),
882            F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Opaque(..) | Or => {
883                bug!("can't convert to pattern: {:?}", pat)
884            }
885        }
886    }
887}
888
889/// Returns `true` if the given pattern would be printed as a wildcard (`_`).
890fn would_print_as_wildcard(tcx: TyCtxt<'_>, p: &WitnessPat<'_, '_>) -> bool {
891    match p.ctor() {
892        Constructor::IntRange(IntRange {
893            lo: MaybeInfiniteInt::NegInfinity,
894            hi: MaybeInfiniteInt::PosInfinity,
895        })
896        | Constructor::Wildcard
897        | Constructor::NonExhaustive
898        | Constructor::Hidden
899        | Constructor::PrivateUninhabited => true,
900        Constructor::Never if !tcx.features().never_patterns() => true,
901        _ => false,
902    }
903}
904
905impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
906    type Ty = RevealedTy<'tcx>;
907    type Error = ErrorGuaranteed;
908    type VariantIdx = VariantIdx;
909    type StrLit = ty::Value<'tcx>;
910    type ArmData = HirId;
911    type PatData = &'p Pat<'tcx>;
912
913    fn is_exhaustive_patterns_feature_on(&self) -> bool {
914        self.tcx.features().exhaustive_patterns()
915    }
916
917    fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: &Self::Ty) -> usize {
918        self.ctor_arity(ctor, *ty)
919    }
920    fn ctor_sub_tys(
921        &self,
922        ctor: &crate::constructor::Constructor<Self>,
923        ty: &Self::Ty,
924    ) -> impl Iterator<Item = (Self::Ty, PrivateUninhabitedField)> + ExactSizeIterator {
925        self.ctor_sub_tys(ctor, *ty)
926    }
927    fn ctors_for_ty(
928        &self,
929        ty: &Self::Ty,
930    ) -> Result<crate::constructor::ConstructorSet<Self>, Self::Error> {
931        self.ctors_for_ty(*ty)
932    }
933
934    fn write_variant_name(
935        f: &mut fmt::Formatter<'_>,
936        ctor: &crate::constructor::Constructor<Self>,
937        ty: &Self::Ty,
938    ) -> fmt::Result {
939        if let ty::Adt(adt, _) = ty.kind() {
940            let variant = adt.variant(Self::variant_index_for_adt(ctor, *adt));
941            write!(f, "{}", variant.name)?;
942        }
943        Ok(())
944    }
945
946    fn bug(&self, fmt: fmt::Arguments<'_>) -> Self::Error {
947        span_bug!(self.scrut_span, "{}", fmt)
948    }
949
950    fn lint_overlapping_range_endpoints(
951        &self,
952        pat: &crate::pat::DeconstructedPat<Self>,
953        overlaps_on: IntRange,
954        overlaps_with: &[&crate::pat::DeconstructedPat<Self>],
955    ) {
956        let overlap_as_pat = self.print_pat_range(&overlaps_on, *pat.ty());
957        let overlaps: Vec<_> = overlaps_with
958            .iter()
959            .map(|pat| pat.data().span)
960            .map(|span| errors::Overlap { range: overlap_as_pat.to_string(), span })
961            .collect();
962        let pat_span = pat.data().span;
963        self.tcx.emit_node_span_lint(
964            lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
965            self.match_lint_level,
966            pat_span,
967            errors::OverlappingRangeEndpoints { overlap: overlaps, range: pat_span },
968        );
969    }
970
971    fn complexity_exceeded(&self) -> Result<(), Self::Error> {
972        let span = self.whole_match_span.unwrap_or(self.scrut_span);
973        Err(self.tcx.dcx().span_err(span, "reached pattern complexity limit"))
974    }
975
976    fn lint_non_contiguous_range_endpoints(
977        &self,
978        pat: &crate::pat::DeconstructedPat<Self>,
979        gap: IntRange,
980        gapped_with: &[&crate::pat::DeconstructedPat<Self>],
981    ) {
982        let &thir_pat = pat.data();
983        let thir::PatKind::Range(range) = &thir_pat.kind else { return };
984        // Only lint when the left range is an exclusive range.
985        if range.end != rustc_hir::RangeEnd::Excluded {
986            return;
987        }
988        // `pat` is an exclusive range like `lo..gap`. `gapped_with` contains ranges that start with
989        // `gap+1`.
990        let suggested_range: String = {
991            // Suggest `lo..=gap` instead.
992            let mut suggested_range = PatRange::clone(range);
993            suggested_range.end = rustc_hir::RangeEnd::Included;
994            suggested_range.to_string()
995        };
996        let gap_as_pat = self.print_pat_range(&gap, *pat.ty());
997        if gapped_with.is_empty() {
998            // If `gapped_with` is empty, `gap == T::MAX`.
999            self.tcx.emit_node_span_lint(
1000                lint::builtin::NON_CONTIGUOUS_RANGE_ENDPOINTS,
1001                self.match_lint_level,
1002                thir_pat.span,
1003                errors::ExclusiveRangeMissingMax {
1004                    // Point at this range.
1005                    first_range: thir_pat.span,
1006                    // That's the gap that isn't covered.
1007                    max: gap_as_pat,
1008                    // Suggest `lo..=max` instead.
1009                    suggestion: suggested_range,
1010                },
1011            );
1012        } else {
1013            self.tcx.emit_node_span_lint(
1014                lint::builtin::NON_CONTIGUOUS_RANGE_ENDPOINTS,
1015                self.match_lint_level,
1016                thir_pat.span,
1017                errors::ExclusiveRangeMissingGap {
1018                    // Point at this range.
1019                    first_range: thir_pat.span,
1020                    // That's the gap that isn't covered.
1021                    gap: gap_as_pat.to_string(),
1022                    // Suggest `lo..=gap` instead.
1023                    suggestion: suggested_range,
1024                    // All these ranges skipped over `gap` which we think is probably a
1025                    // mistake.
1026                    gap_with: gapped_with
1027                        .iter()
1028                        .map(|pat| errors::GappedRange {
1029                            span: pat.data().span,
1030                            gap: gap_as_pat.to_string(),
1031                            first_range: range.to_string(),
1032                        })
1033                        .collect(),
1034                },
1035            );
1036        }
1037    }
1038
1039    fn match_may_contain_deref_pats(&self) -> bool {
1040        self.internal_state.has_lowered_deref_pat.get()
1041    }
1042
1043    fn report_mixed_deref_pat_ctors(
1044        &self,
1045        deref_pat: &crate::pat::DeconstructedPat<Self>,
1046        normal_pat: &crate::pat::DeconstructedPat<Self>,
1047    ) -> Self::Error {
1048        let deref_pattern_label = deref_pat.data().span;
1049        let normal_constructor_label = normal_pat.data().span;
1050        self.tcx.dcx().emit_err(errors::MixedDerefPatternConstructors {
1051            spans: vec![deref_pattern_label, normal_constructor_label],
1052            smart_pointer_ty: deref_pat.ty().inner(),
1053            deref_pattern_label,
1054            normal_constructor_label,
1055        })
1056    }
1057}
1058
1059/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
1060fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> {
1061    fn expand<'p, 'tcx>(pat: &'p Pat<'tcx>, vec: &mut Vec<&'p Pat<'tcx>>) {
1062        if let PatKind::Or { pats } = &pat.kind {
1063            for pat in pats.iter() {
1064                expand(pat, vec);
1065            }
1066        } else {
1067            vec.push(pat)
1068        }
1069    }
1070
1071    let mut pats = Vec::new();
1072    expand(pat, &mut pats);
1073    pats
1074}
1075
1076/// The entrypoint for this crate. Computes whether a match is exhaustive and which of its arms are
1077/// useful, and runs some lints.
1078pub fn analyze_match<'p, 'tcx>(
1079    tycx: &RustcPatCtxt<'p, 'tcx>,
1080    arms: &[MatchArm<'p, 'tcx>],
1081    scrut_ty: Ty<'tcx>,
1082) -> Result<UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> {
1083    let scrut_ty = tycx.reveal_opaque_ty(scrut_ty);
1084
1085    let scrut_validity = PlaceValidity::from_bool(tycx.known_valid_scrutinee);
1086    let report = compute_match_usefulness(
1087        tycx,
1088        arms,
1089        scrut_ty,
1090        scrut_validity,
1091        tycx.tcx.pattern_complexity_limit().0,
1092    )?;
1093
1094    // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
1095    // `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
1096    if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() {
1097        let pat_column = PatternColumn::new(arms);
1098        lint_nonexhaustive_missing_variants(tycx, arms, &pat_column, scrut_ty)?;
1099    }
1100
1101    Ok(report)
1102}