Skip to content

[Experiment] Rewrite exhaustiveness in one pass #111720

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
2bed859
Add some tests
Nadrieril May 15, 2023
0332402
Don't use per-arm lint levels
Nadrieril May 16, 2023
2058de5
Implement lint as a separate columns-wise pass
Nadrieril May 16, 2023
0361bf2
Abstract over list of witnesses
Nadrieril May 15, 2023
49b1581
Add some or-pat tests
Nadrieril May 15, 2023
366a444
Separate arm reachability from match exhaustiveness
Nadrieril May 16, 2023
8b958d1
Start push in matrix early
Nadrieril May 17, 2023
df7b156
Getting close
Nadrieril May 17, 2023
90afa1d
fix constants!
Nadrieril May 17, 2023
a2310d6
kill perf now
Nadrieril May 17, 2023
4c3fdbb
ayyyy one pass
Nadrieril May 17, 2023
690e600
use set to emulate splitwildcard
Nadrieril May 17, 2023
d96a78a
true one pass!
Nadrieril May 17, 2023
51fed5e
don't need SplitWildcard anymore
Nadrieril May 17, 2023
1e1db2e
Specialize `ConstructorSet` per type. Got rid of `ctor.split()`
Nadrieril May 18, 2023
9c33ea7
track whether we're collecting witnesses
Nadrieril May 18, 2023
ea36f62
try a lil perf improvement
Nadrieril May 18, 2023
d8e3c8a
fix silly doc errors
Nadrieril May 18, 2023
0808629
tiny speedup
Nadrieril May 19, 2023
0a67808
Test usize + half-open ranges
Nadrieril May 19, 2023
3dd0d1c
Avoid quadratic behavior in usize/isize matches
Nadrieril May 19, 2023
33ec800
Clean up SplitIntRange a bit
Nadrieril May 19, 2023
449b284
better range analysis: step 1
Nadrieril May 19, 2023
e762149
better range analysis: step 2
Nadrieril May 19, 2023
8458c9f
better range analysis: step 3
Nadrieril May 19, 2023
a3c91da
better range analysis: do overlap check after splitting
Nadrieril May 19, 2023
1bf40c2
maybe tiny perf gain?
Nadrieril May 21, 2023
5450fd5
Store wildcard row in the matrix
Nadrieril May 23, 2023
144ea11
cleanup
Nadrieril May 21, 2023
23dc7c9
Clarify handling empty types
Nadrieril May 21, 2023
77ba32d
Filter hidden variants earlier
Nadrieril May 21, 2023
2364522
tweak
Nadrieril May 22, 2023
c6976d8
tweak
Nadrieril May 22, 2023
500e0bd
tweak
Nadrieril May 22, 2023
5072a1e
`pcx.span` was no longer meaningful
Nadrieril May 22, 2023
f030769
Cleanup slice splitting
Nadrieril May 22, 2023
5cfb953
Splitting ensures subrange comparison is all we need
Nadrieril May 22, 2023
8670ba9
Don't need to carry the `bias` around in `IntRange`
Nadrieril May 22, 2023
839b032
Revert one-pass-omitted-patterns-lint
Nadrieril May 23, 2023
16095a8
Check overlapping_range lint level per arm
Nadrieril May 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3801,8 +3801,10 @@ declare_lint! {
}

declare_lint! {
/// The `non_exhaustive_omitted_patterns` lint detects when a wildcard (`_` or `..`) in a
/// pattern for a `#[non_exhaustive]` struct or enum is reachable.
/// The `non_exhaustive_omitted_patterns` lint detects when some variants or fields of a
/// `#[non_exhaustive]` struct or enum are not mentioned explicitly in a pattern. This allows
/// downstream crates to be warned when new variants or fields are added to the upstream struct
/// or enum.
///
/// ### Example
///
Expand All @@ -3817,9 +3819,9 @@ declare_lint! {
/// // in crate B
/// #![feature(non_exhaustive_omitted_patterns_lint)]
///
/// #[warn(non_exhaustive_omitted_patterns)]
/// match Bar::A {
/// Bar::A => {},
/// #[warn(non_exhaustive_omitted_patterns)]
/// _ => {},
/// }
/// ```
Expand All @@ -3830,8 +3832,8 @@ declare_lint! {
/// warning: reachable patterns not covered of non exhaustive enum
/// --> $DIR/reachable-patterns.rs:70:9
/// |
/// LL | _ => {}
/// | ^ pattern `B` not covered
/// LL | match Bar::A {
/// | ^ pattern `Bar::B` not covered
/// |
/// note: the lint level is defined here
/// --> $DIR/reachable-patterns.rs:69:16
Expand All @@ -3844,12 +3846,11 @@ declare_lint! {
///
/// ### Explanation
///
/// Structs and enums tagged with `#[non_exhaustive]` force the user to add a
/// (potentially redundant) wildcard when pattern-matching, to allow for future
/// addition of fields or variants. The `non_exhaustive_omitted_patterns` lint
/// detects when such a wildcard happens to actually catch some fields/variants.
/// In other words, when the match without the wildcard would not be exhaustive.
/// This lets the user be informed if new fields/variants were added.
/// Structs and enums tagged with `#[non_exhaustive]` force the user to add a (potentially
/// redundant) wildcard when pattern-matching, to allow for future addition of fields or
/// variants. The `non_exhaustive_omitted_patterns` lint detects when such a wildcard happens to
/// actually catch some fields/variants. This lets the user be informed if new fields/variants
/// were added.
pub NON_EXHAUSTIVE_OMITTED_PATTERNS,
Allow,
"detect when patterns of types marked `non_exhaustive` are missed",
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {

let scrut = &self.thir[scrut];
let scrut_ty = scrut.ty;
let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty);
let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty, scrut.span);

match source {
// Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
Expand Down Expand Up @@ -416,7 +416,8 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
let pattern = self.lower_pattern(&mut cx, pat);
let pattern_ty = pattern.ty();
let arm = MatchArm { pat: pattern, hir_id: self.lint_level, has_guard: false };
let report = compute_match_usefulness(&cx, &[arm], self.lint_level, pattern_ty);
let report =
compute_match_usefulness(&cx, &[arm], self.lint_level, pattern_ty, pattern.span());

// Note: we ignore whether the pattern is unreachable (i.e. whether the type is empty). We
// only care about exhaustiveness here.
Expand Down Expand Up @@ -584,7 +585,7 @@ fn is_let_irrefutable<'p, 'tcx>(
pat: &'p DeconstructedPat<'p, 'tcx>,
) -> bool {
let arms = [MatchArm { pat, hir_id: pat_id, has_guard: false }];
let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty());
let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty(), pat.span());

// Report if the pattern is unreachable, which can only occur when the type is uninhabited.
// This also reports unreachable sub-patterns though, so we can't just replace it with an
Expand Down
Loading