Skip to content

Commit f1810d7

Browse files
committed
introduce #[clippy::ignore_interior_mutability]
1 parent b9e2186 commit f1810d7

File tree

9 files changed

+91
-11
lines changed

9 files changed

+91
-11
lines changed

clippy_lints/src/non_copy_const.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ declare_clippy_lint! {
7070
/// no way to both create a value as a constant and modify any mutable field using the
7171
/// type's public interface (e.g. `bytes::Bytes`). As there is no reasonable way to
7272
/// scan a crate's interface to see if this is the case, all such types will be linted.
73-
/// If this happens use the `ignore-interior-mutability` configuration option to allow
74-
/// the type.
73+
/// If this happens, use the `ignore-interior-mutability` configuration option or put
74+
/// the `#[clippy::ignore_interior_mutability]` attribute onto a type to allow the
75+
/// type.
7576
///
7677
/// ### Example
7778
/// ```no_run
@@ -131,8 +132,9 @@ declare_clippy_lint! {
131132
/// no way to both create a value as a constant and modify any mutable field using the
132133
/// type's public interface (e.g. `bytes::Bytes`). As there is no reasonable way to
133134
/// scan a crate's interface to see if this is the case, all such types will be linted.
134-
/// If this happens use the `ignore-interior-mutability` configuration option to allow
135-
/// the type.
135+
/// If this happens, use the `ignore-interior-mutability` configuration option or put
136+
/// the `#[clippy::ignore_interior_mutability]` attribute onto a type to allow the
137+
/// type.
136138
///
137139
/// ### Example
138140
/// ```no_run

clippy_utils/src/attrs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub fn get_builtin_attr<'a, A: AttributeExt + 'a>(
2828
sym::cyclomatic_complexity => Some("cognitive_complexity"),
2929
sym::author
3030
| sym::version
31+
| sym::ignore_interior_mutability
3132
| sym::cognitive_complexity
3233
| sym::dump
3334
| sym::msrv

clippy_utils/src/sym.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ generate! {
174174
has_significant_drop,
175175
hidden_glob_reexports,
176176
hygiene,
177+
ignore_interior_mutability,
177178
insert,
178179
inspect,
179180
int_roundings,

clippy_utils/src/ty/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,17 @@ impl<'tcx> InteriorMut<'tcx> {
11211121
/// this type to be interior mutable. False negatives may be expected for infinitely recursive
11221122
/// types, and `None` will be returned there.
11231123
pub fn interior_mut_ty_chain(&mut self, cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx ty::List<Ty<'tcx>>> {
1124+
// Check if given type has a `#[clippy::ignore_interior_mutability]` attribute
1125+
if let Some(did) = ty.ty_adt_def().map(AdtDef::did)
1126+
&& !self.ignored_def_ids.contains(&did)
1127+
&& let attrs = cx.tcx.get_all_attrs(did)
1128+
&& get_unique_builtin_attr(cx.sess(), attrs, sym::ignore_interior_mutability).is_some()
1129+
{
1130+
self.ignored_def_ids.insert(did);
1131+
// Small optimization: since we know that we're going to ignore interior mutability for
1132+
// this type anyway, running `self.interior_mut_ty_chain_inner` is unnecessary
1133+
return None;
1134+
}
11241135
self.interior_mut_ty_chain_inner(cx, ty, 0)
11251136
}
11261137

tests/ui/borrow_interior_mutable_const.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,11 @@ fn main() {
234234
}
235235
}
236236
}
237+
fn issue13865() {
238+
#[clippy::ignore_interior_mutability]
239+
struct Foo(Cell<i32>);
240+
241+
const FOO: Foo = Foo(Cell::new(0));
242+
let _ = &FOO;
243+
}
237244
}

tests/ui/declare_interior_mutable_const.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,9 @@ impl WithGenericAssocCell for i32 {
198198

199199
thread_local!(static THREAD_LOCAL_CELL: Cell<u32> = const { Cell::new(0) });
200200
thread_local!(static THREAD_LOCAL_CELL2: Cell<u32> = Cell::new(0));
201+
202+
fn issue13865() {
203+
#[clippy::ignore_interior_mutability]
204+
struct IgnoreInteriorMut(Cell<u32>);
205+
const IIM: IgnoreInteriorMut = IgnoreInteriorMut(Cell::new(0));
206+
}

tests/ui/ifs_same_cond.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#![warn(clippy::ifs_same_cond)]
22
#![allow(clippy::if_same_then_else, clippy::needless_if, clippy::needless_else)] // all empty blocks
33

4+
use std::cell::Cell;
5+
46
fn ifs_same_cond() {
57
let a = 0;
68
let b = false;
@@ -72,7 +74,7 @@ fn issue10272() {
7274
} else {
7375
}
7476

75-
let x = std::cell::Cell::new(true);
77+
let x = Cell::new(true);
7678
if x.get() {
7779
} else if !x.take() {
7880
} else if x.get() {
@@ -81,4 +83,34 @@ fn issue10272() {
8183
}
8284
}
8385

86+
fn issue13865() {
87+
#[clippy::ignore_interior_mutability]
88+
struct X<T>(Cell<T>);
89+
90+
// delegate some methods so that the test case works
91+
impl<T> X<T> {
92+
fn get(&self) -> T
93+
where
94+
T: Copy,
95+
{
96+
self.0.get()
97+
}
98+
fn take(&self) -> T
99+
where
100+
T: Default,
101+
{
102+
self.0.take()
103+
}
104+
}
105+
106+
let x = X(Cell::new(true));
107+
if x.get() {
108+
//~^ ifs_same_cond
109+
// x is interior mutable type, but that should be ignored, so we lint
110+
} else if !x.take() {
111+
} else if x.get() {
112+
} else {
113+
}
114+
}
115+
84116
fn main() {}

tests/ui/ifs_same_cond.stderr

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: these `if` branches have the same condition
2-
--> tests/ui/ifs_same_cond.rs:8:8
2+
--> tests/ui/ifs_same_cond.rs:10:8
33
|
44
LL | if b {
55
| ^
@@ -11,7 +11,7 @@ LL | } else if b {
1111
= help: to override `-D warnings` add `#[allow(clippy::ifs_same_cond)]`
1212

1313
error: these `if` branches have the same condition
14-
--> tests/ui/ifs_same_cond.rs:13:8
14+
--> tests/ui/ifs_same_cond.rs:15:8
1515
|
1616
LL | if b {
1717
| ^
@@ -22,7 +22,7 @@ LL | } else if b {
2222
| ^
2323

2424
error: these `if` branches have the same condition
25-
--> tests/ui/ifs_same_cond.rs:19:8
25+
--> tests/ui/ifs_same_cond.rs:21:8
2626
|
2727
LL | if a == 1 {
2828
| ^^^^^^
@@ -31,7 +31,7 @@ LL | } else if a == 1 {
3131
| ^^^^^^
3232

3333
error: these `if` branches have the same condition
34-
--> tests/ui/ifs_same_cond.rs:24:8
34+
--> tests/ui/ifs_same_cond.rs:26:8
3535
|
3636
LL | if 2 * a == 1 {
3737
| ^^^^^^^^^^
@@ -40,13 +40,22 @@ LL | } else if 2 * a == 1 {
4040
| ^^^^^^^^^^
4141

4242
error: these `if` branches have the same condition
43-
--> tests/ui/ifs_same_cond.rs:58:8
43+
--> tests/ui/ifs_same_cond.rs:60:8
4444
|
4545
LL | if a.contains("ah") {
4646
| ^^^^^^^^^^^^^^^^
4747
LL |
4848
LL | } else if a.contains("ah") {
4949
| ^^^^^^^^^^^^^^^^
5050

51-
error: aborting due to 5 previous errors
51+
error: these `if` branches have the same condition
52+
--> tests/ui/ifs_same_cond.rs:105:8
53+
|
54+
LL | if x.get() {
55+
| ^^^^^^^
56+
...
57+
LL | } else if x.get() {
58+
| ^^^^^^^
59+
60+
error: aborting due to 6 previous errors
5261

tests/ui/mut_key.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,14 @@ fn main() {
113113
let _map = HashMap::<&mut usize, usize>::new();
114114
let _map = HashMap::<Result<&mut usize, ()>, usize>::new();
115115
}
116+
117+
fn issue13865() {
118+
#[clippy::ignore_interior_mutability]
119+
struct IgnoreMut {
120+
cell: std::cell::Cell<&'static [u32]>,
121+
}
122+
123+
fn main() {
124+
let a: HashSet<IgnoreMut> = HashSet::new();
125+
}
126+
}

0 commit comments

Comments
 (0)