Resolve projections during internal mutability analysis

This commit is contained in:
Pavel Grigorenko 2025-02-01 02:30:50 +03:00
parent d79f86255d
commit 58d4834097
4 changed files with 96 additions and 0 deletions

View file

@ -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,
}
}

View file

@ -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,
};

View file

@ -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);
}

View file

@ -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