Skip to content

Commit

Permalink
Shortcut on single wildcard
Browse files Browse the repository at this point in the history
Obtained by repeatedly inlining and simplifying, beyond the point of
reason.
  • Loading branch information
Nadrieril committed Oct 20, 2023
1 parent c417e27 commit 1d158a8
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
14 changes: 14 additions & 0 deletions compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,9 @@ pub(super) enum Constructor<'tcx> {
}

impl<'tcx> Constructor<'tcx> {
pub(super) fn is_wildcard(&self) -> bool {
matches!(self, Wildcard)
}
pub(super) fn is_non_exhaustive(&self) -> bool {
matches!(self, NonExhaustive)
}
Expand Down Expand Up @@ -1003,6 +1006,17 @@ impl ConstructorSet {
}
}

/// Whether `self.split().missing` is empty regardless of the column.
pub(super) fn is_empty(&self, cx: &MatchCheckCtxt<'_, '_>, is_top_level: bool) -> bool {
match self {
ConstructorSet::Variants {
visible_variants, hidden_variants, non_exhaustive, ..
} => visible_variants.is_empty() && hidden_variants.is_empty() && !*non_exhaustive,
ConstructorSet::Uninhabited => cx.tcx.features().exhaustive_patterns || is_top_level,
_ => false,
}
}

/// This is the core logical operation of exhaustiveness checking. This analyzes a column a
/// constructors to 1/ determine which constructors of the type (if any) are missing; 2/ split
/// constructors to handle non-trivial intersections e.g. on ranges or slices.
Expand Down
23 changes: 23 additions & 0 deletions compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,29 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
scrut_ty: Ty<'tcx>,
scrut_span: Span,
) -> UsefulnessReport<'p, 'tcx> {
// Shortcut on the common case of a single wildcard arm, e.g. `let x = ...`.
if let [arm] = arms {
if arm.pat.ctor().is_wildcard() && !arm.has_guard {
let mut ty = scrut_ty;
// Opaque types can't get destructured/split, but the patterns can
// actually hint at hidden types, so we use the patterns' types instead.
if let ty::Alias(ty::Opaque, ..) = ty.kind() {
ty = arm.pat.ty();
}

let set = ConstructorSet::for_ty(cx, ty);
let reachability = if set.is_empty(cx, true) {
Reachability::Unreachable
} else {
Reachability::Reachable(vec![])
};
return UsefulnessReport {
arm_usefulness: vec![(*arm, reachability)],
non_exhaustiveness_witnesses: vec![],
};
}
}

let mut matrix = Matrix::empty();
let arm_usefulness: Vec<_> = arms
.iter()
Expand Down

0 comments on commit 1d158a8

Please sign in to comment.