1
1
use std:: { cmp, ops} ;
2
2
3
- use rustc_span:: { DUMMY_SP , Span } ;
3
+ use rustc_span:: Span ;
4
4
5
5
/// Tracks whether executing a node may exit normally (versus
6
6
/// return/break/panic, which "diverge", leaving dead code in their
7
7
/// wake). Tracked semi-automatically (through type variables marked
8
8
/// as diverging), with some manual adjustments for control-flow
9
9
/// primitives (approximating a CFG).
10
- #[ derive( Copy , Clone , Debug , PartialEq , Eq , PartialOrd , Ord ) ]
10
+ #[ derive( Copy , Clone , Debug ) ]
11
11
pub ( crate ) enum Diverges {
12
12
/// Potentially unknown, some cases converge,
13
13
/// others require a CFG to determine them.
14
14
Maybe ,
15
15
16
16
/// Definitely known to diverge and therefore
17
17
/// not reach the next sibling or its parent.
18
- Always {
19
- /// The `Span` points to the expression
20
- /// that caused us to diverge
21
- /// (e.g. `return`, `break`, etc).
22
- span : Span ,
23
- /// In some cases (e.g. a `match` expression
24
- /// where all arms diverge), we may be
25
- /// able to provide a more informative
26
- /// message to the user.
27
- /// If this is `None`, a default message
28
- /// will be generated, which is suitable
29
- /// for most cases.
30
- custom_note : Option < & ' static str > ,
31
- } ,
18
+ Always ( DivergeReason , Span ) ,
32
19
33
20
/// Same as `Always` but with a reachability
34
21
/// warning already emitted.
@@ -40,14 +27,15 @@ pub(crate) enum Diverges {
40
27
impl ops:: BitAnd for Diverges {
41
28
type Output = Self ;
42
29
fn bitand ( self , other : Self ) -> Self {
43
- cmp:: min ( self , other)
30
+ cmp:: min_by_key ( self , other, Self :: ordinal )
44
31
}
45
32
}
46
33
47
34
impl ops:: BitOr for Diverges {
48
35
type Output = Self ;
49
36
fn bitor ( self , other : Self ) -> Self {
50
- cmp:: max ( self , other)
37
+ // argument order is to prefer `self` if ordinal is equal
38
+ cmp:: max_by_key ( other, self , Self :: ordinal)
51
39
}
52
40
}
53
41
@@ -64,15 +52,25 @@ impl ops::BitOrAssign for Diverges {
64
52
}
65
53
66
54
impl Diverges {
67
- /// Creates a `Diverges::Always` with the provided `span` and the default note message.
68
- pub ( super ) fn always ( span : Span ) -> Diverges {
69
- Diverges :: Always { span, custom_note : None }
55
+ pub ( super ) fn is_always ( self ) -> bool {
56
+ match self {
57
+ Self :: Maybe => false ,
58
+ Self :: Always ( ..) | Self :: WarnedAlways => true ,
59
+ }
70
60
}
71
61
72
- pub ( super ) fn is_always ( self ) -> bool {
73
- // Enum comparison ignores the
74
- // contents of fields, so we just
75
- // fill them in with garbage here.
76
- self >= Diverges :: Always { span : DUMMY_SP , custom_note : None }
62
+ fn ordinal ( & self ) -> u8 {
63
+ match self {
64
+ Self :: Maybe => 0 ,
65
+ Self :: Always { .. } => 1 ,
66
+ Self :: WarnedAlways => 2 ,
67
+ }
77
68
}
78
69
}
70
+
71
+ #[ derive( Clone , Copy , Debug ) ]
72
+ pub ( crate ) enum DivergeReason {
73
+ AllArmsDiverge ,
74
+ NeverPattern ,
75
+ Other ,
76
+ }
0 commit comments