Extract never-like into clippy_utils

This commit is contained in:
Catherine Flores 2023-08-02 13:57:06 -05:00
parent 779e0f4021
commit 71c54137ea
8 changed files with 89 additions and 59 deletions

View File

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::{is_never_like, is_type_diagnostic_item};
use clippy_utils::{is_in_cfg_test, is_in_test_function, is_lint_allowed};
use rustc_hir::Expr;
use rustc_lint::{LateContext, Lint};
@ -32,7 +32,8 @@ impl Variant {
}
}
/// lint use of `unwrap()` or `unwrap_err` for `Result` and `unwrap()` for `Option`.
/// Lint usage of `unwrap` or `unwrap_err` for `Result` and `unwrap()` for `Option` (and their
/// `expect` counterparts).
pub(super) fn check(
cx: &LateContext<'_>,
expr: &Expr<'_>,
@ -49,10 +50,7 @@ pub(super) fn check(
&& let ty::Adt(_, substs) = ty.kind()
&& let Some(t_or_e_ty) = substs[usize::from(!is_err)].as_type()
{
// Issue #11245: Do not lint `!` or never-like enums
if t_or_e_ty.is_never()
|| (t_or_e_ty.is_enum() && t_or_e_ty.ty_adt_def().is_some_and(|def| def.variants().is_empty()))
{
if is_never_like(t_or_e_ty) {
return;
}
@ -67,21 +65,19 @@ pub(super) fn check(
return;
}
let help = if variant == Variant::Unwrap && is_lint_allowed(cx, EXPECT_USED, expr.hir_id) {
format!(
"if you don't want to handle the `{none_value}` case gracefully, consider \
using `expect{method_suffix}()` to provide a better panic message"
)
} else {
format!("if this value is {none_prefix}`{none_value}`, it will panic")
};
span_lint_and_help(
span_lint_and_then(
cx,
variant.lint(),
expr.span,
&format!("used `{}()` on {kind} value", variant.method_name(is_err)),
None,
&help,
|diag| {
diag.note(format!("if this value is {none_prefix}`{none_value}`, it will panic"));
if variant == Variant::Unwrap && is_lint_allowed(cx, EXPECT_USED, expr.hir_id) {
diag.help(format!(
"consider using `expect{method_suffix}()` to provide a better panic message"
));
}
},
);
}

View File

@ -1093,6 +1093,11 @@ fn assert_generic_args_match<'tcx>(tcx: TyCtxt<'tcx>, did: DefId, args: &[Generi
}
}
/// Returns whether `ty` is never-like; i.e., `!` (never) or an enum with zero variants.
pub fn is_never_like(ty: Ty<'_>) -> bool {
ty.is_never() || (ty.is_enum() && ty.ty_adt_def().is_some_and(|def| def.variants().is_empty()))
}
/// Makes the projection type for the named associated type in the given impl or trait impl.
///
/// This function is for associated types which are "known" to exist, and as such, will only return

View File

@ -4,7 +4,7 @@ error: used `expect()` on an `Option` value
LL | let _ = opt.expect("");
| ^^^^^^^^^^^^^^
|
= help: if this value is `None`, it will panic
= note: if this value is `None`, it will panic
= note: `-D clippy::expect-used` implied by `-D warnings`
error: used `expect()` on a `Result` value
@ -13,7 +13,7 @@ error: used `expect()` on a `Result` value
LL | let _ = res.expect("");
| ^^^^^^^^^^^^^^
|
= help: if this value is an `Err`, it will panic
= note: if this value is an `Err`, it will panic
error: aborting due to 2 previous errors

View File

@ -12,7 +12,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = boxed_slice.get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
= note: `-D clippy::unwrap-used` implied by `-D warnings`
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
LL | let _ = some_slice.get(0).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:40:17
@ -41,7 +43,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = some_vec.get(0).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:41:17
@ -55,7 +58,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = some_vecdeque.get(0).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:42:17
@ -69,7 +73,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = some_hashmap.get(&1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:43:17
@ -83,7 +88,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = some_btreemap.get(&1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:47:21
@ -97,7 +103,8 @@ error: used `unwrap()` on an `Option` value
LL | let _: u8 = *boxed_slice.get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:52:9
@ -111,7 +118,8 @@ error: used `unwrap()` on an `Option` value
LL | *boxed_slice.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:53:9
@ -125,7 +133,8 @@ error: used `unwrap()` on an `Option` value
LL | *some_slice.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:54:9
@ -139,7 +148,8 @@ error: used `unwrap()` on an `Option` value
LL | *some_vec.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:55:9
@ -153,7 +163,8 @@ error: used `unwrap()` on an `Option` value
LL | *some_vecdeque.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:67:17
@ -167,7 +178,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = some_vec.get(0..1).unwrap().to_vec();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:68:17
@ -181,7 +193,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:75:13

View File

@ -4,7 +4,7 @@ error: used `expect()` on an `Option` value
LL | let _ = opt.expect("");
| ^^^^^^^^^^^^^^
|
= help: if this value is `None`, it will panic
= note: if this value is `None`, it will panic
= note: `-D clippy::expect-used` implied by `-D warnings`
error: used `expect()` on a `Result` value
@ -13,7 +13,7 @@ error: used `expect()` on a `Result` value
LL | let _ = res.expect("");
| ^^^^^^^^^^^^^^
|
= help: if this value is an `Err`, it will panic
= note: if this value is an `Err`, it will panic
error: used `expect_err()` on a `Result` value
--> $DIR/expect.rs:12:13
@ -21,7 +21,7 @@ error: used `expect_err()` on a `Result` value
LL | let _ = res.expect_err("");
| ^^^^^^^^^^^^^^^^^^
|
= help: if this value is an `Ok`, it will panic
= note: if this value is an `Ok`, it will panic
error: aborting due to 3 previous errors

View File

@ -16,7 +16,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = boxed_slice.get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
= note: `-D clippy::unwrap-used` implied by `-D warnings`
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
LL | let _ = some_slice.get(0).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:40:17
@ -45,7 +47,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = some_vec.get(0).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:41:17
@ -59,7 +62,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = some_vecdeque.get(0).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:42:17
@ -73,7 +77,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = some_hashmap.get(&1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:43:17
@ -87,7 +92,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = some_btreemap.get(&1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:47:21
@ -101,7 +107,8 @@ error: used `unwrap()` on an `Option` value
LL | let _: u8 = *boxed_slice.get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:52:9
@ -115,7 +122,8 @@ error: used `unwrap()` on an `Option` value
LL | *boxed_slice.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:53:9
@ -129,7 +137,8 @@ error: used `unwrap()` on an `Option` value
LL | *some_slice.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:54:9
@ -143,7 +152,8 @@ error: used `unwrap()` on an `Option` value
LL | *some_vec.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:55:9
@ -157,7 +167,8 @@ error: used `unwrap()` on an `Option` value
LL | *some_vecdeque.get_mut(0).unwrap() = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:67:17
@ -171,7 +182,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = some_vec.get(0..1).unwrap().to_vec();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:68:17
@ -185,7 +197,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:78:24

View File

@ -4,7 +4,8 @@ error: used `unwrap()` on an `Option` value
LL | let _ = opt.unwrap();
| ^^^^^^^^^^^^
|
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
= note: `-D clippy::unwrap-used` implied by `-D warnings`
error: used `unwrap()` on a `Result` value
@ -13,7 +14,8 @@ error: used `unwrap()` on a `Result` value
LL | let _ = res.unwrap();
| ^^^^^^^^^^^^
|
= help: if you don't want to handle the `Err` case gracefully, consider using `expect()` to provide a better panic message
= note: if this value is an `Err`, it will panic
= help: consider using `expect()` to provide a better panic message
error: used `unwrap_err()` on a `Result` value
--> $DIR/unwrap.rs:12:13
@ -21,7 +23,8 @@ error: used `unwrap_err()` on a `Result` value
LL | let _ = res.unwrap_err();
| ^^^^^^^^^^^^^^^^
|
= help: if you don't want to handle the `Ok` case gracefully, consider using `expect_err()` to provide a better panic message
= note: if this value is an `Ok`, it will panic
= help: consider using `expect_err()` to provide a better panic message
error: aborting due to 3 previous errors

View File

@ -4,7 +4,7 @@ error: used `unwrap()` on an `Option` value
LL | Some(3).unwrap();
| ^^^^^^^^^^^^^^^^
|
= help: if this value is `None`, it will panic
= note: if this value is `None`, it will panic
= note: `-D clippy::unwrap-used` implied by `-D warnings`
error: used `expect()` on an `Option` value
@ -13,7 +13,7 @@ error: used `expect()` on an `Option` value
LL | Some(3).expect("Hello world!");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if this value is `None`, it will panic
= note: if this value is `None`, it will panic
= note: `-D clippy::expect-used` implied by `-D warnings`
error: used `unwrap()` on a `Result` value
@ -22,7 +22,7 @@ error: used `unwrap()` on a `Result` value
LL | a.unwrap();
| ^^^^^^^^^^
|
= help: if this value is an `Err`, it will panic
= note: if this value is an `Err`, it will panic
error: used `expect()` on a `Result` value
--> $DIR/unwrap_expect_used.rs:44:5
@ -30,7 +30,7 @@ error: used `expect()` on a `Result` value
LL | a.expect("Hello world!");
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if this value is an `Err`, it will panic
= note: if this value is an `Err`, it will panic
error: used `unwrap_err()` on a `Result` value
--> $DIR/unwrap_expect_used.rs:45:5
@ -38,7 +38,7 @@ error: used `unwrap_err()` on a `Result` value
LL | a.unwrap_err();
| ^^^^^^^^^^^^^^
|
= help: if this value is an `Ok`, it will panic
= note: if this value is an `Ok`, it will panic
error: used `expect_err()` on a `Result` value
--> $DIR/unwrap_expect_used.rs:46:5
@ -46,7 +46,7 @@ error: used `expect_err()` on a `Result` value
LL | a.expect_err("Hello error!");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if this value is an `Ok`, it will panic
= note: if this value is an `Ok`, it will panic
error: aborting due to 6 previous errors