Skip to main content

rustc_session/options/
mitigation_coverage.rs

1use std::collections::{BTreeMap, BTreeSet};
2use std::str::FromStr;
3
4use rustc_macros::{BlobDecodable, Encodable};
5use rustc_span::edition::Edition;
6use rustc_target::spec::StackProtector;
7
8use crate::Session;
9use crate::config::Options;
10use crate::options::CFGuard;
11
12#[derive(#[automatically_derived]
impl ::core::marker::Copy for DeniedPartialMitigationLevel { }Copy, #[automatically_derived]
impl ::core::clone::Clone for DeniedPartialMitigationLevel {
    #[inline]
    fn clone(&self) -> DeniedPartialMitigationLevel {
        let _: ::core::clone::AssertParamIsClone<bool>;
        let _: ::core::clone::AssertParamIsClone<StackProtector>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for DeniedPartialMitigationLevel {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            DeniedPartialMitigationLevel::Enabled(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Enabled", &__self_0),
            DeniedPartialMitigationLevel::StackProtector(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "StackProtector", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for DeniedPartialMitigationLevel {
    #[inline]
    fn eq(&self, other: &DeniedPartialMitigationLevel) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (DeniedPartialMitigationLevel::Enabled(__self_0),
                    DeniedPartialMitigationLevel::Enabled(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (DeniedPartialMitigationLevel::StackProtector(__self_0),
                    DeniedPartialMitigationLevel::StackProtector(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DeniedPartialMitigationLevel {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<bool>;
        let _: ::core::cmp::AssertParamIsEq<StackProtector>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for DeniedPartialMitigationLevel {
    #[inline]
    fn partial_cmp(&self, other: &DeniedPartialMitigationLevel)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        match (self, other) {
            (DeniedPartialMitigationLevel::Enabled(__self_0),
                DeniedPartialMitigationLevel::Enabled(__arg1_0)) =>
                ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
            (DeniedPartialMitigationLevel::StackProtector(__self_0),
                DeniedPartialMitigationLevel::StackProtector(__arg1_0)) =>
                ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
            _ =>
                ::core::cmp::PartialOrd::partial_cmp(&__self_discr,
                    &__arg1_discr),
        }
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for DeniedPartialMitigationLevel {
    #[inline]
    fn cmp(&self, other: &DeniedPartialMitigationLevel)
        -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
            ::core::cmp::Ordering::Equal =>
                match (self, other) {
                    (DeniedPartialMitigationLevel::Enabled(__self_0),
                        DeniedPartialMitigationLevel::Enabled(__arg1_0)) =>
                        ::core::cmp::Ord::cmp(__self_0, __arg1_0),
                    (DeniedPartialMitigationLevel::StackProtector(__self_0),
                        DeniedPartialMitigationLevel::StackProtector(__arg1_0)) =>
                        ::core::cmp::Ord::cmp(__self_0, __arg1_0),
                    _ => unsafe { ::core::intrinsics::unreachable() }
                },
            cmp => cmp,
        }
    }
}Ord, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for DeniedPartialMitigationLevel {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        DeniedPartialMitigationLevel::Enabled(ref __binding_0) => {
                            0usize
                        }
                        DeniedPartialMitigationLevel::StackProtector(ref __binding_0)
                            => {
                            1usize
                        }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    DeniedPartialMitigationLevel::Enabled(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    DeniedPartialMitigationLevel::StackProtector(ref __binding_0)
                        => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::BlobDecoder> ::rustc_serialize::Decodable<__D>
            for DeniedPartialMitigationLevel {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        DeniedPartialMitigationLevel::Enabled(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => {
                        DeniedPartialMitigationLevel::StackProtector(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `DeniedPartialMitigationLevel`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };BlobDecodable)]
13pub enum DeniedPartialMitigationLevel {
14    // Enabled(false) should be the bottom of the Ord hierarchy
15    Enabled(bool),
16    StackProtector(StackProtector),
17}
18
19impl DeniedPartialMitigationLevel {
20    pub fn level_str(&self) -> &'static str {
21        match self {
22            DeniedPartialMitigationLevel::StackProtector(StackProtector::All) => "=all",
23            DeniedPartialMitigationLevel::StackProtector(StackProtector::Basic) => "=basic",
24            DeniedPartialMitigationLevel::StackProtector(StackProtector::Strong) => "=strong",
25            // currently `=disabled` should not appear
26            DeniedPartialMitigationLevel::Enabled(false) => "=disabled",
27            DeniedPartialMitigationLevel::StackProtector(StackProtector::None)
28            | DeniedPartialMitigationLevel::Enabled(true) => "",
29        }
30    }
31}
32
33impl std::fmt::Display for DeniedPartialMitigationLevel {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        match self {
36            DeniedPartialMitigationLevel::StackProtector(StackProtector::All) => {
37                f.write_fmt(format_args!("all"))write!(f, "all")
38            }
39            DeniedPartialMitigationLevel::StackProtector(StackProtector::Basic) => {
40                f.write_fmt(format_args!("basic"))write!(f, "basic")
41            }
42            DeniedPartialMitigationLevel::StackProtector(StackProtector::Strong) => {
43                f.write_fmt(format_args!("strong"))write!(f, "strong")
44            }
45            DeniedPartialMitigationLevel::Enabled(true) => {
46                f.write_fmt(format_args!("enabled"))write!(f, "enabled")
47            }
48            DeniedPartialMitigationLevel::StackProtector(StackProtector::None)
49            | DeniedPartialMitigationLevel::Enabled(false) => {
50                f.write_fmt(format_args!("disabled"))write!(f, "disabled")
51            }
52        }
53    }
54}
55
56impl From<bool> for DeniedPartialMitigationLevel {
57    fn from(value: bool) -> Self {
58        DeniedPartialMitigationLevel::Enabled(value)
59    }
60}
61
62impl From<StackProtector> for DeniedPartialMitigationLevel {
63    fn from(value: StackProtector) -> Self {
64        DeniedPartialMitigationLevel::StackProtector(value)
65    }
66}
67
68#[derive(#[automatically_derived]
impl ::core::marker::Copy for MitigationStatus { }Copy, #[automatically_derived]
impl ::core::clone::Clone for MitigationStatus {
    #[inline]
    fn clone(&self) -> MitigationStatus {
        let _: ::core::clone::AssertParamIsClone<usize>;
        let _: ::core::clone::AssertParamIsClone<Option<bool>>;
        *self
    }
}Clone)]
69struct MitigationStatus {
70    // This is the index of the option in the command line. This is needed because
71    // re-enabling a mitigation resets the partial mitigation status if it's later in the command
72    // line, and this works across `-C` and `-Z` args.
73    //
74    // e.g. `-Z stack-protector=strong` resets `-C allow-partial-mitigations=stack-protector`.
75    index: usize,
76    allowed: Option<bool>,
77}
78
79#[derive(#[automatically_derived]
impl ::core::clone::Clone for MitigationCoverageMap {
    #[inline]
    fn clone(&self) -> MitigationCoverageMap {
        MitigationCoverageMap { map: ::core::clone::Clone::clone(&self.map) }
    }
}Clone, #[automatically_derived]
impl ::core::default::Default for MitigationCoverageMap {
    #[inline]
    fn default() -> MitigationCoverageMap {
        MitigationCoverageMap { map: ::core::default::Default::default() }
    }
}Default)]
80pub struct MitigationCoverageMap {
81    map: BTreeMap<DeniedPartialMitigationKind, MitigationStatus>,
82}
83
84impl MitigationCoverageMap {
85    fn apply_mitigation(
86        &mut self,
87        kind: DeniedPartialMitigationKind,
88        index: usize,
89        allowed: Option<bool>,
90    ) {
91        self.map
92            .entry(kind)
93            .and_modify(|e| {
94                if index >= e.index {
95                    *e = MitigationStatus { index, allowed }
96                }
97            })
98            .or_insert(MitigationStatus { index, allowed });
99    }
100
101    pub(crate) fn handle_allowdeny_mitigation_option(
102        &mut self,
103        v: Option<&str>,
104        index: usize,
105        allowed: bool,
106    ) -> bool {
107        match v {
108            Some(s) => {
109                for sub in s.split(',') {
110                    match sub.parse() {
111                        Ok(kind) => self.apply_mitigation(kind, index, Some(allowed)),
112                        Err(_) => return false,
113                    }
114                }
115                true
116            }
117            None => false,
118        }
119    }
120
121    pub(crate) fn reset_mitigation(&mut self, kind: DeniedPartialMitigationKind, index: usize) {
122        self.apply_mitigation(kind, index, None);
123    }
124}
125
126pub struct DeniedPartialMitigationKindParseError;
127
128macro_rules! intersperse {
129    ($sep:expr, ($first:expr $(, $rest:expr)* $(,)?)) => {
130        concat!($first $(, $sep, $rest)*)
131    };
132}
133
134macro_rules! denied_partial_mitigations {
135    ([$self:ident] enum $kind:ident {$(($name:ident, $text:expr, $since:ident, $code:expr)),*}) => {
136        #[allow(non_camel_case_types)]
137        #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Encodable, BlobDecodable)]
138        pub enum DeniedPartialMitigationKind {
139            $($name),*
140        }
141
142        impl std::fmt::Display for DeniedPartialMitigationKind {
143            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144                match self {
145                    $(DeniedPartialMitigationKind::$name => write!(f, $text)),*
146                }
147            }
148        }
149
150        impl DeniedPartialMitigationKind {
151            pub(crate) const KINDS: &'static str = concat!("comma-separated list of mitigation kinds (available: ",
152                intersperse!(", ", ($(concat!("`", $text, "`")),*)), ")");
153        }
154
155        impl FromStr for DeniedPartialMitigationKind {
156            type Err = DeniedPartialMitigationKindParseError;
157
158            fn from_str(v: &str) -> Result<DeniedPartialMitigationKind, DeniedPartialMitigationKindParseError> {
159                match v {
160                    $($text => Ok(DeniedPartialMitigationKind::$name)),*
161                    ,
162                    _ => Err(DeniedPartialMitigationKindParseError),
163                }
164            }
165        }
166
167        #[allow(unused)]
168        impl DeniedPartialMitigationKind {
169            pub fn allowed_by_default_at(&self, edition: Edition) -> bool {
170                let denied_since = match self {
171                    // Should change the denied-since edition of StackProtector to 2015
172                    // (all editions) when `-C stack-protector` is stabilized.
173                    $(DeniedPartialMitigationKind::$name => Edition::$since),*
174                };
175                edition < denied_since
176            }
177        }
178
179        impl Options {
180            pub fn all_denied_partial_mitigations(&self) -> impl Iterator<Item = DeniedPartialMitigationKind> {
181                [$(DeniedPartialMitigationKind::$name),*].into_iter()
182            }
183        }
184
185        impl Session {
186            pub fn gather_enabled_denied_partial_mitigations(&$self) -> Vec<DeniedPartialMitigation> {
187                let mut mitigations = [
188                    $(
189                    DeniedPartialMitigation {
190                        kind: DeniedPartialMitigationKind::$name,
191                        level: From::from($code),
192                    }
193                    ),*
194                ];
195                mitigations.sort();
196                mitigations.into_iter().collect()
197            }
198        }
199    }
200}
201
202#[allow(non_camel_case_types)]
pub enum DeniedPartialMitigationKind { stack_protector, control_flow_guard, }
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::marker::Copy for DeniedPartialMitigationKind { }
#[automatically_derived]
#[doc(hidden)]
#[allow(non_camel_case_types)]
unsafe impl ::core::clone::TrivialClone for DeniedPartialMitigationKind { }
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::clone::Clone for DeniedPartialMitigationKind {
    #[inline]
    fn clone(&self) -> DeniedPartialMitigationKind { *self }
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::fmt::Debug for DeniedPartialMitigationKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                DeniedPartialMitigationKind::stack_protector =>
                    "stack_protector",
                DeniedPartialMitigationKind::control_flow_guard =>
                    "control_flow_guard",
            })
    }
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::marker::StructuralPartialEq for DeniedPartialMitigationKind { }
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialEq for DeniedPartialMitigationKind {
    #[inline]
    fn eq(&self, other: &DeniedPartialMitigationKind) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::Eq for DeniedPartialMitigationKind {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::hash::Hash for DeniedPartialMitigationKind {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialOrd for DeniedPartialMitigationKind {
    #[inline]
    fn partial_cmp(&self, other: &DeniedPartialMitigationKind)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::Ord for DeniedPartialMitigationKind {
    #[inline]
    fn cmp(&self, other: &DeniedPartialMitigationKind)
        -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}
const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for DeniedPartialMitigationKind {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        DeniedPartialMitigationKind::stack_protector => { 0usize }
                        DeniedPartialMitigationKind::control_flow_guard => {
                            1usize
                        }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    DeniedPartialMitigationKind::stack_protector => {}
                    DeniedPartialMitigationKind::control_flow_guard => {}
                }
            }
        }
    };
const _: () =
    {
        impl<__D: ::rustc_span::BlobDecoder> ::rustc_serialize::Decodable<__D>
            for DeniedPartialMitigationKind {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { DeniedPartialMitigationKind::stack_protector }
                    1usize => {
                        DeniedPartialMitigationKind::control_flow_guard
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `DeniedPartialMitigationKind`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };
impl std::fmt::Display for DeniedPartialMitigationKind {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            DeniedPartialMitigationKind::stack_protector =>
                f.write_fmt(format_args!("stack-protector")),
            DeniedPartialMitigationKind::control_flow_guard =>
                f.write_fmt(format_args!("control-flow-guard")),
        }
    }
}
impl DeniedPartialMitigationKind {
    pub(crate) const KINDS: &'static str =
        "comma-separated list of mitigation kinds (available: `stack-protector`, `control-flow-guard`)";
}
impl FromStr for DeniedPartialMitigationKind {
    type Err = DeniedPartialMitigationKindParseError;
    fn from_str(v: &str)
        ->
            Result<DeniedPartialMitigationKind,
            DeniedPartialMitigationKindParseError> {
        match v {
            "stack-protector" =>
                Ok(DeniedPartialMitigationKind::stack_protector),
            "control-flow-guard" =>
                Ok(DeniedPartialMitigationKind::control_flow_guard),
            _ => Err(DeniedPartialMitigationKindParseError),
        }
    }
}
#[allow(unused)]
impl DeniedPartialMitigationKind {
    pub fn allowed_by_default_at(&self, edition: Edition) -> bool {
        let denied_since =
            match self {
                DeniedPartialMitigationKind::stack_protector =>
                    Edition::EditionFuture,
                DeniedPartialMitigationKind::control_flow_guard =>
                    Edition::EditionFuture,
            };
        edition < denied_since
    }
}
impl Options {
    pub fn all_denied_partial_mitigations(&self)
        -> impl Iterator<Item = DeniedPartialMitigationKind> {
        [DeniedPartialMitigationKind::stack_protector,
                    DeniedPartialMitigationKind::control_flow_guard].into_iter()
    }
}
impl Session {
    pub fn gather_enabled_denied_partial_mitigations(&self)
        -> Vec<DeniedPartialMitigation> {
        let mut mitigations =
            [DeniedPartialMitigation {
                        kind: DeniedPartialMitigationKind::stack_protector,
                        level: From::from(self.stack_protector()),
                    },
                    DeniedPartialMitigation {
                        kind: DeniedPartialMitigationKind::control_flow_guard,
                        level: From::from(self.opts.cg.control_flow_guard ==
                                CFGuard::Checks),
                    }];
        mitigations.sort();
        mitigations.into_iter().collect()
    }
}denied_partial_mitigations! {
203    [self]
204    enum DeniedPartialMitigationKind {
205        // The mitigation name should match the option name in rustc_session::options,
206        // to allow for resetting the mitigation
207        (stack_protector, "stack-protector", EditionFuture, self.stack_protector()),
208        (control_flow_guard, "control-flow-guard", EditionFuture, self.opts.cg.control_flow_guard == CFGuard::Checks)
209    }
210}
211
212/// A mitigation that cannot be partially enabled (see
213/// [RFC 3855](https://github.com/rust-lang/rfcs/pull/3855)), but are currently enabled for this
214/// crate.
215#[derive(#[automatically_derived]
impl ::core::marker::Copy for DeniedPartialMitigation { }Copy, #[automatically_derived]
impl ::core::clone::Clone for DeniedPartialMitigation {
    #[inline]
    fn clone(&self) -> DeniedPartialMitigation {
        let _: ::core::clone::AssertParamIsClone<DeniedPartialMitigationKind>;
        let _:
                ::core::clone::AssertParamIsClone<DeniedPartialMitigationLevel>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for DeniedPartialMitigation {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "DeniedPartialMitigation", "kind", &self.kind, "level",
            &&self.level)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for DeniedPartialMitigation {
    #[inline]
    fn eq(&self, other: &DeniedPartialMitigation) -> bool {
        self.kind == other.kind && self.level == other.level
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DeniedPartialMitigation {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<DeniedPartialMitigationKind>;
        let _: ::core::cmp::AssertParamIsEq<DeniedPartialMitigationLevel>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for DeniedPartialMitigation {
    #[inline]
    fn partial_cmp(&self, other: &DeniedPartialMitigation)
        -> ::core::option::Option<::core::cmp::Ordering> {
        match ::core::cmp::PartialOrd::partial_cmp(&self.kind, &other.kind) {
            ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
                ::core::cmp::PartialOrd::partial_cmp(&self.level,
                    &other.level),
            cmp => cmp,
        }
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for DeniedPartialMitigation {
    #[inline]
    fn cmp(&self, other: &DeniedPartialMitigation) -> ::core::cmp::Ordering {
        match ::core::cmp::Ord::cmp(&self.kind, &other.kind) {
            ::core::cmp::Ordering::Equal =>
                ::core::cmp::Ord::cmp(&self.level, &other.level),
            cmp => cmp,
        }
    }
}Ord, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for DeniedPartialMitigation {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    DeniedPartialMitigation {
                        kind: ref __binding_0, level: ref __binding_1 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::BlobDecoder> ::rustc_serialize::Decodable<__D>
            for DeniedPartialMitigation {
            fn decode(__decoder: &mut __D) -> Self {
                DeniedPartialMitigation {
                    kind: ::rustc_serialize::Decodable::decode(__decoder),
                    level: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };BlobDecodable)]
216pub struct DeniedPartialMitigation {
217    pub kind: DeniedPartialMitigationKind,
218    pub level: DeniedPartialMitigationLevel,
219}
220
221impl Options {
222    // Return the list of mitigations that are allowed to be partial
223    pub fn allowed_partial_mitigations(
224        &self,
225        edition: Edition,
226    ) -> impl Iterator<Item = DeniedPartialMitigationKind> {
227        let mut result: BTreeSet<_> = self
228            .all_denied_partial_mitigations()
229            .filter(|mitigation| mitigation.allowed_by_default_at(edition))
230            .collect();
231        for (kind, MitigationStatus { index: _, allowed }) in &self.mitigation_coverage_map.map {
232            match allowed {
233                Some(true) => {
234                    result.insert(*kind);
235                }
236                Some(false) => {
237                    result.remove(kind);
238                }
239                None => {}
240            }
241        }
242        result.into_iter()
243    }
244}