Skip to content

Commit c40898e

Browse files
authored
declare_interior_mutable_const, borrow_interior_mutable_const: resolve <T as Trait>::AssocT projections (#14125)
changelog: [`declare_interior_mutable_const`, `borrow_interior_mutable_const`]: resolve `<T as Trait>::AssocT` projections --- This came up during rust-lang/rust#130543 where we have `<T as AtomicPrimitive>::Assoc = AtomicT` instead of just `AtomicT` and clippy failed to resolve that properly. This really needs a review, because - I don't know if `try_normalize_erasing_regions` is the right thing to call here. - I'm not sure if I peel off the correct amount of `ValTree::Branch` layers (I think I do). Also, shouldn't this lint's infrastructure rely on `Freeze` trait (rust-lang/rust#121675) instead of hardcoding a list of known-to-be-interior-mutable types? --- Previously filed this in the main rust repo (rust-lang/rust#136369), was asked to do it here instead (rust-lang/rust#136369 (comment)).
2 parents ff87bea + 58d4834 commit c40898e

File tree

4 files changed

+96
-0
lines changed

4 files changed

+96
-0
lines changed

clippy_lints/src/non_copy_const.rs

+6
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,12 @@ impl<'tcx> NonCopyConst<'tcx> {
215215
.iter()
216216
.zip(tys)
217217
.any(|(field, ty)| Self::is_value_unfrozen_raw_inner(cx, *field, ty)),
218+
ty::Alias(ty::Projection, _) => match cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) {
219+
Ok(normalized_ty) if ty != normalized_ty => {
220+
Self::is_value_unfrozen_raw_inner(cx, ty::ValTree::Branch(val), normalized_ty)
221+
},
222+
_ => false,
223+
},
218224
_ => false,
219225
}
220226
}

clippy_utils/src/ty/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,10 @@ impl<'tcx> InteriorMut<'tcx> {
12471247
.find_map(|f| self.interior_mut_ty_chain(cx, f.ty(cx.tcx, args)))
12481248
}
12491249
},
1250+
ty::Alias(ty::Projection, _) => match cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) {
1251+
Ok(normalized_ty) if ty != normalized_ty => self.interior_mut_ty_chain(cx, normalized_ty),
1252+
_ => None,
1253+
},
12501254
_ => None,
12511255
};
12521256

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#![deny(clippy::borrow_interior_mutable_const)]
2+
#![deny(clippy::declare_interior_mutable_const)]
3+
4+
// Inspired by https://github.com/rust-lang/rust/pull/130543#issuecomment-2364828139
5+
6+
use std::cell::UnsafeCell;
7+
8+
trait Trait {
9+
type Assoc;
10+
}
11+
12+
type Assoc<T> = <T as Trait>::Assoc;
13+
14+
impl Trait for u8 {
15+
type Assoc = UnsafeCell<u8>;
16+
}
17+
18+
impl Trait for () {
19+
type Assoc = ();
20+
}
21+
22+
enum MaybeMutable {
23+
Mutable(Assoc<u8>),
24+
Immutable(Assoc<()>),
25+
}
26+
27+
const CELL: Assoc<u8> = UnsafeCell::new(0); //~ ERROR: interior mutable
28+
const UNIT: Assoc<()> = ();
29+
const MUTABLE: MaybeMutable = MaybeMutable::Mutable(CELL); //~ ERROR: interior mutable
30+
const IMMUTABLE: MaybeMutable = MaybeMutable::Immutable(UNIT);
31+
32+
fn print_ref<T>(t: &T) {
33+
let p: *const T = t;
34+
println!("{p:p}")
35+
}
36+
37+
fn main() {
38+
print_ref(&CELL); //~ ERROR: interior mutability
39+
print_ref(&UNIT);
40+
print_ref(&MUTABLE); //~ ERROR: interior mutability
41+
print_ref(&IMMUTABLE);
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
error: a `const` item should not be interior mutable
2+
--> tests/ui/borrow_interior_mutable_const/projections.rs:27:1
3+
|
4+
LL | const CELL: Assoc<u8> = UnsafeCell::new(0);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
8+
note: the lint level is defined here
9+
--> tests/ui/borrow_interior_mutable_const/projections.rs:2:9
10+
|
11+
LL | #![deny(clippy::declare_interior_mutable_const)]
12+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
14+
error: a `const` item should not be interior mutable
15+
--> tests/ui/borrow_interior_mutable_const/projections.rs:29:1
16+
|
17+
LL | const MUTABLE: MaybeMutable = MaybeMutable::Mutable(CELL);
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19+
|
20+
= help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
21+
22+
error: a `const` item with interior mutability should not be borrowed
23+
--> tests/ui/borrow_interior_mutable_const/projections.rs:38:16
24+
|
25+
LL | print_ref(&CELL);
26+
| ^^^^
27+
|
28+
= help: assign this const to a local or static variable, and use the variable here
29+
note: the lint level is defined here
30+
--> tests/ui/borrow_interior_mutable_const/projections.rs:1:9
31+
|
32+
LL | #![deny(clippy::borrow_interior_mutable_const)]
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34+
35+
error: a `const` item with interior mutability should not be borrowed
36+
--> tests/ui/borrow_interior_mutable_const/projections.rs:40:16
37+
|
38+
LL | print_ref(&MUTABLE);
39+
| ^^^^^^^
40+
|
41+
= help: assign this const to a local or static variable, and use the variable here
42+
43+
error: aborting due to 4 previous errors
44+

0 commit comments

Comments
 (0)