diff --git a/clippy_lints/src/manual_option_as_slice.rs b/clippy_lints/src/manual_option_as_slice.rs index 59b5de6e7e0b..3342bf834785 100644 --- a/clippy_lints/src/manual_option_as_slice.rs +++ b/clippy_lints/src/manual_option_as_slice.rs @@ -1,7 +1,8 @@ use clippy_config::Conf; -use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::Msrv; use clippy_utils::res::{MaybeDef, MaybeQPath, MaybeResPath}; +use clippy_utils::source::snippet_with_context; use clippy_utils::{is_none_pattern, msrvs, peel_hir_expr_refs, sym}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -133,19 +134,22 @@ fn check_as_ref(cx: &LateContext<'_>, expr: &Expr<'_>, span: Span, msrv: Msrv) { }, ) { - if let Some(snippet) = clippy_utils::source::snippet_opt(cx, callee.span) { - span_lint_and_sugg( - cx, - MANUAL_OPTION_AS_SLICE, - span, - "use `Option::as_slice`", - "use", - format!("{snippet}.as_slice()"), - Applicability::MachineApplicable, - ); - } else { - span_lint(cx, MANUAL_OPTION_AS_SLICE, span, "use `Option_as_slice`"); - } + span_lint_and_then( + cx, + MANUAL_OPTION_AS_SLICE, + span, + "manual implementation of `Option::as_slice`", + |diag| { + let mut app = Applicability::MachineApplicable; + let callee = snippet_with_context(cx, callee.span, expr.span.ctxt(), "_", &mut app).0; + diag.span_suggestion_verbose( + span, + "use `Option::as_slice` directly", + format!("{callee}.as_slice()"), + app, + ); + }, + ); } } diff --git a/tests/ui/manual_option_as_slice.stderr b/tests/ui/manual_option_as_slice.stderr index e240ae8eb7d9..37113e9eafe1 100644 --- a/tests/ui/manual_option_as_slice.stderr +++ b/tests/ui/manual_option_as_slice.stderr @@ -1,4 +1,4 @@ -error: use `Option::as_slice` +error: manual implementation of `Option::as_slice` --> tests/ui/manual_option_as_slice.rs:5:9 | LL | _ = match x.as_ref() { @@ -7,12 +7,21 @@ LL | | LL | | Some(f) => std::slice::from_ref(f), LL | | None => &[], LL | | }; - | |_____^ help: use: `x.as_slice()` + | |_____^ | = note: `-D clippy::manual-option-as-slice` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_option_as_slice)]` +help: use `Option::as_slice` directly + | +LL - _ = match x.as_ref() { +LL - +LL - Some(f) => std::slice::from_ref(f), +LL - None => &[], +LL - }; +LL + _ = x.as_slice(); + | -error: use `Option::as_slice` +error: manual implementation of `Option::as_slice` --> tests/ui/manual_option_as_slice.rs:11:9 | LL | _ = if let Some(f) = x.as_ref() { @@ -23,37 +32,79 @@ LL | | std::slice::from_ref(f) LL | | } else { LL | | &[] LL | | }; - | |_____^ help: use: `x.as_slice()` + | |_____^ + | +help: use `Option::as_slice` directly + | +LL - _ = if let Some(f) = x.as_ref() { +LL - +LL - +LL - std::slice::from_ref(f) +LL - } else { +LL - &[] +LL - }; +LL + _ = x.as_slice(); + | -error: use `Option::as_slice` +error: manual implementation of `Option::as_slice` --> tests/ui/manual_option_as_slice.rs:19:9 | LL | _ = x.as_ref().map_or(&[][..], std::slice::from_ref); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `Option::as_slice` directly + | +LL - _ = x.as_ref().map_or(&[][..], std::slice::from_ref); +LL + _ = x.as_slice(); + | -error: use `Option::as_slice` +error: manual implementation of `Option::as_slice` --> tests/ui/manual_option_as_slice.rs:22:9 | LL | _ = x.as_ref().map_or_else(Default::default, std::slice::from_ref); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `Option::as_slice` directly + | +LL - _ = x.as_ref().map_or_else(Default::default, std::slice::from_ref); +LL + _ = x.as_slice(); + | -error: use `Option::as_slice` +error: manual implementation of `Option::as_slice` --> tests/ui/manual_option_as_slice.rs:25:9 | LL | _ = x.as_ref().map(std::slice::from_ref).unwrap_or_default(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `Option::as_slice` directly + | +LL - _ = x.as_ref().map(std::slice::from_ref).unwrap_or_default(); +LL + _ = x.as_slice(); + | -error: use `Option::as_slice` +error: manual implementation of `Option::as_slice` --> tests/ui/manual_option_as_slice.rs:28:9 | LL | _ = x.as_ref().map_or_else(|| &[42][..0], std::slice::from_ref); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `Option::as_slice` directly + | +LL - _ = x.as_ref().map_or_else(|| &[42][..0], std::slice::from_ref); +LL + _ = x.as_slice(); + | -error: use `Option::as_slice` +error: manual implementation of `Option::as_slice` --> tests/ui/manual_option_as_slice.rs:33:13 | LL | _ = x.as_ref().map_or_else(<&[_]>::default, from_ref); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `Option::as_slice` directly + | +LL - _ = x.as_ref().map_or_else(<&[_]>::default, from_ref); +LL + _ = x.as_slice(); + | error: aborting due to 7 previous errors