summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/tests/ui/borrow_interior_mutable_const
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/tests/ui/borrow_interior_mutable_const')
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs17
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs101
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr75
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs104
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr115
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs202
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr123
7 files changed, 737 insertions, 0 deletions
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs
new file mode 100644
index 000000000..f13733af3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs
@@ -0,0 +1,17 @@
+// this file solely exists to test constants defined in foreign crates.
+// As the most common case is the `http` crate, it replicates `http::HeadewrName`'s structure.
+
+#![allow(clippy::declare_interior_mutable_const)]
+#![allow(unused_tuple_struct_fields)]
+
+use std::sync::atomic::AtomicUsize;
+
+enum Private<T> {
+ ToBeUnfrozen(T),
+ Frozen(usize),
+}
+
+pub struct Wrapper(Private<AtomicUsize>);
+
+pub const WRAPPED_PRIVATE_UNFROZEN_VARIANT: Wrapper = Wrapper(Private::ToBeUnfrozen(AtomicUsize::new(6)));
+pub const WRAPPED_PRIVATE_FROZEN_VARIANT: Wrapper = Wrapper(Private::Frozen(7));
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs
new file mode 100644
index 000000000..5027db445
--- /dev/null
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs
@@ -0,0 +1,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;
+}
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr
new file mode 100644
index 000000000..654a1ee7d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr
@@ -0,0 +1,75 @@
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/enums.rs:22:14
+ |
+LL | let _ = &UNFROZEN_VARIANT; //~ ERROR interior mutability
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/enums.rs:37:18
+ |
+LL | let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/enums.rs:41:18
+ |
+LL | let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/enums.rs:50:18
+ |
+LL | let _ = &<Self as AssocConsts>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/enums.rs:52:18
+ |
+LL | let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/enums.rs:74:18
+ |
+LL | let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/enums.rs:91:18
+ |
+LL | let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/enums.rs:92:18
+ |
+LL | let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/enums.rs:99:14
+ |
+LL | let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR interior mutability
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs
new file mode 100644
index 000000000..eefeb1dec
--- /dev/null
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs
@@ -0,0 +1,104 @@
+#![warn(clippy::borrow_interior_mutable_const)]
+#![allow(clippy::declare_interior_mutable_const, clippy::needless_borrow)]
+#![allow(const_item_mutation)]
+
+use std::borrow::Cow;
+use std::cell::{Cell, UnsafeCell};
+use std::fmt::Display;
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::Once;
+
+const ATOMIC: AtomicUsize = AtomicUsize::new(5);
+const CELL: Cell<usize> = Cell::new(6);
+const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
+const INTEGER: u8 = 8;
+const STRING: String = String::new();
+const STR: &str = "012345";
+const COW: Cow<str> = Cow::Borrowed("abcdef");
+const NO_ANN: &dyn Display = &70;
+static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING);
+const ONCE_INIT: Once = Once::new();
+
+// This is just a pointer that can be safely dereferenced,
+// it's semantically the same as `&'static T`;
+// but it isn't allowed to make a static reference from an arbitrary integer value at the moment.
+// For more information, please see the issue #5918.
+pub struct StaticRef<T> {
+ ptr: *const T,
+}
+
+impl<T> StaticRef<T> {
+ /// Create a new `StaticRef` from a raw pointer
+ ///
+ /// ## Safety
+ ///
+ /// Callers must pass in a reference to statically allocated memory which
+ /// does not overlap with other values.
+ pub const unsafe fn new(ptr: *const T) -> StaticRef<T> {
+ StaticRef { ptr }
+ }
+}
+
+impl<T> std::ops::Deref for StaticRef<T> {
+ type Target = T;
+
+ fn deref(&self) -> &'static T {
+ unsafe { &*self.ptr }
+ }
+}
+
+// use a tuple to make sure referencing a field behind a pointer isn't linted.
+const CELL_REF: StaticRef<(UnsafeCell<u32>,)> = unsafe { StaticRef::new(std::ptr::null()) };
+
+fn main() {
+ ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
+ assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
+
+ let _once = ONCE_INIT;
+ let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
+ let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
+ let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
+ let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
+ let _atomic_into_inner = ATOMIC.into_inner();
+ // these should be all fine.
+ let _twice = (ONCE_INIT, ONCE_INIT);
+ let _ref_twice = &(ONCE_INIT, ONCE_INIT);
+ let _ref_once = &(ONCE_INIT, ONCE_INIT).0;
+ let _array_twice = [ONCE_INIT, ONCE_INIT];
+ let _ref_array_twice = &[ONCE_INIT, ONCE_INIT];
+ let _ref_array_once = &[ONCE_INIT, ONCE_INIT][0];
+
+ // referencing projection is still bad.
+ let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
+ let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
+ let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
+ let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
+ let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
+ let _ = &*ATOMIC_TUPLE.1;
+ let _ = &ATOMIC_TUPLE.2;
+ let _ = (&&&&ATOMIC_TUPLE).0;
+ let _ = (&&&&ATOMIC_TUPLE).2;
+ let _ = ATOMIC_TUPLE.0;
+ let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
+ let _ = ATOMIC_TUPLE.1.into_iter();
+ let _ = ATOMIC_TUPLE.2;
+ let _ = &{ ATOMIC_TUPLE };
+
+ CELL.set(2); //~ ERROR interior mutability
+ assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
+
+ assert_eq!(INTEGER, 8);
+ assert!(STRING.is_empty());
+
+ let a = ATOMIC;
+ a.store(4, Ordering::SeqCst);
+ assert_eq!(a.load(Ordering::SeqCst), 4);
+
+ STATIC_TUPLE.0.store(3, Ordering::SeqCst);
+ assert_eq!(STATIC_TUPLE.0.load(Ordering::SeqCst), 3);
+ assert!(STATIC_TUPLE.1.is_empty());
+
+ assert_eq!(NO_ANN.to_string(), "70"); // should never lint this.
+
+ let _ = &CELL_REF.0;
+}
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr
new file mode 100644
index 000000000..9a908cf30
--- /dev/null
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr
@@ -0,0 +1,115 @@
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:54:5
+ |
+LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
+ | ^^^^^^
+ |
+ = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:55:16
+ |
+LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
+ | ^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:58:22
+ |
+LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
+ | ^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:59:25
+ |
+LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
+ | ^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:60:27
+ |
+LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
+ | ^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:61:26
+ |
+LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
+ | ^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:72:14
+ |
+LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
+ | ^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:73:14
+ |
+LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
+ | ^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:74:19
+ |
+LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
+ | ^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:75:14
+ |
+LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
+ | ^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:76:13
+ |
+LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
+ | ^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:82:13
+ |
+LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
+ | ^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:87:5
+ |
+LL | CELL.set(2); //~ ERROR interior mutability
+ | ^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/others.rs:88:16
+ |
+LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
+ | ^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: aborting due to 14 previous errors
+
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
index 000000000..06b5d62e8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs
@@ -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
+}
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr
new file mode 100644
index 000000000..8f26403ab
--- /dev/null
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr
@@ -0,0 +1,123 @@
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:15:18
+ |
+LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^
+ |
+ = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:26:18
+ |
+LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:51:18
+ |
+LL | let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:86:18
+ |
+LL | let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:87:18
+ |
+LL | let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:109:18
+ |
+LL | let _ = &Self::BOUNDED; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:122:18
+ |
+LL | let _ = &Self::BOUNDED; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:151:18
+ |
+LL | let _ = &Self::SELF; //~ ERROR interior mutable
+ | ^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:152:18
+ |
+LL | let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:162:18
+ |
+LL | let _ = &Self::INDIRECT; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:172:18
+ |
+LL | let _ = &Self::INDIRECT; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:191:18
+ |
+LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:195:18
+ |
+LL | let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:200:5
+ |
+LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
+ | ^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: a `const` item with interior mutability should not be borrowed
+ --> $DIR/traits.rs:201:16
+ |
+LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability
+ | ^^^^^^^^^^^
+ |
+ = help: assign this const to a local or static variable, and use the variable here
+
+error: aborting due to 15 previous errors
+