summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs
blob: 5027db44561798d1ba05fe0e692af592da2612b5 (plain)
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
// aux-build:helper.rs

#![warn(clippy::borrow_interior_mutable_const)]
#![allow(clippy::declare_interior_mutable_const)]

// this file (mostly) replicates its `declare` counterpart. Please see it for more discussions.

extern crate helper;

use std::cell::Cell;
use std::sync::atomic::AtomicUsize;

enum OptionalCell {
    Unfrozen(Cell<bool>),
    Frozen,
}

const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true));
const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;

fn borrow_optional_cell() {
    let _ = &UNFROZEN_VARIANT; //~ ERROR interior mutability
    let _ = &FROZEN_VARIANT;
}

trait AssocConsts {
    const TO_BE_UNFROZEN_VARIANT: OptionalCell;
    const TO_BE_FROZEN_VARIANT: OptionalCell;

    const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
    const DEFAULTED_ON_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;

    fn function() {
        // This is the "suboptimal behavior" mentioned in `is_value_unfrozen`
        // caused by a similar reason to unfrozen types without any default values
        // get linted even if it has frozen variants'.
        let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable

        // The lint ignores default values because an impl of this trait can set
        // an unfrozen variant to `DEFAULTED_ON_FROZEN_VARIANT` and use the default impl for `function`.
        let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior mutable
    }
}

impl AssocConsts for u64 {
    const TO_BE_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
    const TO_BE_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;

    fn function() {
        let _ = &<Self as AssocConsts>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
        let _ = &<Self as AssocConsts>::TO_BE_FROZEN_VARIANT;
        let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mutable
        let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT;
    }
}

trait AssocTypes {
    type ToBeUnfrozen;

    const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen>;
    const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen>;

    // there's no need to test here because it's the exactly same as `trait::AssocTypes`
    fn function();
}

impl AssocTypes for u64 {
    type ToBeUnfrozen = AtomicUsize;

    const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable
    const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen> = None;

    fn function() {
        let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
        let _ = &<Self as AssocTypes>::TO_BE_FROZEN_VARIANT;
    }
}

enum BothOfCellAndGeneric<T> {
    Unfrozen(Cell<*const T>),
    Generic(*const T),
    Frozen(usize),
}

impl<T> BothOfCellAndGeneric<T> {
    const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable
    const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable
    const FROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Frozen(5);

    fn function() {
        let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability
        let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability
        let _ = &Self::FROZEN_VARIANT;
    }
}

fn main() {
    // constants defined in foreign crates
    let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR interior mutability
    let _ = &helper::WRAPPED_PRIVATE_FROZEN_VARIANT;
}