Skip to content

Commit 1d158a8

Browse files
committed
Shortcut on single wildcard
Obtained by repeatedly inlining and simplifying, beyond the point of reason.
1 parent c417e27 commit 1d158a8

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs

+14
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,9 @@ pub(super) enum Constructor<'tcx> {
634634
}
635635

636636
impl<'tcx> Constructor<'tcx> {
637+
pub(super) fn is_wildcard(&self) -> bool {
638+
matches!(self, Wildcard)
639+
}
637640
pub(super) fn is_non_exhaustive(&self) -> bool {
638641
matches!(self, NonExhaustive)
639642
}
@@ -1003,6 +1006,17 @@ impl ConstructorSet {
10031006
}
10041007
}
10051008

1009+
/// Whether `self.split().missing` is empty regardless of the column.
1010+
pub(super) fn is_empty(&self, cx: &MatchCheckCtxt<'_, '_>, is_top_level: bool) -> bool {
1011+
match self {
1012+
ConstructorSet::Variants {
1013+
visible_variants, hidden_variants, non_exhaustive, ..
1014+
} => visible_variants.is_empty() && hidden_variants.is_empty() && !*non_exhaustive,
1015+
ConstructorSet::Uninhabited => cx.tcx.features().exhaustive_patterns || is_top_level,
1016+
_ => false,
1017+
}
1018+
}
1019+
10061020
/// This is the core logical operation of exhaustiveness checking. This analyzes a column a
10071021
/// constructors to 1/ determine which constructors of the type (if any) are missing; 2/ split
10081022
/// constructors to handle non-trivial intersections e.g. on ranges or slices.

compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

+23
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,29 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
991991
scrut_ty: Ty<'tcx>,
992992
scrut_span: Span,
993993
) -> UsefulnessReport<'p, 'tcx> {
994+
// Shortcut on the common case of a single wildcard arm, e.g. `let x = ...`.
995+
if let [arm] = arms {
996+
if arm.pat.ctor().is_wildcard() && !arm.has_guard {
997+
let mut ty = scrut_ty;
998+
// Opaque types can't get destructured/split, but the patterns can
999+
// actually hint at hidden types, so we use the patterns' types instead.
1000+
if let ty::Alias(ty::Opaque, ..) = ty.kind() {
1001+
ty = arm.pat.ty();
1002+
}
1003+
1004+
let set = ConstructorSet::for_ty(cx, ty);
1005+
let reachability = if set.is_empty(cx, true) {
1006+
Reachability::Unreachable
1007+
} else {
1008+
Reachability::Reachable(vec![])
1009+
};
1010+
return UsefulnessReport {
1011+
arm_usefulness: vec![(*arm, reachability)],
1012+
non_exhaustiveness_witnesses: vec![],
1013+
};
1014+
}
1015+
}
1016+
9941017
let mut matrix = Matrix::empty();
9951018
let arm_usefulness: Vec<_> = arms
9961019
.iter()

0 commit comments

Comments
 (0)