11use std:: { cmp, ops} ;
22
3- use rustc_span:: { DUMMY_SP , Span } ;
3+ use rustc_span:: Span ;
44
55/// Tracks whether executing a node may exit normally (versus
66/// return/break/panic, which "diverge", leaving dead code in their
77/// wake). Tracked semi-automatically (through type variables marked
88/// as diverging), with some manual adjustments for control-flow
99/// primitives (approximating a CFG).
10- #[ derive( Copy , Clone , Debug , PartialEq , Eq , PartialOrd , Ord ) ]
10+ #[ derive( Copy , Clone , Debug ) ]
1111pub ( crate ) enum Diverges {
1212 /// Potentially unknown, some cases converge,
1313 /// others require a CFG to determine them.
1414 Maybe ,
1515
1616 /// Definitely known to diverge and therefore
1717 /// 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 ) ,
3219
3320 /// Same as `Always` but with a reachability
3421 /// warning already emitted.
@@ -40,14 +27,15 @@ pub(crate) enum Diverges {
4027impl ops:: BitAnd for Diverges {
4128 type Output = Self ;
4229 fn bitand ( self , other : Self ) -> Self {
43- cmp:: min ( self , other)
30+ cmp:: min_by_key ( self , other, Self :: ordinal )
4431 }
4532}
4633
4734impl ops:: BitOr for Diverges {
4835 type Output = Self ;
4936 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)
5139 }
5240}
5341
@@ -64,15 +52,25 @@ impl ops::BitOrAssign for Diverges {
6452}
6553
6654impl 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+ }
7060 }
7161
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+ }
7768 }
7869}
70+
71+ #[ derive( Clone , Copy , Debug ) ]
72+ pub ( crate ) enum DivergeReason {
73+ AllArmsDiverge ,
74+ NeverPattern ,
75+ Other ,
76+ }
0 commit comments