about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/non_copy_const.rs6
-rw-r--r--clippy_utils/src/ty/mod.rs4
-rw-r--r--tests/ui/borrow_interior_mutable_const/projections.rs42
-rw-r--r--tests/ui/borrow_interior_mutable_const/projections.stderr44
4 files changed, 96 insertions, 0 deletions
diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index 147654675ec..0d89b4e8535 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -215,6 +215,12 @@ impl<'tcx> NonCopyConst<'tcx> {
                 .iter()
                 .zip(tys)
                 .any(|(field, ty)| Self::is_value_unfrozen_raw_inner(cx, *field, ty)),
+            ty::Alias(ty::Projection, _) => match cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) {
+                Ok(normalized_ty) if ty != normalized_ty => {
+                    Self::is_value_unfrozen_raw_inner(cx, ty::ValTree::Branch(val), normalized_ty)
+                },
+                _ => false,
+            },
             _ => false,
         }
     }
diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs
index f2bbdda7058..5201036d84d 100644
--- a/clippy_utils/src/ty/mod.rs
+++ b/clippy_utils/src/ty/mod.rs
@@ -1227,6 +1227,10 @@ impl<'tcx> InteriorMut<'tcx> {
                         .find_map(|f| self.interior_mut_ty_chain(cx, f.ty(cx.tcx, args)))
                 }
             },
+            ty::Alias(ty::Projection, _) => match cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) {
+                Ok(normalized_ty) if ty != normalized_ty => self.interior_mut_ty_chain(cx, normalized_ty),
+                _ => None,
+            },
             _ => None,
         };
 
diff --git a/tests/ui/borrow_interior_mutable_const/projections.rs b/tests/ui/borrow_interior_mutable_const/projections.rs
new file mode 100644
index 00000000000..bbe5538fbe1
--- /dev/null
+++ b/tests/ui/borrow_interior_mutable_const/projections.rs
@@ -0,0 +1,42 @@
+#![deny(clippy::borrow_interior_mutable_const)]
+#![deny(clippy::declare_interior_mutable_const)]
+
+// Inspired by https://github.com/rust-lang/rust/pull/130543#issuecomment-2364828139
+
+use std::cell::UnsafeCell;
+
+trait Trait {
+    type Assoc;
+}
+
+type Assoc<T> = <T as Trait>::Assoc;
+
+impl Trait for u8 {
+    type Assoc = UnsafeCell<u8>;
+}
+
+impl Trait for () {
+    type Assoc = ();
+}
+
+enum MaybeMutable {
+    Mutable(Assoc<u8>),
+    Immutable(Assoc<()>),
+}
+
+const CELL: Assoc<u8> = UnsafeCell::new(0); //~ ERROR: interior mutable
+const UNIT: Assoc<()> = ();
+const MUTABLE: MaybeMutable = MaybeMutable::Mutable(CELL); //~ ERROR: interior mutable
+const IMMUTABLE: MaybeMutable = MaybeMutable::Immutable(UNIT);
+
+fn print_ref<T>(t: &T) {
+    let p: *const T = t;
+    println!("{p:p}")
+}
+
+fn main() {
+    print_ref(&CELL); //~ ERROR: interior mutability
+    print_ref(&UNIT);
+    print_ref(&MUTABLE); //~ ERROR: interior mutability
+    print_ref(&IMMUTABLE);
+}
diff --git a/tests/ui/borrow_interior_mutable_const/projections.stderr b/tests/ui/borrow_interior_mutable_const/projections.stderr
new file mode 100644
index 00000000000..eabaf66560a
--- /dev/null
+++ b/tests/ui/borrow_interior_mutable_const/projections.stderr
@@ -0,0 +1,44 @@
+error: a `const` item should not be interior mutable
+  --> tests/ui/borrow_interior_mutable_const/projections.rs:27:1
+   |
+LL | const CELL: Assoc<u8> = UnsafeCell::new(0);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
+note: the lint level is defined here
+  --> tests/ui/borrow_interior_mutable_const/projections.rs:2:9
+   |
+LL | #![deny(clippy::declare_interior_mutable_const)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item should not be interior mutable
+  --> tests/ui/borrow_interior_mutable_const/projections.rs:29:1
+   |
+LL | const MUTABLE: MaybeMutable = MaybeMutable::Mutable(CELL);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
+
+error: a `const` item with interior mutability should not be borrowed
+  --> tests/ui/borrow_interior_mutable_const/projections.rs:38:16
+   |
+LL |     print_ref(&CELL);
+   |                ^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+note: the lint level is defined here
+  --> tests/ui/borrow_interior_mutable_const/projections.rs:1:9
+   |
+LL | #![deny(clippy::borrow_interior_mutable_const)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: a `const` item with interior mutability should not be borrowed
+  --> tests/ui/borrow_interior_mutable_const/projections.rs:40:16
+   |
+LL |     print_ref(&MUTABLE);
+   |                ^^^^^^^
+   |
+   = help: assign this const to a local or static variable, and use the variable here
+
+error: aborting due to 4 previous errors
+