1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Traits for determining whether we can derive traits for a thing or not.
//!
//! These traits tend to come in pairs:
//!
//! 1. A "trivial" version, whose implementations aren't allowed to recursively
//! look at other types or the results of fix point analyses.
//!
//! 2. A "normal" version, whose implementations simply query the results of a
//! fix point analysis.
//!
//! The former is used by the analyses when creating the results queried by the
//! second.

use super::context::BindgenContext;

use std::cmp;
use std::ops;

/// A trait that encapsulates the logic for whether or not we can derive `Debug`
/// for a given thing.
pub trait CanDeriveDebug {
    /// Return `true` if `Debug` can be derived for this thing, `false`
    /// otherwise.
    fn can_derive_debug(&self, ctx: &BindgenContext) -> bool;
}

/// A trait that encapsulates the logic for whether or not we can derive `Copy`
/// for a given thing.
pub trait CanDeriveCopy {
    /// Return `true` if `Copy` can be derived for this thing, `false`
    /// otherwise.
    fn can_derive_copy(&self, ctx: &BindgenContext) -> bool;
}

/// A trait that encapsulates the logic for whether or not we can derive
/// `Default` for a given thing.
pub trait CanDeriveDefault {
    /// Return `true` if `Default` can be derived for this thing, `false`
    /// otherwise.
    fn can_derive_default(&self, ctx: &BindgenContext) -> bool;
}

/// A trait that encapsulates the logic for whether or not we can derive `Hash`
/// for a given thing.
pub trait CanDeriveHash {
    /// Return `true` if `Hash` can be derived for this thing, `false`
    /// otherwise.
    fn can_derive_hash(&self, ctx: &BindgenContext) -> bool;
}

/// A trait that encapsulates the logic for whether or not we can derive
/// `PartialEq` for a given thing.
pub trait CanDerivePartialEq {
    /// Return `true` if `PartialEq` can be derived for this thing, `false`
    /// otherwise.
    fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool;
}

/// A trait that encapsulates the logic for whether or not we can derive
/// `PartialOrd` for a given thing.
pub trait CanDerivePartialOrd {
    /// Return `true` if `PartialOrd` can be derived for this thing, `false`
    /// otherwise.
    fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool;
}

/// A trait that encapsulates the logic for whether or not we can derive `Eq`
/// for a given thing.
pub trait CanDeriveEq {
    /// Return `true` if `Eq` can be derived for this thing, `false` otherwise.
    fn can_derive_eq(&self, ctx: &BindgenContext) -> bool;
}

/// A trait that encapsulates the logic for whether or not we can derive `Ord`
/// for a given thing.
pub trait CanDeriveOrd {
    /// Return `true` if `Ord` can be derived for this thing, `false` otherwise.
    fn can_derive_ord(&self, ctx: &BindgenContext) -> bool;
}

/// Whether it is possible or not to automatically derive trait for an item.
///
/// ```ignore
///         No
///          ^
///          |
///      Manually
///          ^
///          |
///         Yes
/// ```
///
/// Initially we assume that we can derive trait for all types and then
/// update our understanding as we learn more about each type.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum CanDerive {
    /// Yes, we can derive automatically.
    Yes,

    /// The only thing that stops us from automatically deriving is that
    /// array with more than maximum number of elements is used.
    ///
    /// This means we probably can "manually" implement such trait.
    Manually,

    /// No, we cannot.
    No,
}

impl Default for CanDerive {
    fn default() -> CanDerive {
        CanDerive::Yes
    }
}

impl CanDerive {
    /// Take the least upper bound of `self` and `rhs`.
    pub fn join(self, rhs: Self) -> Self {
        cmp::max(self, rhs)
    }
}

impl ops::BitOr for CanDerive {
    type Output = Self;

    fn bitor(self, rhs: Self) -> Self::Output {
        self.join(rhs)
    }
}

impl ops::BitOrAssign for CanDerive {
    fn bitor_assign(&mut self, rhs: Self) {
        *self = self.join(rhs)
    }
}