Skip to content

Commit 999d239

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 8151c43 commit 999d239

File tree

7 files changed

+184
-158
lines changed

7 files changed

+184
-158
lines changed

clippy_lints/src/non_copy_const.rs

+68-49
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
use clippy_config::Conf;
2121
use clippy_utils::consts::{ConstEvalCtxt, Constant};
22-
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
22+
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
2323
use clippy_utils::macros::macro_backtrace;
2424
use clippy_utils::ty::{get_field_idx_by_name, implements_trait};
2525
use clippy_utils::{def_path_def_ids, is_in_const_context};
@@ -41,35 +41,36 @@ use std::collections::hash_map::Entry;
4141

4242
declare_clippy_lint! {
4343
/// ### What it does
44-
/// Checks for declaration of `const` items which is interior
45-
/// mutable (e.g., contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.).
44+
/// Checks for the declaration of named constant which contain interior mutability.
4645
///
4746
/// ### Why is this bad?
48-
/// Consts are copied everywhere they are referenced, i.e.,
49-
/// every time you refer to the const a fresh instance of the `Cell` or `Mutex`
50-
/// or `AtomicXxxx` will be created, which defeats the whole purpose of using
51-
/// these types in the first place.
47+
/// Named constants are copied at every use site which means any change to their value
48+
/// will be lost after the newly created value is dropped. e.g.
5249
///
53-
/// The `const` should better be replaced by a `static` item if a global
54-
/// variable is wanted, or replaced by a `const fn` if a constructor is wanted.
50+
/// ```rust
51+
/// use core::sync::atomic::{AtomicUsize, Ordering};
52+
/// const ATOMIC: AtomicUsize = AtomicUsize::new(0);
53+
/// fn add_one() -> usize {
54+
/// // This will always return `0` since `ATOMIC` is copied before it's used.
55+
/// ATOMIC.fetch_add(1, Ordering::AcqRel)
56+
/// }
57+
/// ```
5558
///
56-
/// ### Known problems
57-
/// A "non-constant" const item is a legacy way to supply an
58-
/// initialized value to downstream `static` items (e.g., the
59-
/// `std::sync::ONCE_INIT` constant). In this case the use of `const` is legit,
60-
/// and this lint should be suppressed.
59+
/// If shared modification of the value is desired, a `static` item is needed instead.
60+
/// If that is not desired, a `const fn` constructor should be used to make it obvious
61+
/// at the use site that a new value is created.
6162
///
62-
/// Even though the lint avoids triggering on a constant whose type has enums that have variants
63-
/// with interior mutability, and its value uses non interior mutable variants (see
64-
/// [#3962](https://github.com/rust-lang/rust-clippy/issues/3962) and
65-
/// [#3825](https://github.com/rust-lang/rust-clippy/issues/3825) for examples);
66-
/// it complains about associated constants without default values only based on its types;
67-
/// which might not be preferable.
68-
/// There're other enums plus associated constants cases that the lint cannot handle.
63+
/// ### Known problems
64+
/// Prior to `const fn` stabilization this was the only way to provide a value which
65+
/// could initialize a `static` item (e.g. the `std::sync::ONCE_INIT` constant). In
66+
/// this case the use of `const` is required and this lint should be suppressed.
6967
///
70-
/// Types that have underlying or potential interior mutability trigger the lint whether
71-
/// the interior mutable field is used or not. See issue
72-
/// [#5812](https://github.com/rust-lang/rust-clippy/issues/5812)
68+
/// There also exists types which contain private fields with interior mutability, but
69+
/// no way to both create a value as a constant and modify any mutable field using the
70+
/// type's public interface (e.g. `bytes::Bytes`). As there is no reasonable way to
71+
/// scan a crate's interface to see if this is the case, all such types will be linted.
72+
/// If this happens use the `ignore-interior-mutability` configuration option to allow
73+
/// the type.
7374
///
7475
/// ### Example
7576
/// ```no_run
@@ -95,26 +96,42 @@ declare_clippy_lint! {
9596

9697
declare_clippy_lint! {
9798
/// ### What it does
98-
/// Checks if `const` items which is interior mutable (e.g.,
99-
/// contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.) has been borrowed directly.
99+
/// Checks for a borrow of a named constant with interior mutability.
100100
///
101101
/// ### Why is this bad?
102-
/// Consts are copied everywhere they are referenced, i.e.,
103-
/// every time you refer to the const a fresh instance of the `Cell` or `Mutex`
104-
/// or `AtomicXxxx` will be created, which defeats the whole purpose of using
105-
/// these types in the first place.
102+
/// Named constants are copied at every use site which means any change to their value
103+
/// will be lost after the newly created value is dropped. e.g.
106104
///
107-
/// The `const` value should be stored inside a `static` item.
105+
/// ```rust
106+
/// use core::sync::atomic::{AtomicUsize, Ordering};
107+
/// const ATOMIC: AtomicUsize = AtomicUsize::new(0);
108+
/// fn add_one() -> usize {
109+
/// // This will always return `0` since `ATOMIC` is copied before it's borrowed
110+
/// // for use by `fetch_add`.
111+
/// ATOMIC.fetch_add(1, Ordering::AcqRel)
112+
/// }
113+
/// ```
108114
///
109115
/// ### Known problems
110-
/// When an enum has variants with interior mutability, use of its non
111-
/// interior mutable variants can generate false positives. See issue
112-
/// [#3962](https://github.com/rust-lang/rust-clippy/issues/3962)
116+
/// This lint does not, and cannot in general, determine if the borrow of the constant
117+
/// is used in a way which causes a mutation. e.g.
118+
///
119+
/// ```rust
120+
/// use core::cell::Cell;
121+
/// const CELL: Cell<usize> = Cell::new(0);
122+
/// fn get_cell() -> Cell<usize> {
123+
/// // This is fine. It borrows a copy of `CELL`, but never mutates it through the
124+
/// // borrow.
125+
/// CELL.clone()
126+
/// }
127+
/// ```
113128
///
114-
/// Types that have underlying or potential interior mutability trigger the lint whether
115-
/// the interior mutable field is used or not. See issues
116-
/// [#5812](https://github.com/rust-lang/rust-clippy/issues/5812) and
117-
/// [#3825](https://github.com/rust-lang/rust-clippy/issues/3825)
129+
/// There also exists types which contain private fields with interior mutability, but
130+
/// no way to both create a value as a constant and modify any mutable field using the
131+
/// type's public interface (e.g. `bytes::Bytes`). As there is no reasonable way to
132+
/// scan a crate's interface to see if this is the case, all such types will be linted.
133+
/// If this happens use the `ignore-interior-mutability` configuration option to allow
134+
/// the type.
118135
///
119136
/// ### Example
120137
/// ```no_run
@@ -697,17 +714,15 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
697714
cx,
698715
DECLARE_INTERIOR_MUTABLE_CONST,
699716
item.ident.span,
700-
"a `const` item should not be interior mutable",
717+
"named constant with interior mutability",
701718
|diag| {
702719
let Some(sync_trait) = cx.tcx.lang_items().sync_trait() else {
703720
return;
704721
};
705722
if implements_trait(cx, ty, sync_trait, &[]) {
706-
diag.help("consider making this a static item");
723+
diag.help("did you mean to make this a `static` item");
707724
} else {
708-
diag.help(
709-
"consider making this `Sync` so that it can go in a static item or using a `thread_local`",
710-
);
725+
diag.help("did you mean to make this a `thread_local!` item");
711726
}
712727
},
713728
);
@@ -741,7 +756,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
741756
cx,
742757
DECLARE_INTERIOR_MUTABLE_CONST,
743758
item.ident.span,
744-
"a `const` item should not be interior mutable",
759+
"named constant with interior mutability",
745760
);
746761
}
747762
}
@@ -793,7 +808,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
793808
cx,
794809
DECLARE_INTERIOR_MUTABLE_CONST,
795810
item.ident.span,
796-
"a `const` item should not be interior mutable",
811+
"named constant with interior mutability",
797812
);
798813
}
799814
}
@@ -825,13 +840,17 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
825840
}
826841
&& !in_external_macro(cx.sess(), borrow_src.expr.span)
827842
{
828-
span_lint_and_help(
843+
span_lint_and_then(
829844
cx,
830845
BORROW_INTERIOR_MUTABLE_CONST,
831846
borrow_src.expr.span,
832-
"a `const` item with interior mutability should not be borrowed",
833-
None,
834-
"assign this const to a local or static variable, and use the variable here",
847+
"borrow of a named constant with interior mutability",
848+
|diag| {
849+
diag.help("this lint can be silenced by assigning the value to a local variable before borrowing");
850+
if let Some(note) = borrow_src.cause.note() {
851+
diag.note(note);
852+
}
853+
},
835854
);
836855
}
837856
}
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)