-
Notifications
You must be signed in to change notification settings - Fork 1.8k
feat: min_exhaustive_patterns
#17853
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,22 +69,20 @@ pub(crate) struct MatchCheckCtx<'db> { | |
body: DefWithBodyId, | ||
pub(crate) db: &'db dyn HirDatabase, | ||
exhaustive_patterns: bool, | ||
min_exhaustive_patterns: bool, | ||
} | ||
|
||
impl<'db> MatchCheckCtx<'db> { | ||
pub(crate) fn new(module: ModuleId, body: DefWithBodyId, db: &'db dyn HirDatabase) -> Self { | ||
let def_map = db.crate_def_map(module.krate()); | ||
let exhaustive_patterns = def_map.is_unstable_feature_enabled(&sym::exhaustive_patterns); | ||
let min_exhaustive_patterns = | ||
def_map.is_unstable_feature_enabled(&sym::min_exhaustive_patterns); | ||
Self { module, body, db, exhaustive_patterns, min_exhaustive_patterns } | ||
Self { module, body, db, exhaustive_patterns } | ||
} | ||
|
||
pub(crate) fn compute_match_usefulness( | ||
&self, | ||
arms: &[MatchArm<'db>], | ||
scrut_ty: Ty, | ||
known_valid_scrutinee: Option<bool>, | ||
) -> Result<UsefulnessReport<'db, Self>, ()> { | ||
if scrut_ty.contains_unknown() { | ||
return Err(()); | ||
|
@@ -95,8 +93,7 @@ impl<'db> MatchCheckCtx<'db> { | |
} | ||
} | ||
|
||
// FIXME: Determine place validity correctly. For now, err on the safe side. | ||
let place_validity = PlaceValidity::MaybeInvalid; | ||
let place_validity = PlaceValidity::from_bool(known_valid_scrutinee.unwrap_or(true)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
// Measured to take ~100ms on modern hardware. | ||
let complexity_limit = Some(500000); | ||
compute_match_usefulness(self, arms, scrut_ty, place_validity, complexity_limit) | ||
|
@@ -307,7 +304,8 @@ impl<'db> MatchCheckCtx<'db> { | |
&Str(void) => match void {}, | ||
Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild, | ||
Never => PatKind::Never, | ||
Missing | F32Range(..) | F64Range(..) | Opaque(..) | Or => { | ||
Missing | F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Opaque(..) | ||
| Or => { | ||
never!("can't convert to pattern: {:?}", pat.ctor()); | ||
PatKind::Wild | ||
} | ||
|
@@ -327,9 +325,6 @@ impl<'db> PatCx for MatchCheckCtx<'db> { | |
fn is_exhaustive_patterns_feature_on(&self) -> bool { | ||
self.exhaustive_patterns | ||
} | ||
fn is_min_exhaustive_patterns_feature_on(&self) -> bool { | ||
self.min_exhaustive_patterns | ||
} | ||
|
||
fn ctor_arity( | ||
&self, | ||
|
@@ -356,8 +351,9 @@ impl<'db> PatCx for MatchCheckCtx<'db> { | |
}, | ||
Ref => 1, | ||
Slice(..) => unimplemented!(), | ||
Never | Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | ||
| Opaque(..) | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => 0, | ||
Never | Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..) | ||
| F128Range(..) | Str(..) | Opaque(..) | NonExhaustive | PrivateUninhabited | ||
| Hidden | Missing | Wildcard => 0, | ||
Or => { | ||
never!("The `Or` constructor doesn't have a fixed arity"); | ||
0 | ||
|
@@ -419,8 +415,9 @@ impl<'db> PatCx for MatchCheckCtx<'db> { | |
} | ||
}, | ||
Slice(_) => unreachable!("Found a `Slice` constructor in match checking"), | ||
Never | Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | ||
| Opaque(..) | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => { | ||
Never | Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..) | ||
| F128Range(..) | Str(..) | Opaque(..) | NonExhaustive | PrivateUninhabited | ||
| Hidden | Missing | Wildcard => { | ||
smallvec![] | ||
} | ||
Or => { | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -80,6 +80,28 @@ fn main() { | |||||
//^^^^ error: non-exhaustive pattern: `Some(_)` not covered | ||||||
} | ||||||
} | ||||||
"#, | ||||||
); | ||||||
} | ||||||
|
||||||
#[test] | ||||||
fn min_exhaustive() { | ||||||
check_diagnostics( | ||||||
r#" | ||||||
//- minicore: result | ||||||
fn test(x: Result<i32, !>) { | ||||||
let Ok(_y) = x; | ||||||
} | ||||||
"#, | ||||||
); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason that this test doesn't have a pointer deref case is because the following code; fn test(ptr: *const Result<i32, !>) {
unsafe {
let Ok(_x) = *ptr;
}
} is getting a block with no stmts but tail one in here(thus, no diagnostic error), rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs Lines 256 to 257 in 0daeb5c
while the following is getting a block with a single stmt without tail 🤔 fn test(x: Result<i32, &'static !>) {
let Ok(_y) = x;
} I'll make a more deep inspection and file this as a new issue There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
oh no that sounds very wrong There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it looks very wrong 🤔 I'll check the entire lowering process from AST to hir once I get back home There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is because of #17865 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I got into this 😂 rust-lang/rust#129009 |
||||||
|
||||||
check_diagnostics( | ||||||
r#" | ||||||
//- minicore: result | ||||||
fn test(x: Result<i32, &'static !>) { | ||||||
let Ok(_y) = x; | ||||||
//^^^^^^ error: non-exhaustive pattern: `Err(_)` not covered | ||||||
} | ||||||
"#, | ||||||
); | ||||||
} | ||||||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This dance is the compressed version of
https://github.com/rust-lang/rust/blob/c9bd03cb724e13cca96ad320733046cbdb16fbbe/compiler/rustc_mir_build/src/thir/cx/expr.rs
and then
https://github.com/rust-lang/rust/blob/c9bd03cb724e13cca96ad320733046cbdb16fbbe/compiler/rustc_mir_build/src/thir/pattern/check_match.rs#L288