Skip to content

Commit 0e04c25

Browse files
committed
[once_cell_lazy]: adjust error message, docs, and auxiliary code.
1 parent 7fba7f9 commit 0e04c25

File tree

7 files changed

+79
-108
lines changed

7 files changed

+79
-108
lines changed

clippy_lints/src/once_cell_lazy.rs

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,23 @@ use rustc_span::Span;
1313

1414
declare_clippy_lint! {
1515
/// ### What it does
16-
/// Lints when a `once_cell::sync::Lazy` type is declared as static variables.
16+
/// Lints when a `static` is declared with `once_cell::sync::Lazy` type,
17+
/// which can mostly be done with `std::sync::LazyLock` without relying on
18+
/// additional dependency.
19+
///
20+
/// Note: This lint will not trigger in crate with `no_std` context, or with MSRV < 1.80.0.
1721
///
1822
/// ### Why restrict this?
19-
/// Such useage have been superseded by the `std::sync::LazyLock` type,
20-
/// replacing them would reduce dependency of `once_cell` crate.
23+
/// Such usage can be replaced with the `std::sync::LazyLock` type,
24+
/// to reduce dependence of the `once_cell` crate.
2125
///
2226
/// ### Example
23-
/// ```rust
24-
/// use once_cell_lazy::once_cell_lazy;
25-
/// use once_cell::sync::Lazy;
26-
///
27-
/// once_cell_lazy! {
28-
/// static ref FOO: String = "foo".to_uppercase();
29-
/// }
30-
/// static BAR: Lazy<String> = Lazy::new(|| "BAR".to_lowercase());
27+
/// ```ignore
28+
/// static FOO: once_cell::sync::Lazy<String> = once_cell::sync::Lazy::new(|| "FOO".to_lowercase());
3129
/// ```
3230
/// Use instead:
33-
/// ```rust
34-
/// static FOO: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "foo".to_uppercase());
35-
/// static BAR: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "BAR".to_lowercase());
31+
/// ```ignore
32+
/// static FOO: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "FOO".to_lowercase());
3633
/// ```
3734
#[clippy::version = "1.81.0"]
3835
pub ONCE_CELL_LAZY,
@@ -48,15 +45,13 @@ declare_clippy_lint! {
4845
/// `Unspecified` or `MaybeIncorret`.
4946
static FUNCTION_REPLACEMENTS: &[(&str, Option<&str>)] = &[
5047
("once_cell::sync::Lazy::force", Some("std::sync::LazyLock::force")),
51-
("once_cell::sync::Lazy::force_mut", None),
5248
("once_cell::sync::Lazy::get", None),
53-
("once_cell::sync::Lazy::get_mut", None),
5449
("once_cell::sync::Lazy::new", Some("std::sync::LazyLock::new")),
55-
// Note that `Lazy::into_value` is not in the list,
56-
// because we only check for `static`s in this lint, and `into_value` attempts to take ownership
57-
// of the parameter, which means it would fail natively.
58-
// But do keep in mind that the equivalant replacement is called `LazyLock::into_inner`
59-
// if somehow we decided to expand this lint to catch "non-static"s.
50+
// Note: `Lazy::{into_value, get_mut, force_mut}` are not in the list.
51+
// Because the lint only checks for `static`s, and using these functions with statics
52+
// will either be a hard error or triggers `static_mut_ref` that will be hard errors.
53+
// But keep in mind that if somehow we decide to expand this lint to catch non-statics,
54+
// add those functions into the list.
6055
];
6156

6257
pub struct OnceCellLazy {
@@ -78,6 +73,8 @@ impl OnceCellLazy {
7873

7974
impl_lint_pass!(OnceCellLazy => [ONCE_CELL_LAZY]);
8075

76+
/// Return if current MSRV does not meet the requirement for `lazy_cell` feature,
77+
/// or current context has `no_std` attribute.
8178
macro_rules! ensure_prerequisite {
8279
($msrv:expr, $cx:ident) => {
8380
if !$msrv.meets(clippy_config::msrvs::LAZY_CELL) || clippy_utils::is_no_std_crate($cx) {
@@ -90,7 +87,7 @@ impl<'hir> LateLintPass<'hir> for OnceCellLazy {
9087
extract_msrv_attr!(LateContext);
9188

9289
fn check_crate(&mut self, cx: &LateContext<'hir>) {
93-
// Do not link if current crate does not support `LazyLock`.
90+
// Do not lint if current crate does not support `LazyLock`.
9491
ensure_prerequisite!(self.msrv, cx);
9592

9693
// Convert hardcoded fn replacement list into a map with def_id
@@ -105,8 +102,8 @@ impl<'hir> LateLintPass<'hir> for OnceCellLazy {
105102
fn check_item(&mut self, cx: &LateContext<'hir>, item: &Item<'hir>) {
106103
ensure_prerequisite!(self.msrv, cx);
107104

108-
if let Some(lazy_kind) = LazyInfo::from_item(cx, item) {
109-
self.lazy_type_defs.insert(item.owner_id.to_def_id(), lazy_kind);
105+
if let Some(lazy_info) = LazyInfo::from_item(cx, item) {
106+
self.lazy_type_defs.insert(item.owner_id.to_def_id(), lazy_info);
110107
}
111108
}
112109

@@ -137,8 +134,7 @@ impl<'hir> LateLintPass<'hir> for OnceCellLazy {
137134
}
138135

139136
struct LazyInfo {
140-
/// Span of the [`hir::Ty`] where this `Lazy` type was declared,
141-
/// without including args.
137+
/// Span of the [`hir::Ty`] without including args.
142138
/// i.e.:
143139
/// ```ignore
144140
/// static FOO: Lazy<String> = Lazy::new(...);
@@ -148,22 +144,8 @@ struct LazyInfo {
148144
/// `Span` and `DefId` of calls on `Lazy` type.
149145
/// i.e.:
150146
/// ```ignore
151-
/// static FOO: Lazy<String> = {
152-
/// if cond {
153-
/// Lazy::new(...)
154-
/// // ^^^^^^^^^
155-
/// } else {
156-
/// Lazy::new(...)
157-
/// // ^^^^^^^^^
158-
/// }
159-
/// }
160-
/// ```
161-
///
162-
/// Or:
163-
///
164-
/// ```ignore
165-
/// let x = Lazy::get(&FOO);
166-
/// // ^^^^^^^^
147+
/// static FOO: Lazy<String> = Lazy::new(...);
148+
/// // ^^^^^^^^^
167149
/// ```
168150
calls_span_and_id: FxIndexMap<Span, DefId>,
169151
}
@@ -228,9 +210,9 @@ impl LazyInfo {
228210
cx,
229211
ONCE_CELL_LAZY,
230212
self.ty_span_no_args,
231-
"this type has been superceded by `LazyLock`",
213+
"this type has been superceded by `std::sync::LazyLock`",
232214
|diag| {
233-
diag.multipart_suggestion("consider using the `LazyLock` from standard library", suggs, appl);
215+
diag.multipart_suggestion("use `std::sync::LazyLock` instead", suggs, appl);
234216
},
235217
);
236218
}
Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,39 @@
11
//! **FAKE** once_cell crate.
22
33
pub mod sync {
4-
use core::cell::Cell;
54
use std::marker::PhantomData;
65

7-
pub struct OnceCell<T>(PhantomData<T>);
8-
impl<T> OnceCell<T> {
9-
pub const fn new() -> OnceCell<T> {
10-
OnceCell(PhantomData)
11-
}
12-
}
13-
impl<T> Default for OnceCell<T> {
14-
fn default() -> Self {
15-
Self::new()
16-
}
17-
}
18-
196
pub struct Lazy<T, F = fn() -> T> {
20-
cell: OnceCell<T>,
21-
init: Cell<Option<F>>,
7+
cell: PhantomData<T>,
8+
init: F,
229
}
23-
unsafe impl<T, F: Send> Sync for Lazy<T, F> where OnceCell<T>: Sync {}
10+
unsafe impl<T, F: Send> Sync for Lazy<T, F> {}
2411
impl<T, F> Lazy<T, F> {
2512
pub const fn new(f: F) -> Lazy<T, F> {
2613
Lazy {
27-
cell: OnceCell::new(),
28-
init: Cell::new(Some(f)),
14+
cell: PhantomData,
15+
init: f,
2916
}
3017
}
3118

32-
pub fn into_value(this: Lazy<T, F>) -> Result<T, i32> {
33-
Err(1)
19+
pub fn into_value(this: Lazy<T, F>) -> Result<T, F> {
20+
unimplemented!()
3421
}
3522

36-
pub fn force(_this: &Lazy<T, F>) -> i32 {
37-
0
23+
pub fn force(_this: &Lazy<T, F>) -> &T {
24+
unimplemented!()
3825
}
3926

40-
pub fn force_mut(_this: &mut Lazy<T, F>) -> i32 {
41-
0
27+
pub fn force_mut(_this: &mut Lazy<T, F>) -> &mut T {
28+
unimplemented!()
4229
}
4330

44-
pub fn get(_this: &Lazy<T, F>) -> i32 {
45-
0
31+
pub fn get(_this: &Lazy<T, F>) -> Option<&T> {
32+
unimplemented!()
4633
}
4734

48-
pub fn get_mut(_this: &mut Lazy<T, F>) -> i32 {
49-
0
35+
pub fn get_mut(_this: &mut Lazy<T, F>) -> Option<&mut T> {
36+
unimplemented!()
5037
}
5138
}
5239
}

tests/ui/lazy_lock_like/lazy_lock_like_fixable.fixed

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ use once_cell::sync::Lazy;
88
fn main() {}
99

1010
static LAZY_FOO: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "foo".to_uppercase());
11-
//~^ ERROR: this type has been superceded by `LazyLock`
11+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
1212
static LAZY_BAR: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| {
13-
//~^ ERROR: this type has been superceded by `LazyLock`
13+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
1414
let x = "bar";
1515
x.to_uppercase()
1616
});
1717
static LAZY_BAZ: std::sync::LazyLock<String> = { std::sync::LazyLock::new(|| "baz".to_uppercase()) };
18-
//~^ ERROR: this type has been superceded by `LazyLock`
18+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
1919
static LAZY_QUX: std::sync::LazyLock<String> = {
20-
//~^ ERROR: this type has been superceded by `LazyLock`
20+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
2121
if "qux".len() == 3 {
2222
std::sync::LazyLock::new(|| "qux".to_uppercase())
2323
} else if "qux".is_ascii() {
@@ -38,11 +38,11 @@ mod once_cell_lazy_with_fns {
3838
use super::Lazy; // nice
3939

4040
static LAZY_FOO: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "foo".to_uppercase());
41-
//~^ ERROR: this type has been superceded by `LazyLock`
41+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
4242
static LAZY_BAR: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "bar".to_uppercase());
43-
//~^ ERROR: this type has been superceded by `LazyLock`
43+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
4444
static mut LAZY_BAZ: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "baz".to_uppercase());
45-
//~^ ERROR: this type has been superceded by `LazyLock`
45+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
4646

4747
fn calling_replaceable_fns() {
4848
let _ = std::sync::LazyLock::force(&LAZY_FOO);

tests/ui/lazy_lock_like/lazy_lock_like_fixable.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ use once_cell::sync::Lazy;
88
fn main() {}
99

1010
static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
11-
//~^ ERROR: this type has been superceded by `LazyLock`
11+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
1212
static LAZY_BAR: Lazy<String> = Lazy::new(|| {
13-
//~^ ERROR: this type has been superceded by `LazyLock`
13+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
1414
let x = "bar";
1515
x.to_uppercase()
1616
});
1717
static LAZY_BAZ: Lazy<String> = { Lazy::new(|| "baz".to_uppercase()) };
18-
//~^ ERROR: this type has been superceded by `LazyLock`
18+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
1919
static LAZY_QUX: Lazy<String> = {
20-
//~^ ERROR: this type has been superceded by `LazyLock`
20+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
2121
if "qux".len() == 3 {
2222
Lazy::new(|| "qux".to_uppercase())
2323
} else if "qux".is_ascii() {
@@ -38,11 +38,11 @@ mod once_cell_lazy_with_fns {
3838
use super::Lazy; // nice
3939

4040
static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
41-
//~^ ERROR: this type has been superceded by `LazyLock`
41+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
4242
static LAZY_BAR: Lazy<String> = Lazy::new(|| "bar".to_uppercase());
43-
//~^ ERROR: this type has been superceded by `LazyLock`
43+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
4444
static mut LAZY_BAZ: Lazy<String> = Lazy::new(|| "baz".to_uppercase());
45-
//~^ ERROR: this type has been superceded by `LazyLock`
45+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
4646

4747
fn calling_replaceable_fns() {
4848
let _ = Lazy::force(&LAZY_FOO);

tests/ui/lazy_lock_like/lazy_lock_like_fixable.stderr

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,45 @@
1-
error: this type has been superceded by `LazyLock`
1+
error: this type has been superceded by `std::sync::LazyLock`
22
--> tests/ui/lazy_lock_like/lazy_lock_like_fixable.rs:10:18
33
|
44
LL | static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
55
| ^^^^
66
|
77
= note: `-D clippy::once-cell-lazy` implied by `-D warnings`
88
= help: to override `-D warnings` add `#[allow(clippy::once_cell_lazy)]`
9-
help: consider using the `LazyLock` from standard library
9+
help: use `std::sync::LazyLock` instead
1010
|
1111
LL | static LAZY_FOO: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "foo".to_uppercase());
1212
| ~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
1313

14-
error: this type has been superceded by `LazyLock`
14+
error: this type has been superceded by `std::sync::LazyLock`
1515
--> tests/ui/lazy_lock_like/lazy_lock_like_fixable.rs:12:18
1616
|
1717
LL | static LAZY_BAR: Lazy<String> = Lazy::new(|| {
1818
| ^^^^
1919
|
20-
help: consider using the `LazyLock` from standard library
20+
help: use `std::sync::LazyLock` instead
2121
|
2222
LL | static LAZY_BAR: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| {
2323
| ~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
2424

25-
error: this type has been superceded by `LazyLock`
25+
error: this type has been superceded by `std::sync::LazyLock`
2626
--> tests/ui/lazy_lock_like/lazy_lock_like_fixable.rs:17:18
2727
|
2828
LL | static LAZY_BAZ: Lazy<String> = { Lazy::new(|| "baz".to_uppercase()) };
2929
| ^^^^
3030
|
31-
help: consider using the `LazyLock` from standard library
31+
help: use `std::sync::LazyLock` instead
3232
|
3333
LL | static LAZY_BAZ: std::sync::LazyLock<String> = { std::sync::LazyLock::new(|| "baz".to_uppercase()) };
3434
| ~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
3535

36-
error: this type has been superceded by `LazyLock`
36+
error: this type has been superceded by `std::sync::LazyLock`
3737
--> tests/ui/lazy_lock_like/lazy_lock_like_fixable.rs:19:18
3838
|
3939
LL | static LAZY_QUX: Lazy<String> = {
4040
| ^^^^
4141
|
42-
help: consider using the `LazyLock` from standard library
42+
help: use `std::sync::LazyLock` instead
4343
|
4444
LL ~ static LAZY_QUX: std::sync::LazyLock<String> = {
4545
LL |
@@ -51,13 +51,13 @@ LL | } else {
5151
LL ~ std::sync::LazyLock::new(|| "qux".to_string())
5252
|
5353

54-
error: this type has been superceded by `LazyLock`
54+
error: this type has been superceded by `std::sync::LazyLock`
5555
--> tests/ui/lazy_lock_like/lazy_lock_like_fixable.rs:40:22
5656
|
5757
LL | static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
5858
| ^^^^
5959
|
60-
help: consider using the `LazyLock` from standard library
60+
help: use `std::sync::LazyLock` instead
6161
|
6262
LL ~ static LAZY_FOO: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "foo".to_uppercase());
6363
LL |
@@ -66,13 +66,13 @@ LL | fn calling_replaceable_fns() {
6666
LL ~ let _ = std::sync::LazyLock::force(&LAZY_FOO);
6767
|
6868

69-
error: this type has been superceded by `LazyLock`
69+
error: this type has been superceded by `std::sync::LazyLock`
7070
--> tests/ui/lazy_lock_like/lazy_lock_like_fixable.rs:42:22
7171
|
7272
LL | static LAZY_BAR: Lazy<String> = Lazy::new(|| "bar".to_uppercase());
7373
| ^^^^
7474
|
75-
help: consider using the `LazyLock` from standard library
75+
help: use `std::sync::LazyLock` instead
7676
|
7777
LL ~ static LAZY_BAR: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "bar".to_uppercase());
7878
LL |
@@ -81,13 +81,13 @@ LL | let _ = Lazy::force(&LAZY_FOO);
8181
LL ~ let _ = std::sync::LazyLock::force(&LAZY_BAR);
8282
|
8383

84-
error: this type has been superceded by `LazyLock`
84+
error: this type has been superceded by `std::sync::LazyLock`
8585
--> tests/ui/lazy_lock_like/lazy_lock_like_fixable.rs:44:26
8686
|
8787
LL | static mut LAZY_BAZ: Lazy<String> = Lazy::new(|| "baz".to_uppercase());
8888
| ^^^^
8989
|
90-
help: consider using the `LazyLock` from standard library
90+
help: use `std::sync::LazyLock` instead
9191
|
9292
LL ~ static mut LAZY_BAZ: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "baz".to_uppercase());
9393
LL |

tests/ui/lazy_lock_like/lazy_lock_like_unfixable.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ use once_cell::sync::Lazy;
99
fn main() {}
1010

1111
static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
12-
//~^ ERROR: this type has been superceded by `LazyLock`
12+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
1313
static LAZY_BAR: Lazy<String> = Lazy::new(|| "bar".to_uppercase());
14+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
1415
static mut LAZY_BAZ: Lazy<String> = Lazy::new(|| "baz".to_uppercase());
16+
//~^ ERROR: this type has been superceded by `std::sync::LazyLock`
1517

1618
fn calling_irreplaceable_fns() {
1719
let _ = Lazy::get(&LAZY_BAR);

0 commit comments

Comments
 (0)