Skip to content

Commit 71c5413

Browse files
committed
Extract never-like into clippy_utils
1 parent 779e0f4 commit 71c5413

File tree

8 files changed

+89
-59
lines changed

8 files changed

+89
-59
lines changed

clippy_lints/src/methods/unwrap_expect_used.rs

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use clippy_utils::diagnostics::span_lint_and_help;
2-
use clippy_utils::ty::is_type_diagnostic_item;
1+
use clippy_utils::diagnostics::span_lint_and_then;
2+
use clippy_utils::ty::{is_never_like, is_type_diagnostic_item};
33
use clippy_utils::{is_in_cfg_test, is_in_test_function, is_lint_allowed};
44
use rustc_hir::Expr;
55
use rustc_lint::{LateContext, Lint};
@@ -32,7 +32,8 @@ impl Variant {
3232
}
3333
}
3434

35-
/// lint use of `unwrap()` or `unwrap_err` for `Result` and `unwrap()` for `Option`.
35+
/// Lint usage of `unwrap` or `unwrap_err` for `Result` and `unwrap()` for `Option` (and their
36+
/// `expect` counterparts).
3637
pub(super) fn check(
3738
cx: &LateContext<'_>,
3839
expr: &Expr<'_>,
@@ -49,10 +50,7 @@ pub(super) fn check(
4950
&& let ty::Adt(_, substs) = ty.kind()
5051
&& let Some(t_or_e_ty) = substs[usize::from(!is_err)].as_type()
5152
{
52-
// Issue #11245: Do not lint `!` or never-like enums
53-
if t_or_e_ty.is_never()
54-
|| (t_or_e_ty.is_enum() && t_or_e_ty.ty_adt_def().is_some_and(|def| def.variants().is_empty()))
55-
{
53+
if is_never_like(t_or_e_ty) {
5654
return;
5755
}
5856

@@ -67,21 +65,19 @@ pub(super) fn check(
6765
return;
6866
}
6967

70-
let help = if variant == Variant::Unwrap && is_lint_allowed(cx, EXPECT_USED, expr.hir_id) {
71-
format!(
72-
"if you don't want to handle the `{none_value}` case gracefully, consider \
73-
using `expect{method_suffix}()` to provide a better panic message"
74-
)
75-
} else {
76-
format!("if this value is {none_prefix}`{none_value}`, it will panic")
77-
};
78-
79-
span_lint_and_help(
68+
span_lint_and_then(
8069
cx,
8170
variant.lint(),
8271
expr.span,
8372
&format!("used `{}()` on {kind} value", variant.method_name(is_err)),
84-
None,
85-
&help,
73+
|diag| {
74+
diag.note(format!("if this value is {none_prefix}`{none_value}`, it will panic"));
75+
76+
if variant == Variant::Unwrap && is_lint_allowed(cx, EXPECT_USED, expr.hir_id) {
77+
diag.help(format!(
78+
"consider using `expect{method_suffix}()` to provide a better panic message"
79+
));
80+
}
81+
},
8682
);
8783
}

clippy_utils/src/ty.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,11 @@ fn assert_generic_args_match<'tcx>(tcx: TyCtxt<'tcx>, did: DefId, args: &[Generi
10931093
}
10941094
}
10951095

1096+
/// Returns whether `ty` is never-like; i.e., `!` (never) or an enum with zero variants.
1097+
pub fn is_never_like(ty: Ty<'_>) -> bool {
1098+
ty.is_never() || (ty.is_enum() && ty.ty_adt_def().is_some_and(|def| def.variants().is_empty()))
1099+
}
1100+
10961101
/// Makes the projection type for the named associated type in the given impl or trait impl.
10971102
///
10981103
/// This function is for associated types which are "known" to exist, and as such, will only return

tests/ui-toml/expect_used/expect_used.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: used `expect()` on an `Option` value
44
LL | let _ = opt.expect("");
55
| ^^^^^^^^^^^^^^
66
|
7-
= help: if this value is `None`, it will panic
7+
= note: if this value is `None`, it will panic
88
= note: `-D clippy::expect-used` implied by `-D warnings`
99

1010
error: used `expect()` on a `Result` value
@@ -13,7 +13,7 @@ error: used `expect()` on a `Result` value
1313
LL | let _ = res.expect("");
1414
| ^^^^^^^^^^^^^^
1515
|
16-
= help: if this value is an `Err`, it will panic
16+
= note: if this value is an `Err`, it will panic
1717

1818
error: aborting due to 2 previous errors
1919

tests/ui-toml/unwrap_used/unwrap_used.stderr

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ error: used `unwrap()` on an `Option` value
1212
LL | let _ = boxed_slice.get(1).unwrap();
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
1414
|
15-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
15+
= note: if this value is `None`, it will panic
16+
= help: consider using `expect()` to provide a better panic message
1617
= note: `-D clippy::unwrap-used` implied by `-D warnings`
1718

1819
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
@@ -27,7 +28,8 @@ error: used `unwrap()` on an `Option` value
2728
LL | let _ = some_slice.get(0).unwrap();
2829
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
2930
|
30-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
31+
= note: if this value is `None`, it will panic
32+
= help: consider using `expect()` to provide a better panic message
3133

3234
error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
3335
--> $DIR/unwrap_used.rs:40:17
@@ -41,7 +43,8 @@ error: used `unwrap()` on an `Option` value
4143
LL | let _ = some_vec.get(0).unwrap();
4244
| ^^^^^^^^^^^^^^^^^^^^^^^^
4345
|
44-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
46+
= note: if this value is `None`, it will panic
47+
= help: consider using `expect()` to provide a better panic message
4548

4649
error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
4750
--> $DIR/unwrap_used.rs:41:17
@@ -55,7 +58,8 @@ error: used `unwrap()` on an `Option` value
5558
LL | let _ = some_vecdeque.get(0).unwrap();
5659
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5760
|
58-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
61+
= note: if this value is `None`, it will panic
62+
= help: consider using `expect()` to provide a better panic message
5963

6064
error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
6165
--> $DIR/unwrap_used.rs:42:17
@@ -69,7 +73,8 @@ error: used `unwrap()` on an `Option` value
6973
LL | let _ = some_hashmap.get(&1).unwrap();
7074
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7175
|
72-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
76+
= note: if this value is `None`, it will panic
77+
= help: consider using `expect()` to provide a better panic message
7378

7479
error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
7580
--> $DIR/unwrap_used.rs:43:17
@@ -83,7 +88,8 @@ error: used `unwrap()` on an `Option` value
8388
LL | let _ = some_btreemap.get(&1).unwrap();
8489
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8590
|
86-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
91+
= note: if this value is `None`, it will panic
92+
= help: consider using `expect()` to provide a better panic message
8793

8894
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
8995
--> $DIR/unwrap_used.rs:47:21
@@ -97,7 +103,8 @@ error: used `unwrap()` on an `Option` value
97103
LL | let _: u8 = *boxed_slice.get(1).unwrap();
98104
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
99105
|
100-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
106+
= note: if this value is `None`, it will panic
107+
= help: consider using `expect()` to provide a better panic message
101108

102109
error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
103110
--> $DIR/unwrap_used.rs:52:9
@@ -111,7 +118,8 @@ error: used `unwrap()` on an `Option` value
111118
LL | *boxed_slice.get_mut(0).unwrap() = 1;
112119
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
113120
|
114-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
121+
= note: if this value is `None`, it will panic
122+
= help: consider using `expect()` to provide a better panic message
115123

116124
error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
117125
--> $DIR/unwrap_used.rs:53:9
@@ -125,7 +133,8 @@ error: used `unwrap()` on an `Option` value
125133
LL | *some_slice.get_mut(0).unwrap() = 1;
126134
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
127135
|
128-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
136+
= note: if this value is `None`, it will panic
137+
= help: consider using `expect()` to provide a better panic message
129138

130139
error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
131140
--> $DIR/unwrap_used.rs:54:9
@@ -139,7 +148,8 @@ error: used `unwrap()` on an `Option` value
139148
LL | *some_vec.get_mut(0).unwrap() = 1;
140149
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
141150
|
142-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
151+
= note: if this value is `None`, it will panic
152+
= help: consider using `expect()` to provide a better panic message
143153

144154
error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
145155
--> $DIR/unwrap_used.rs:55:9
@@ -153,7 +163,8 @@ error: used `unwrap()` on an `Option` value
153163
LL | *some_vecdeque.get_mut(0).unwrap() = 1;
154164
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
155165
|
156-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
166+
= note: if this value is `None`, it will panic
167+
= help: consider using `expect()` to provide a better panic message
157168

158169
error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
159170
--> $DIR/unwrap_used.rs:67:17
@@ -167,7 +178,8 @@ error: used `unwrap()` on an `Option` value
167178
LL | let _ = some_vec.get(0..1).unwrap().to_vec();
168179
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
169180
|
170-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
181+
= note: if this value is `None`, it will panic
182+
= help: consider using `expect()` to provide a better panic message
171183

172184
error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
173185
--> $DIR/unwrap_used.rs:68:17
@@ -181,7 +193,8 @@ error: used `unwrap()` on an `Option` value
181193
LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec();
182194
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
183195
|
184-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
196+
= note: if this value is `None`, it will panic
197+
= help: consider using `expect()` to provide a better panic message
185198

186199
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
187200
--> $DIR/unwrap_used.rs:75:13

tests/ui/expect.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: used `expect()` on an `Option` value
44
LL | let _ = opt.expect("");
55
| ^^^^^^^^^^^^^^
66
|
7-
= help: if this value is `None`, it will panic
7+
= note: if this value is `None`, it will panic
88
= note: `-D clippy::expect-used` implied by `-D warnings`
99

1010
error: used `expect()` on a `Result` value
@@ -13,15 +13,15 @@ error: used `expect()` on a `Result` value
1313
LL | let _ = res.expect("");
1414
| ^^^^^^^^^^^^^^
1515
|
16-
= help: if this value is an `Err`, it will panic
16+
= note: if this value is an `Err`, it will panic
1717

1818
error: used `expect_err()` on a `Result` value
1919
--> $DIR/expect.rs:12:13
2020
|
2121
LL | let _ = res.expect_err("");
2222
| ^^^^^^^^^^^^^^^^^^
2323
|
24-
= help: if this value is an `Ok`, it will panic
24+
= note: if this value is an `Ok`, it will panic
2525

2626
error: aborting due to 3 previous errors
2727

tests/ui/get_unwrap.stderr

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ error: used `unwrap()` on an `Option` value
1616
LL | let _ = boxed_slice.get(1).unwrap();
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
1818
|
19-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
19+
= note: if this value is `None`, it will panic
20+
= help: consider using `expect()` to provide a better panic message
2021
= note: `-D clippy::unwrap-used` implied by `-D warnings`
2122

2223
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
@@ -31,7 +32,8 @@ error: used `unwrap()` on an `Option` value
3132
LL | let _ = some_slice.get(0).unwrap();
3233
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
3334
|
34-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
35+
= note: if this value is `None`, it will panic
36+
= help: consider using `expect()` to provide a better panic message
3537

3638
error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
3739
--> $DIR/get_unwrap.rs:40:17
@@ -45,7 +47,8 @@ error: used `unwrap()` on an `Option` value
4547
LL | let _ = some_vec.get(0).unwrap();
4648
| ^^^^^^^^^^^^^^^^^^^^^^^^
4749
|
48-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
50+
= note: if this value is `None`, it will panic
51+
= help: consider using `expect()` to provide a better panic message
4952

5053
error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
5154
--> $DIR/get_unwrap.rs:41:17
@@ -59,7 +62,8 @@ error: used `unwrap()` on an `Option` value
5962
LL | let _ = some_vecdeque.get(0).unwrap();
6063
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6164
|
62-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
65+
= note: if this value is `None`, it will panic
66+
= help: consider using `expect()` to provide a better panic message
6367

6468
error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
6569
--> $DIR/get_unwrap.rs:42:17
@@ -73,7 +77,8 @@ error: used `unwrap()` on an `Option` value
7377
LL | let _ = some_hashmap.get(&1).unwrap();
7478
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7579
|
76-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
80+
= note: if this value is `None`, it will panic
81+
= help: consider using `expect()` to provide a better panic message
7782

7883
error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
7984
--> $DIR/get_unwrap.rs:43:17
@@ -87,7 +92,8 @@ error: used `unwrap()` on an `Option` value
8792
LL | let _ = some_btreemap.get(&1).unwrap();
8893
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8994
|
90-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
95+
= note: if this value is `None`, it will panic
96+
= help: consider using `expect()` to provide a better panic message
9197

9298
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
9399
--> $DIR/get_unwrap.rs:47:21
@@ -101,7 +107,8 @@ error: used `unwrap()` on an `Option` value
101107
LL | let _: u8 = *boxed_slice.get(1).unwrap();
102108
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
103109
|
104-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
110+
= note: if this value is `None`, it will panic
111+
= help: consider using `expect()` to provide a better panic message
105112

106113
error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
107114
--> $DIR/get_unwrap.rs:52:9
@@ -115,7 +122,8 @@ error: used `unwrap()` on an `Option` value
115122
LL | *boxed_slice.get_mut(0).unwrap() = 1;
116123
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
117124
|
118-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
125+
= note: if this value is `None`, it will panic
126+
= help: consider using `expect()` to provide a better panic message
119127

120128
error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
121129
--> $DIR/get_unwrap.rs:53:9
@@ -129,7 +137,8 @@ error: used `unwrap()` on an `Option` value
129137
LL | *some_slice.get_mut(0).unwrap() = 1;
130138
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
131139
|
132-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
140+
= note: if this value is `None`, it will panic
141+
= help: consider using `expect()` to provide a better panic message
133142

134143
error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
135144
--> $DIR/get_unwrap.rs:54:9
@@ -143,7 +152,8 @@ error: used `unwrap()` on an `Option` value
143152
LL | *some_vec.get_mut(0).unwrap() = 1;
144153
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
145154
|
146-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
155+
= note: if this value is `None`, it will panic
156+
= help: consider using `expect()` to provide a better panic message
147157

148158
error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
149159
--> $DIR/get_unwrap.rs:55:9
@@ -157,7 +167,8 @@ error: used `unwrap()` on an `Option` value
157167
LL | *some_vecdeque.get_mut(0).unwrap() = 1;
158168
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
159169
|
160-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
170+
= note: if this value is `None`, it will panic
171+
= help: consider using `expect()` to provide a better panic message
161172

162173
error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
163174
--> $DIR/get_unwrap.rs:67:17
@@ -171,7 +182,8 @@ error: used `unwrap()` on an `Option` value
171182
LL | let _ = some_vec.get(0..1).unwrap().to_vec();
172183
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
173184
|
174-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
185+
= note: if this value is `None`, it will panic
186+
= help: consider using `expect()` to provide a better panic message
175187

176188
error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
177189
--> $DIR/get_unwrap.rs:68:17
@@ -185,7 +197,8 @@ error: used `unwrap()` on an `Option` value
185197
LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec();
186198
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
187199
|
188-
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
200+
= note: if this value is `None`, it will panic
201+
= help: consider using `expect()` to provide a better panic message
189202

190203
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
191204
--> $DIR/get_unwrap.rs:78:24

0 commit comments

Comments
 (0)