Skip to content

Commit 1087095

Browse files
committed
introduce #[clippy::ignore_interior_mutability]
1 parent 969e771 commit 1087095

File tree

9 files changed

+93
-13
lines changed

9 files changed

+93
-13
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
@@ -175,6 +175,7 @@ generate! {
175175
has_significant_drop,
176176
hidden_glob_reexports,
177177
hygiene,
178+
ignore_interior_mutability,
178179
insert,
179180
insert_str,
180181
inspect,

clippy_utils/src/ty/mod.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_hir::def_id::DefId;
1414
use rustc_hir::{Expr, FnDecl, LangItem, find_attr};
1515
use rustc_hir_analysis::lower_ty;
1616
use rustc_infer::infer::TyCtxtInferExt;
17-
use rustc_lint::LateContext;
17+
use rustc_lint::{LateContext, LintContext};
1818
use rustc_middle::mir::ConstValue;
1919
use rustc_middle::mir::interpret::Scalar;
2020
use rustc_middle::traits::EvaluationResult;
@@ -36,7 +36,7 @@ use std::{iter, mem};
3636

3737
use crate::paths::{PathNS, lookup_path_str};
3838
use crate::res::{MaybeDef, MaybeQPath};
39-
use crate::sym;
39+
use crate::{get_unique_builtin_attr, sym};
4040

4141
mod type_certainty;
4242
pub use type_certainty::expr_type_is_certain;
@@ -1071,6 +1071,17 @@ impl<'tcx> InteriorMut<'tcx> {
10711071
/// this type to be interior mutable. False negatives may be expected for infinitely recursive
10721072
/// types, and `None` will be returned there.
10731073
pub fn interior_mut_ty_chain(&mut self, cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx ty::List<Ty<'tcx>>> {
1074+
// Check if given type has a `#[clippy::ignore_interior_mutability]` attribute
1075+
if let Some(did) = ty.ty_adt_def().map(AdtDef::did)
1076+
&& !self.ignored_def_ids.contains(&did)
1077+
&& let attrs = cx.tcx.get_all_attrs(did)
1078+
&& get_unique_builtin_attr(cx.sess(), attrs, sym::ignore_interior_mutability).is_some()
1079+
{
1080+
self.ignored_def_ids.insert(did);
1081+
// Small optimization: since we know that we're going to ignore interior mutability for
1082+
// this type anyway, running `self.interior_mut_ty_chain_inner` is unnecessary
1083+
return None;
1084+
}
10741085
self.interior_mut_ty_chain_inner(cx, ty, 0)
10751086
}
10761087

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:107: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)