]> git.lizzy.rs Git - rust.git/blob - tests/ui/declare_interior_mutable_const.rs
add `WRAPPED_SELF: Option<Self>` in the test
[rust.git] / tests / ui / declare_interior_mutable_const.rs
1 #![warn(clippy::declare_interior_mutable_const)]
2
3 use std::borrow::Cow;
4 use std::cell::Cell;
5 use std::fmt::Display;
6 use std::sync::atomic::AtomicUsize;
7 use std::sync::Once;
8
9 const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable
10 const CELL: Cell<usize> = Cell::new(6); //~ ERROR interior mutable
11 const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
12 //~^ ERROR interior mutable
13
14 macro_rules! declare_const {
15     ($name:ident: $ty:ty = $e:expr) => {
16         const $name: $ty = $e;
17     };
18 }
19 declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable
20
21 // const ATOMIC_REF: &AtomicUsize = &AtomicUsize::new(7); // This will simply trigger E0492.
22
23 const INTEGER: u8 = 8;
24 const STRING: String = String::new();
25 const STR: &str = "012345";
26 const COW: Cow<str> = Cow::Borrowed("abcdef");
27 //^ note: a const item of Cow is used in the `postgres` package.
28
29 const NO_ANN: &dyn Display = &70;
30
31 static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING);
32 //^ there should be no lints on this line
33
34 #[allow(clippy::declare_interior_mutable_const)]
35 const ONCE_INIT: Once = Once::new();
36
37 // a constant whose type is a concrete type should be linted at the definition site.
38 trait ConcreteTypes {
39     const ATOMIC: AtomicUsize; //~ ERROR interior mutable
40     const INTEGER: u64;
41     const STRING: String;
42     declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR interior mutable
43 }
44
45 impl ConcreteTypes for u64 {
46     const ATOMIC: AtomicUsize = AtomicUsize::new(9);
47     const INTEGER: u64 = 10;
48     const STRING: String = String::new();
49 }
50
51 // a helper trait used below
52 trait ConstDefault {
53     const DEFAULT: Self;
54 }
55
56 // a constant whose type is a generic type should be linted at the implementation site.
57 trait GenericTypes<T, U> {
58     const TO_REMAIN_GENERIC: T;
59     const TO_BE_CONCRETE: U;
60
61     const HAVING_DEFAULT: T = Self::TO_REMAIN_GENERIC;
62     declare_const!(IN_MACRO: T = Self::TO_REMAIN_GENERIC);
63 }
64
65 impl<T: ConstDefault> GenericTypes<T, AtomicUsize> for u64 {
66     const TO_REMAIN_GENERIC: T = T::DEFAULT;
67     const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable
68 }
69
70 // a helper type used below
71 struct Wrapper<T>(T);
72
73 // a constant whose type is an associated type should be linted at the implementation site, too.
74 trait AssocTypes {
75     type ToBeFrozen;
76     type ToBeUnfrozen;
77     type ToBeGenericParam;
78
79     const TO_BE_FROZEN: Self::ToBeFrozen;
80     const TO_BE_UNFROZEN: Self::ToBeUnfrozen;
81     const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen>;
82     // to ensure it can handle things when a generic type remains after normalization.
83     const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam>;
84 }
85
86 impl<T: ConstDefault> AssocTypes for Vec<T> {
87     type ToBeFrozen = u16;
88     type ToBeUnfrozen = AtomicUsize;
89     type ToBeGenericParam = T;
90
91     const TO_BE_FROZEN: Self::ToBeFrozen = 12;
92     const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable
93     const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable
94     const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam> = Wrapper(T::DEFAULT);
95 }
96
97 // a helper trait used below
98 trait AssocTypesHelper {
99     type NotToBeBounded;
100     type ToBeBounded;
101
102     const NOT_TO_BE_BOUNDED: Self::NotToBeBounded;
103 }
104
105 // a constant whose type is an assoc type originated from a generic param bounded at the definition
106 // site should be linted at there.
107 trait AssocTypesFromGenericParam<T>
108 where
109     T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
110 {
111     const NOT_BOUNDED: T::NotToBeBounded;
112     const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable
113 }
114
115 impl<T> AssocTypesFromGenericParam<T> for u64
116 where
117     T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
118 {
119     // an associated type could remain unknown in a trait impl.
120     const NOT_BOUNDED: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
121     const BOUNDED: T::ToBeBounded = AtomicUsize::new(15);
122 }
123
124 // a constant whose type is `Self` should be linted at the implementation site as well.
125 // (`Option` requires `Sized` bound.)
126 trait SelfType: Sized {
127     const SELF: Self;
128     // this was the one in the original issue (#5050).
129     const WRAPPED_SELF: Option<Self>;
130 }
131
132 impl SelfType for u64 {
133     const SELF: Self = 16;
134     const WRAPPED_SELF: Option<Self> = Some(20);
135 }
136
137 impl SelfType for AtomicUsize {
138     // this (interior mutable `Self` const) exists in `parking_lot`.
139     // `const_trait_impl` will replace it in the future, hopefully.
140     const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable
141     const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21)); //~ ERROR interior mutable
142 }
143
144 // Even though a constant contains a generic type, if it also have a interior mutable type,
145 // it should be linted at the definition site.
146 trait BothOfCellAndGeneric<T> {
147     // this is a false negative in the current implementation.
148     const DIRECT: Cell<T>;
149     const INDIRECT: Cell<*const T>; //~ ERROR interior mutable
150 }
151
152 impl<T: ConstDefault> BothOfCellAndGeneric<T> for u64 {
153     const DIRECT: Cell<T> = Cell::new(T::DEFAULT);
154     const INDIRECT: Cell<*const T> = Cell::new(std::ptr::null());
155 }
156
157 struct Local<T>(T);
158
159 // a constant in an inherent impl are essentially the same as a normal const item
160 // except there can be a generic or associated type.
161 impl<T> Local<T>
162 where
163     T: ConstDefault + AssocTypesHelper<ToBeBounded = AtomicUsize>,
164 {
165     const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable
166     const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy");
167
168     const GENERIC_TYPE: T = T::DEFAULT;
169
170     const ASSOC_TYPE: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
171     const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable
172 }
173
174 fn main() {}