-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Exhaustive integer matching #50912
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
Exhaustive integer matching #50912
Changes from 1 commit
e3357d9
b3d2baf
384db4f
ed5a4d5
b8702a0
121fa8d
7476ba4
9778a81
a20cb10
7f72030
c00fd8f
7695bd0
a553fa7
8389972
f4af3b0
a9f2c5a
effb3d0
c388c11
97a032e
be12b24
72cc4bd
1aa7494
732d638
6c21a03
d27c21c
07064de
25ba911
af366b0
bfc0807
4aa929c
5959a35
bfc8ce3
99754ad
400cb14
9e9e023
527cccb
e9c8361
1dbc781
0383539
798b9ff
87463c3
6e8a625
c421af9
61b6363
6a957e1
dec5563
6971c5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,7 @@ use arena::TypedArena; | |
use std::cmp::{self, Ordering}; | ||
use std::fmt; | ||
use std::iter::{FromIterator, IntoIterator}; | ||
use std::ops::RangeInclusive; | ||
|
||
pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pattern<'tcx>) | ||
-> &'a Pattern<'tcx> | ||
|
@@ -274,7 +275,7 @@ impl<'tcx> Constructor<'tcx> { | |
} | ||
} | ||
|
||
#[derive(Clone)] | ||
#[derive(Clone, Debug)] | ||
pub enum Usefulness<'tcx> { | ||
Useful, | ||
UsefulWithWitness(Vec<Witness<'tcx>>), | ||
|
@@ -290,7 +291,7 @@ impl<'tcx> Usefulness<'tcx> { | |
} | ||
} | ||
|
||
#[derive(Copy, Clone)] | ||
#[derive(Copy, Clone, Debug)] | ||
pub enum WitnessPreference { | ||
ConstructWitness, | ||
LeaveOutWitness | ||
|
@@ -303,7 +304,7 @@ struct PatternContext<'tcx> { | |
} | ||
|
||
/// A stack of patterns in reverse order of construction | ||
#[derive(Clone)] | ||
#[derive(Clone, Debug)] | ||
pub struct Witness<'tcx>(Vec<Pattern<'tcx>>); | ||
|
||
impl<'tcx> Witness<'tcx> { | ||
|
@@ -418,10 +419,6 @@ impl<'tcx> Witness<'tcx> { | |
/// but is instead bounded by the maximum fixed length of slice patterns in | ||
/// the column of patterns being analyzed. | ||
/// | ||
/// This intentionally does not list ConstantValue specializations for | ||
/// non-booleans, because we currently assume that there is always a | ||
/// "non-standard constant" that matches. See issue #12483. | ||
/// | ||
/// We make sure to omit constructors that are statically impossible. eg for | ||
/// Option<!> we do not include Some(_) in the returned list of constructors. | ||
fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, | ||
|
@@ -530,7 +527,7 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>( | |
// `[true, ..]` | ||
// `[.., false]` | ||
// Then any slice of length ≥1 that matches one of these two | ||
// patterns can be be trivially turned to a slice of any | ||
// patterns can be trivially turned to a slice of any | ||
// other length ≥1 that matches them and vice-versa - for | ||
// but the slice from length 2 `[false, true]` that matches neither | ||
// of these patterns can't be turned to a slice from length 1 that | ||
|
@@ -823,33 +820,32 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, | |
// as patterns in the `match` expression, but did not. | ||
let mut missing_ctors = vec![]; | ||
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. maybe extract this to a separate function? this is ok |
||
for req_ctor in &all_ctors { | ||
if consider_value_constructors { | ||
let mut refined_ctors = vec![req_ctor.clone()]; | ||
for used_ctor in &used_ctors { | ||
// Refine the required constructors for the type by subtracting | ||
// the range defined by the current constructor pattern. | ||
refined_ctors = match IntRange::from_ctor(cx.tcx, used_ctor) { | ||
Some(interval) => interval.subtract_from(cx.tcx, refined_ctors), | ||
None => refined_ctors, | ||
}; | ||
// If the constructor patterns that have been considered so far | ||
// already cover the entire range of values, then we the | ||
// constructor is not missing, and we can move on to the next one. | ||
if refined_ctors.is_empty() { | ||
break; | ||
let mut refined_ctors = vec![req_ctor.clone()]; | ||
for used_ctor in &used_ctors { | ||
if used_ctor == req_ctor { | ||
// If a constructor appears in a `match` arm, we can | ||
// eliminate it straight away. | ||
refined_ctors = vec![] | ||
} else if exhaustive_integer_patterns { | ||
if let Some(interval) = IntRange::from_ctor(cx.tcx, used_ctor) { | ||
// Refine the required constructors for the type by subtracting | ||
// the range defined by the current constructor pattern. | ||
refined_ctors = interval.subtract_from(cx.tcx, refined_ctors); | ||
} | ||
} | ||
// If a constructor has not been matched, then it is missing. | ||
// We add `refined_ctors` instead of `req_ctor`, because then we can | ||
// provide more detailed error information about precisely which | ||
// ranges have been omitted. | ||
missing_ctors.extend(refined_ctors); | ||
} else { | ||
// A constructor is missing if it never appears in a `match` arm. | ||
if !used_ctors.iter().any(|used_ctor| used_ctor == req_ctor) { | ||
missing_ctors.push(req_ctor.clone()); | ||
|
||
// If the constructor patterns that have been considered so far | ||
// already cover the entire range of values, then we the | ||
// constructor is not missing, and we can move on to the next one. | ||
if refined_ctors.is_empty() { | ||
break; | ||
} | ||
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 think these codepaths could be unified - that is, in the other path, if |
||
} | ||
// If a constructor has not been matched, then it is missing. | ||
// We add `refined_ctors` instead of `req_ctor`, because then we can | ||
// provide more detailed error information about precisely which | ||
// ranges have been omitted. | ||
missing_ctors.extend(refined_ctors); | ||
} | ||
|
||
// `missing_ctors` is the set of constructors from the same type as the | ||
|
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.
code: extract this to a function?