option_option: split part of diagnostic message into help message (#15870)
changelog: [`option_option`]: improve diagnostic message
This commit is contained in:
commit
973e596eb0
3 changed files with 65 additions and 35 deletions
|
|
@ -1,6 +1,7 @@
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::qpath_generic_tys;
|
||||
use clippy_utils::res::MaybeResPath;
|
||||
use clippy_utils::source::snippet;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, QPath};
|
||||
use rustc_lint::LateContext;
|
||||
|
|
@ -13,12 +14,21 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
|
|||
&& let Some(arg) = qpath_generic_tys(qpath).next()
|
||||
&& arg.basic_res().opt_def_id() == Some(def_id)
|
||||
{
|
||||
span_lint(
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
OPTION_OPTION,
|
||||
hir_ty.span,
|
||||
"consider using `Option<T>` instead of `Option<Option<T>>` or a custom \
|
||||
enum if you need to distinguish all 3 cases",
|
||||
// use just `T` here, as the inner type is not what's problematic
|
||||
"use of `Option<Option<T>>`",
|
||||
|diag| {
|
||||
// but use the specific type here, as:
|
||||
// - this is kind of a suggestion
|
||||
// - it's printed right after the linted type
|
||||
let inner_opt = snippet(cx, arg.span, "_");
|
||||
diag.help(format!(
|
||||
"consider using `{inner_opt}`, or a custom enum if you need to distinguish all 3 cases"
|
||||
));
|
||||
},
|
||||
);
|
||||
true
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,52 +1,52 @@
|
|||
#![deny(clippy::option_option)]
|
||||
#![allow(clippy::unnecessary_wraps, clippy::manual_unwrap_or_default)]
|
||||
#![warn(clippy::option_option)]
|
||||
#![expect(clippy::unnecessary_wraps)]
|
||||
|
||||
const C: Option<Option<i32>> = None;
|
||||
//~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if
|
||||
//~^ option_option
|
||||
static S: Option<Option<i32>> = None;
|
||||
//~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if
|
||||
//~^ option_option
|
||||
|
||||
fn input(_: Option<Option<u8>>) {}
|
||||
//~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if
|
||||
//~^ option_option
|
||||
|
||||
fn output() -> Option<Option<u8>> {
|
||||
//~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if
|
||||
//~^ option_option
|
||||
None
|
||||
}
|
||||
|
||||
fn output_nested() -> Vec<Option<Option<u8>>> {
|
||||
//~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if
|
||||
//~^ option_option
|
||||
vec![None]
|
||||
}
|
||||
|
||||
// The lint only generates one warning for this
|
||||
fn output_nested_nested() -> Option<Option<Option<u8>>> {
|
||||
//~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if
|
||||
//~^ option_option
|
||||
None
|
||||
}
|
||||
|
||||
struct Struct {
|
||||
x: Option<Option<u8>>,
|
||||
//~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum
|
||||
//~^ option_option
|
||||
}
|
||||
|
||||
impl Struct {
|
||||
fn struct_fn() -> Option<Option<u8>> {
|
||||
//~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum
|
||||
//~^ option_option
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait Trait {
|
||||
fn trait_fn() -> Option<Option<u8>>;
|
||||
//~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum
|
||||
//~^ option_option
|
||||
}
|
||||
|
||||
enum Enum {
|
||||
Tuple(Option<Option<u8>>),
|
||||
//~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum
|
||||
//~^ option_option
|
||||
Struct { x: Option<Option<u8>> },
|
||||
//~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum
|
||||
//~^ option_option
|
||||
}
|
||||
|
||||
// The lint allows this
|
||||
|
|
@ -88,7 +88,7 @@ mod issue_4298 {
|
|||
#[serde(default)]
|
||||
#[serde(borrow)]
|
||||
foo: Option<Option<Cow<'a, str>>>,
|
||||
//~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom
|
||||
//~^ option_option
|
||||
}
|
||||
|
||||
#[allow(clippy::option_option)]
|
||||
|
|
|
|||
|
|
@ -1,80 +1,100 @@
|
|||
error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
|
||||
error: use of `Option<Option<T>>`
|
||||
--> tests/ui/option_option.rs:4:10
|
||||
|
|
||||
LL | const C: Option<Option<i32>> = None;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> tests/ui/option_option.rs:1:9
|
||||
|
|
||||
LL | #![deny(clippy::option_option)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
= help: consider using `Option<i32>`, or a custom enum if you need to distinguish all 3 cases
|
||||
= note: `-D clippy::option-option` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::option_option)]`
|
||||
|
||||
error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
|
||||
error: use of `Option<Option<T>>`
|
||||
--> tests/ui/option_option.rs:6:11
|
||||
|
|
||||
LL | static S: Option<Option<i32>> = None;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `Option<i32>`, or a custom enum if you need to distinguish all 3 cases
|
||||
|
||||
error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
|
||||
error: use of `Option<Option<T>>`
|
||||
--> tests/ui/option_option.rs:9:13
|
||||
|
|
||||
LL | fn input(_: Option<Option<u8>>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `Option<u8>`, or a custom enum if you need to distinguish all 3 cases
|
||||
|
||||
error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
|
||||
error: use of `Option<Option<T>>`
|
||||
--> tests/ui/option_option.rs:12:16
|
||||
|
|
||||
LL | fn output() -> Option<Option<u8>> {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `Option<u8>`, or a custom enum if you need to distinguish all 3 cases
|
||||
|
||||
error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
|
||||
error: use of `Option<Option<T>>`
|
||||
--> tests/ui/option_option.rs:17:27
|
||||
|
|
||||
LL | fn output_nested() -> Vec<Option<Option<u8>>> {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `Option<u8>`, or a custom enum if you need to distinguish all 3 cases
|
||||
|
||||
error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
|
||||
error: use of `Option<Option<T>>`
|
||||
--> tests/ui/option_option.rs:23:30
|
||||
|
|
||||
LL | fn output_nested_nested() -> Option<Option<Option<u8>>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `Option<Option<u8>>`, or a custom enum if you need to distinguish all 3 cases
|
||||
|
||||
error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
|
||||
error: use of `Option<Option<T>>`
|
||||
--> tests/ui/option_option.rs:29:8
|
||||
|
|
||||
LL | x: Option<Option<u8>>,
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `Option<u8>`, or a custom enum if you need to distinguish all 3 cases
|
||||
|
||||
error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
|
||||
error: use of `Option<Option<T>>`
|
||||
--> tests/ui/option_option.rs:34:23
|
||||
|
|
||||
LL | fn struct_fn() -> Option<Option<u8>> {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `Option<u8>`, or a custom enum if you need to distinguish all 3 cases
|
||||
|
||||
error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
|
||||
error: use of `Option<Option<T>>`
|
||||
--> tests/ui/option_option.rs:41:22
|
||||
|
|
||||
LL | fn trait_fn() -> Option<Option<u8>>;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `Option<u8>`, or a custom enum if you need to distinguish all 3 cases
|
||||
|
||||
error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
|
||||
error: use of `Option<Option<T>>`
|
||||
--> tests/ui/option_option.rs:46:11
|
||||
|
|
||||
LL | Tuple(Option<Option<u8>>),
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `Option<u8>`, or a custom enum if you need to distinguish all 3 cases
|
||||
|
||||
error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
|
||||
error: use of `Option<Option<T>>`
|
||||
--> tests/ui/option_option.rs:48:17
|
||||
|
|
||||
LL | Struct { x: Option<Option<u8>> },
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `Option<u8>`, or a custom enum if you need to distinguish all 3 cases
|
||||
|
||||
error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
|
||||
error: use of `Option<Option<T>>`
|
||||
--> tests/ui/option_option.rs:90:14
|
||||
|
|
||||
LL | foo: Option<Option<Cow<'a, str>>>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `Option<Cow<'a, str>>`, or a custom enum if you need to distinguish all 3 cases
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue