Skip to content

Commit 5c63f87

Browse files
committed
Reword declare_interior_mutable_const and borrow_interior_mutable_const messages to be less assertive.
Update documentation for both lints.
1 parent 60d9b6e commit 5c63f87

File tree

7 files changed

+184
-158
lines changed

7 files changed

+184
-158
lines changed

clippy_lints/src/non_copy_const.rs

Lines changed: 68 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clippy_config::Conf;
22
use clippy_utils::consts::{ConstEvalCtxt, Constant};
33
use clippy_utils::def_path_def_ids;
4-
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
4+
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
55
use clippy_utils::macros::macro_backtrace;
66
use clippy_utils::ty::{get_field_idx_by_name, implements_trait};
77
use rustc_data_structures::fx::FxHashMap;
@@ -21,35 +21,36 @@ use std::collections::hash_map::Entry;
2121

2222
declare_clippy_lint! {
2323
/// ### What it does
24-
/// Checks for declaration of `const` items which is interior
25-
/// mutable (e.g., contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.).
24+
/// Checks for the declaration of named constant which contain interior mutability.
2625
///
2726
/// ### Why is this bad?
28-
/// Consts are copied everywhere they are referenced, i.e.,
29-
/// every time you refer to the const a fresh instance of the `Cell` or `Mutex`
30-
/// or `AtomicXxxx` will be created, which defeats the whole purpose of using
31-
/// these types in the first place.
27+
/// Named constants are copied at every use site which means any change to their value
28+
/// will be lost after the newly created value is dropped. e.g.
3229
///
33-
/// The `const` should better be replaced by a `static` item if a global
34-
/// variable is wanted, or replaced by a `const fn` if a constructor is wanted.
30+
/// ```rust
31+
/// use core::sync::{AtomicUsize, Ordering};
32+
/// const ATOMIC: AtomicUsize = AtomicUsize::new(0);
33+
/// fn add_one() -> usize {
34+
/// // This will always return `0` since `ATOMIC` is copied before it's used.
35+
/// ATOMIC.fetch_add(1, Ordering::AcqRel)
36+
/// }
37+
/// ```
3538
///
36-
/// ### Known problems
37-
/// A "non-constant" const item is a legacy way to supply an
38-
/// initialized value to downstream `static` items (e.g., the
39-
/// `std::sync::ONCE_INIT` constant). In this case the use of `const` is legit,
40-
/// and this lint should be suppressed.
39+
/// If shared modification of the value is desired, a `static` item is needed instead.
40+
/// If that is not desired, a `const fn` constructor should be used to make it obvious
41+
/// at the use site that a new value is created.
4142
///
42-
/// Even though the lint avoids triggering on a constant whose type has enums that have variants
43-
/// with interior mutability, and its value uses non interior mutable variants (see
44-
/// [#3962](https://github.com/rust-lang/rust-clippy/issues/3962) and
45-
/// [#3825](https://github.com/rust-lang/rust-clippy/issues/3825) for examples);
46-
/// it complains about associated constants without default values only based on its types;
47-
/// which might not be preferable.
48-
/// There're other enums plus associated constants cases that the lint cannot handle.
43+
/// ### Known problems
44+
/// Prior to `const fn` stabilization this was the only way to provide a value which
45+
/// could initialize a `static` item (e.g. the `std::sync::ONCE_INIT` constant). In
46+
/// this case the use of `const` is required and this lint should be suppressed.
4947
///
50-
/// Types that have underlying or potential interior mutability trigger the lint whether
51-
/// the interior mutable field is used or not. See issue
52-
/// [#5812](https://github.com/rust-lang/rust-clippy/issues/5812)
48+
/// There also exists types which contain private fields with interior mutability, but
49+
/// no way to both create a value as a constant and modify any mutable field using the
50+
/// type's public interface (e.g. `bytes::Bytes`). As there is no reasonable way to
51+
/// scan a crate's interface to see if this is the case, all such types will be linted.
52+
/// If this happens use the `ignore-interior-mutability` configuration option to allow
53+
/// the type.
5354
///
5455
/// ### Example
5556
/// ```no_run
@@ -75,26 +76,42 @@ declare_clippy_lint! {
7576

7677
declare_clippy_lint! {
7778
/// ### What it does
78-
/// Checks if `const` items which is interior mutable (e.g.,
79-
/// contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.) has been borrowed directly.
79+
/// Checks for a borrow of a named constant with interior mutability.
8080
///
8181
/// ### Why is this bad?
82-
/// Consts are copied everywhere they are referenced, i.e.,
83-
/// every time you refer to the const a fresh instance of the `Cell` or `Mutex`
84-
/// or `AtomicXxxx` will be created, which defeats the whole purpose of using
85-
/// these types in the first place.
82+
/// Named constants are copied at every use site which means any change to their value
83+
/// will be lost after the newly created value is dropped. e.g.
8684
///
87-
/// The `const` value should be stored inside a `static` item.
85+
/// ```rust
86+
/// use core::sync::{AtomicUsize, Ordering};
87+
/// const ATOMIC: AtomicUsize = AtomicUsize::new(0);
88+
/// fn add_one() -> usize {
89+
/// // This will always return `0` since `ATOMIC` is copied before it's borrowed
90+
/// // for use by `fetch_add`.
91+
/// ATOMIC.fetch_add(1, Ordering::AcqRel)
92+
/// }
93+
/// ```
8894
///
8995
/// ### Known problems
90-
/// When an enum has variants with interior mutability, use of its non
91-
/// interior mutable variants can generate false positives. See issue
92-
/// [#3962](https://github.com/rust-lang/rust-clippy/issues/3962)
96+
/// This lint does not, and cannot in general, determine if the borrow of the constant
97+
/// is used in a way which causes a mutation. e.g.
98+
///
99+
/// ```rust
100+
/// use core::cell::Cell;
101+
/// const CELL: Cell<usize> = Cell::new(0);
102+
/// fn get_cell() -> Cell<usize> {
103+
/// // This is fine. It borrows a copy of `CELL`, but never mutates it through the
104+
/// // borrow.
105+
/// CELL.clone()
106+
/// }
107+
/// ```
93108
///
94-
/// Types that have underlying or potential interior mutability trigger the lint whether
95-
/// the interior mutable field is used or not. See issues
96-
/// [#5812](https://github.com/rust-lang/rust-clippy/issues/5812) and
97-
/// [#3825](https://github.com/rust-lang/rust-clippy/issues/3825)
109+
/// There also exists types which contain private fields with interior mutability, but
110+
/// no way to both create a value as a constant and modify any mutable field using the
111+
/// type's public interface (e.g. `bytes::Bytes`). As there is no reasonable way to
112+
/// scan a crate's interface to see if this is the case, all such types will be linted.
113+
/// If this happens use the `ignore-interior-mutability` configuration option to allow
114+
/// the type.
98115
///
99116
/// ### Example
100117
/// ```no_run
@@ -659,17 +676,15 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
659676
cx,
660677
DECLARE_INTERIOR_MUTABLE_CONST,
661678
item.ident.span,
662-
"a `const` item should not be interior mutable",
679+
"named constant with interior mutability",
663680
|diag| {
664681
let Some(sync_trait) = cx.tcx.lang_items().sync_trait() else {
665682
return;
666683
};
667684
if implements_trait(cx, ty, sync_trait, &[]) {
668-
diag.help("consider making this a static item");
685+
diag.help("did you mean to make this a `static` item");
669686
} else {
670-
diag.help(
671-
"consider making this `Sync` so that it can go in a static item or using a `thread_local`",
672-
);
687+
diag.help("did you mean to make this a `thread_local!` item");
673688
}
674689
},
675690
);
@@ -702,7 +717,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
702717
cx,
703718
DECLARE_INTERIOR_MUTABLE_CONST,
704719
item.ident.span,
705-
"a `const` item should not be interior mutable",
720+
"named constant with interior mutability",
706721
);
707722
}
708723
}
@@ -753,7 +768,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
753768
cx,
754769
DECLARE_INTERIOR_MUTABLE_CONST,
755770
item.ident.span,
756-
"a `const` item should not be interior mutable",
771+
"named constant with interior mutability",
757772
);
758773
}
759774
}
@@ -790,13 +805,17 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
790805
}
791806
&& !in_external_macro(cx.sess(), borrow_src.expr.span)
792807
{
793-
span_lint_and_help(
808+
span_lint_and_then(
794809
cx,
795810
BORROW_INTERIOR_MUTABLE_CONST,
796811
borrow_src.expr.span,
797-
"a `const` item with interior mutability should not be borrowed",
798-
None,
799-
"assign this const to a local or static variable, and use the variable here",
812+
"borrow of a named constant with interior mutability",
813+
|diag| {
814+
diag.help("this lint can be silenced by assigning the value to a local variable before borrowing");
815+
if let Some(note) = borrow_src.cause.note() {
816+
diag.note(note);
817+
}
818+
},
800819
);
801820
}
802821
}
Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,55 @@
1-
error: a `const` item with interior mutability should not be borrowed
1+
error: borrow of a named constant with interior mutability
22
--> tests/ui/borrow_interior_mutable_const/enums.rs:22:13
33
|
44
LL | let _ = &UNFROZEN_VARIANT;
55
| ^^^^^^^^^^^^^^^^^
66
|
7-
= help: assign this const to a local or static variable, and use the variable here
7+
= help: this lint can be silenced by assigning the value to a local variable before borrowing
88
note: the lint level is defined here
99
--> tests/ui/borrow_interior_mutable_const/enums.rs:3:9
1010
|
1111
LL | #![deny(clippy::borrow_interior_mutable_const)]
1212
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1313

14-
error: a `const` item with interior mutability should not be borrowed
14+
error: borrow of a named constant with interior mutability
1515
--> tests/ui/borrow_interior_mutable_const/enums.rs:50:17
1616
|
1717
LL | let _ = &<Self as AssocConsts>::TO_BE_UNFROZEN_VARIANT;
1818
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1919
|
20-
= help: assign this const to a local or static variable, and use the variable here
20+
= help: this lint can be silenced by assigning the value to a local variable before borrowing
2121

22-
error: a `const` item with interior mutability should not be borrowed
22+
error: borrow of a named constant with interior mutability
2323
--> tests/ui/borrow_interior_mutable_const/enums.rs:52:17
2424
|
2525
LL | let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT;
2626
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2727
|
28-
= help: assign this const to a local or static variable, and use the variable here
28+
= help: this lint can be silenced by assigning the value to a local variable before borrowing
2929

30-
error: a `const` item with interior mutability should not be borrowed
30+
error: borrow of a named constant with interior mutability
3131
--> tests/ui/borrow_interior_mutable_const/enums.rs:74:17
3232
|
3333
LL | let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT;
3434
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3535
|
36-
= help: assign this const to a local or static variable, and use the variable here
36+
= help: this lint can be silenced by assigning the value to a local variable before borrowing
3737

38-
error: a `const` item with interior mutability should not be borrowed
38+
error: borrow of a named constant with interior mutability
3939
--> tests/ui/borrow_interior_mutable_const/enums.rs:91:17
4040
|
4141
LL | let _ = &Self::UNFROZEN_VARIANT;
4242
| ^^^^^^^^^^^^^^^^^^^^^^^
4343
|
44-
= help: assign this const to a local or static variable, and use the variable here
44+
= help: this lint can be silenced by assigning the value to a local variable before borrowing
4545

46-
error: a `const` item with interior mutability should not be borrowed
46+
error: borrow of a named constant with interior mutability
4747
--> tests/ui/borrow_interior_mutable_const/enums.rs:99:13
4848
|
4949
LL | let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT;
5050
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5151
|
52-
= help: assign this const to a local or static variable, and use the variable here
52+
= help: this lint can be silenced by assigning the value to a local variable before borrowing
5353

5454
error: aborting due to 6 previous errors
5555

0 commit comments

Comments
 (0)