]> git.proxmox.com Git - rustc.git/blobdiff - src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs
Update upstream source from tag 'upstream/1.52.1+dfsg1'
[rustc.git] / src / tools / clippy / tests / ui / borrow_interior_mutable_const / traits.rs
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs
new file mode 100644 (file)
index 0000000..06b5d62
--- /dev/null
@@ -0,0 +1,202 @@
+#![warn(clippy::borrow_interior_mutable_const)]
+#![allow(clippy::declare_interior_mutable_const)]
+
+// this file replicates its `declare` counterpart. Please see it for more discussions.
+
+use std::borrow::Cow;
+use std::cell::Cell;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+trait ConcreteTypes {
+    const ATOMIC: AtomicUsize;
+    const STRING: String;
+
+    fn function() {
+        let _ = &Self::ATOMIC; //~ ERROR interior mutable
+        let _ = &Self::STRING;
+    }
+}
+
+impl ConcreteTypes for u64 {
+    const ATOMIC: AtomicUsize = AtomicUsize::new(9);
+    const STRING: String = String::new();
+
+    fn function() {
+        // Lint this again since implementers can choose not to borrow it.
+        let _ = &Self::ATOMIC; //~ ERROR interior mutable
+        let _ = &Self::STRING;
+    }
+}
+
+// a helper trait used below
+trait ConstDefault {
+    const DEFAULT: Self;
+}
+
+trait GenericTypes<T, U> {
+    const TO_REMAIN_GENERIC: T;
+    const TO_BE_CONCRETE: U;
+
+    fn function() {
+        let _ = &Self::TO_REMAIN_GENERIC;
+    }
+}
+
+impl<T: ConstDefault> GenericTypes<T, AtomicUsize> for Vec<T> {
+    const TO_REMAIN_GENERIC: T = T::DEFAULT;
+    const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11);
+
+    fn function() {
+        let _ = &Self::TO_REMAIN_GENERIC;
+        let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable
+    }
+}
+
+// a helper type used below
+pub struct Wrapper<T>(T);
+
+trait AssocTypes {
+    type ToBeFrozen;
+    type ToBeUnfrozen;
+    type ToBeGenericParam;
+
+    const TO_BE_FROZEN: Self::ToBeFrozen;
+    const TO_BE_UNFROZEN: Self::ToBeUnfrozen;
+    const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen>;
+    const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam>;
+
+    fn function() {
+        let _ = &Self::TO_BE_FROZEN;
+        let _ = &Self::WRAPPED_TO_BE_UNFROZEN;
+    }
+}
+
+impl<T: ConstDefault> AssocTypes for Vec<T> {
+    type ToBeFrozen = u16;
+    type ToBeUnfrozen = AtomicUsize;
+    type ToBeGenericParam = T;
+
+    const TO_BE_FROZEN: Self::ToBeFrozen = 12;
+    const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13);
+    const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14));
+    const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam> = Wrapper(T::DEFAULT);
+
+    fn function() {
+        let _ = &Self::TO_BE_FROZEN;
+        let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable
+        let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable
+        let _ = &Self::WRAPPED_TO_BE_GENERIC_PARAM;
+    }
+}
+
+// a helper trait used below
+trait AssocTypesHelper {
+    type NotToBeBounded;
+    type ToBeBounded;
+
+    const NOT_TO_BE_BOUNDED: Self::NotToBeBounded;
+}
+
+trait AssocTypesFromGenericParam<T>
+where
+    T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
+{
+    const NOT_BOUNDED: T::NotToBeBounded;
+    const BOUNDED: T::ToBeBounded;
+
+    fn function() {
+        let _ = &Self::NOT_BOUNDED;
+        let _ = &Self::BOUNDED; //~ ERROR interior mutable
+    }
+}
+
+impl<T> AssocTypesFromGenericParam<T> for Vec<T>
+where
+    T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
+{
+    const NOT_BOUNDED: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
+    const BOUNDED: T::ToBeBounded = AtomicUsize::new(15);
+
+    fn function() {
+        let _ = &Self::NOT_BOUNDED;
+        let _ = &Self::BOUNDED; //~ ERROR interior mutable
+    }
+}
+
+trait SelfType: Sized {
+    const SELF: Self;
+    const WRAPPED_SELF: Option<Self>;
+
+    fn function() {
+        let _ = &Self::SELF;
+        let _ = &Self::WRAPPED_SELF;
+    }
+}
+
+impl SelfType for u64 {
+    const SELF: Self = 16;
+    const WRAPPED_SELF: Option<Self> = Some(20);
+
+    fn function() {
+        let _ = &Self::SELF;
+        let _ = &Self::WRAPPED_SELF;
+    }
+}
+
+impl SelfType for AtomicUsize {
+    const SELF: Self = AtomicUsize::new(17);
+    const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21));
+
+    fn function() {
+        let _ = &Self::SELF; //~ ERROR interior mutable
+        let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable
+    }
+}
+
+trait BothOfCellAndGeneric<T> {
+    const DIRECT: Cell<T>;
+    const INDIRECT: Cell<*const T>;
+
+    fn function() {
+        let _ = &Self::DIRECT;
+        let _ = &Self::INDIRECT; //~ ERROR interior mutable
+    }
+}
+
+impl<T: ConstDefault> BothOfCellAndGeneric<T> for Vec<T> {
+    const DIRECT: Cell<T> = Cell::new(T::DEFAULT);
+    const INDIRECT: Cell<*const T> = Cell::new(std::ptr::null());
+
+    fn function() {
+        let _ = &Self::DIRECT;
+        let _ = &Self::INDIRECT; //~ ERROR interior mutable
+    }
+}
+
+struct Local<T>(T);
+
+impl<T> Local<T>
+where
+    T: ConstDefault + AssocTypesHelper<ToBeBounded = AtomicUsize>,
+{
+    const ATOMIC: AtomicUsize = AtomicUsize::new(18);
+    const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy");
+
+    const GENERIC_TYPE: T = T::DEFAULT;
+
+    const ASSOC_TYPE: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
+    const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19);
+
+    fn function() {
+        let _ = &Self::ATOMIC; //~ ERROR interior mutable
+        let _ = &Self::COW;
+        let _ = &Self::GENERIC_TYPE;
+        let _ = &Self::ASSOC_TYPE;
+        let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable
+    }
+}
+
+fn main() {
+    u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
+    assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability
+}