]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/check/diverges.rs
Auto merge of #102189 - davidtwco:translation-derive-enums, r=compiler-errors
[rust.git] / compiler / rustc_typeck / src / check / diverges.rs
1 use rustc_span::source_map::DUMMY_SP;
2 use rustc_span::{self, Span};
3 use std::{cmp, ops};
4
5 /// Tracks whether executing a node may exit normally (versus
6 /// return/break/panic, which "diverge", leaving dead code in their
7 /// wake). Tracked semi-automatically (through type variables marked
8 /// as diverging), with some manual adjustments for control-flow
9 /// primitives (approximating a CFG).
10 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
11 pub enum Diverges {
12     /// Potentially unknown, some cases converge,
13     /// others require a CFG to determine them.
14     Maybe,
15
16     /// Definitely known to diverge and therefore
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     },
32
33     /// Same as `Always` but with a reachability
34     /// warning already emitted.
35     WarnedAlways,
36 }
37
38 // Convenience impls for combining `Diverges`.
39
40 impl ops::BitAnd for Diverges {
41     type Output = Self;
42     fn bitand(self, other: Self) -> Self {
43         cmp::min(self, other)
44     }
45 }
46
47 impl ops::BitOr for Diverges {
48     type Output = Self;
49     fn bitor(self, other: Self) -> Self {
50         cmp::max(self, other)
51     }
52 }
53
54 impl ops::BitAndAssign for Diverges {
55     fn bitand_assign(&mut self, other: Self) {
56         *self = *self & other;
57     }
58 }
59
60 impl ops::BitOrAssign for Diverges {
61     fn bitor_assign(&mut self, other: Self) {
62         *self = *self | other;
63     }
64 }
65
66 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 }
70     }
71
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 }
77     }
78 }