clippy_utils/ty/type_certainty/
certainty.rs1use rustc_hir::def_id::DefId;
2use std::fmt::Debug;
3
4#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5pub enum Certainty {
6 Uncertain,
8
9 Certain(Option<DefId>),
13
14 Contradiction,
16}
17
18pub trait Meet {
19 fn meet(self, other: Self) -> Self;
20}
21
22pub trait TryJoin: Sized {
23 fn try_join(self, other: Self) -> Option<Self>;
24}
25
26impl Meet for Option<DefId> {
27 fn meet(self, other: Self) -> Self {
28 match (self, other) {
29 (None, _) | (_, None) => None,
30 (Some(lhs), Some(rhs)) => (lhs == rhs).then_some(lhs),
31 }
32 }
33}
34
35impl TryJoin for Option<DefId> {
36 fn try_join(self, other: Self) -> Option<Self> {
37 match (self, other) {
38 (Some(lhs), Some(rhs)) => (lhs == rhs).then_some(Some(lhs)),
39 (Some(def_id), _) | (_, Some(def_id)) => Some(Some(def_id)),
40 (None, None) => Some(None),
41 }
42 }
43}
44
45impl Meet for Certainty {
46 fn meet(self, other: Self) -> Self {
47 match (self, other) {
48 (Certainty::Uncertain, _) | (_, Certainty::Uncertain) => Certainty::Uncertain,
49 (Certainty::Certain(lhs), Certainty::Certain(rhs)) => Certainty::Certain(lhs.meet(rhs)),
50 (Certainty::Certain(inner), _) | (_, Certainty::Certain(inner)) => Certainty::Certain(inner),
51 (Certainty::Contradiction, Certainty::Contradiction) => Certainty::Contradiction,
52 }
53 }
54}
55
56impl Certainty {
57 pub fn join(self, other: Self) -> Self {
61 match (self, other) {
62 (Certainty::Contradiction, _) | (_, Certainty::Contradiction) => Certainty::Contradiction,
63
64 (Certainty::Certain(lhs), Certainty::Certain(rhs)) => {
65 if let Some(inner) = lhs.try_join(rhs) {
66 Certainty::Certain(inner)
67 } else {
68 debug_assert!(false, "Contradiction with {lhs:?} and {rhs:?}");
69 Certainty::Contradiction
70 }
71 },
72
73 (Certainty::Certain(inner), _) | (_, Certainty::Certain(inner)) => Certainty::Certain(inner),
74
75 (Certainty::Uncertain, Certainty::Uncertain) => Certainty::Uncertain,
76 }
77 }
78
79 pub fn join_clearing_def_ids(self, other: Self) -> Self {
83 self.clear_def_id().join(other.clear_def_id())
84 }
85
86 pub fn clear_def_id(self) -> Certainty {
87 if matches!(self, Certainty::Certain(_)) {
88 Certainty::Certain(None)
89 } else {
90 self
91 }
92 }
93
94 pub fn with_def_id(self, def_id: DefId) -> Certainty {
95 if matches!(self, Certainty::Certain(_)) {
96 Certainty::Certain(Some(def_id))
97 } else {
98 self
99 }
100 }
101
102 pub fn to_def_id(self) -> Option<DefId> {
103 match self {
104 Certainty::Certain(inner) => inner,
105 _ => None,
106 }
107 }
108
109 pub fn is_certain(self) -> bool {
110 matches!(self, Self::Certain(_))
111 }
112}
113
114pub fn meet(iter: impl Iterator<Item = Certainty>) -> Certainty {
116 iter.fold(Certainty::Certain(None), Certainty::meet)
117}
118
119pub fn join(iter: impl Iterator<Item = Certainty>) -> Certainty {
121 iter.fold(Certainty::Uncertain, Certainty::join)
122}