diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 1afd401ca68..66722786eab 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -183,7 +183,7 @@ fn lint_same_then_else(cx: &LateContext<'_, '_>, blocks: &[&Block<'_>]) { IF_SAME_THEN_ELSE, j.span, "this `if` has identical blocks", - i.span, + Some(i.span), "same as this", ); } @@ -206,7 +206,7 @@ fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) { IFS_SAME_COND, j.span, "this `if` has the same condition as a previous `if`", - i.span, + Some(i.span), "same as this", ); } @@ -234,7 +234,7 @@ fn lint_same_fns_in_if_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) { SAME_FUNCTIONS_IN_IF_CONDITION, j.span, "this `if` has the same function call as a previous `if`", - i.span, + Some(i.span), "same as this", ); } diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index 3e2d5b88e7b..d79aa2ef020 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyIterator { COPY_ITERATOR, item.span, "you are implementing `Iterator` on a `Copy` type", - item.span, + None, "consider implementing `IntoIterator` instead", ); } diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 7d34ef157e4..dc05f5b658f 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -168,7 +168,7 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item<'_>, trait EXPL_IMPL_CLONE_ON_COPY, item.span, "you are implementing `Clone` explicitly on a `Copy` type", - item.span, + Some(item.span), "consider deriving `Clone` or removing `Copy`", ); } diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 9a60b2f027a..9de9056c140 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -135,7 +135,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DropForgetRef { lint, expr.span, &msg, - arg.span, + Some(arg.span), &format!("argument has type `{}`", arg_ty)); } else if is_copy(cx, arg_ty) { if match_def_path(cx, def_id, &paths::DROP) { @@ -151,7 +151,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DropForgetRef { lint, expr.span, &msg, - arg.span, + Some(arg.span), &format!("argument has type {}", arg_ty)); } } diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 48b761260a5..5206266ccf2 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -310,7 +310,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { EVAL_ORDER_DEPENDENCE, expr.span, "unsequenced read of a variable", - self.write_expr.span, + Some(self.write_expr.span), "whether read occurs before this write depends on evaluation order" ); } diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index d2ee22e8706..eb4b7a826f2 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -149,7 +149,7 @@ fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) { really are doing `.. = ({op} ..)`", op = op ), - eqop_span, + None, &format!("to remove this lint, use either `{op}=` or `= {op}`", op = op), ); } @@ -227,7 +227,7 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) { SUSPICIOUS_ELSE_FORMATTING, else_span, &format!("this is an `else {}` but the formatting might hide it", else_desc), - else_span, + None, &format!( "to remove this lint, remove the `else` or remove the new line between \ `else` and `{}`", @@ -266,7 +266,7 @@ fn check_array(cx: &EarlyContext<'_>, expr: &Expr) { POSSIBLE_MISSING_COMMA, lint_span, "possibly missing a comma here", - lint_span, + None, "to remove this lint, add a comma or write the expr in a single line", ); } @@ -297,7 +297,7 @@ fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) { SUSPICIOUS_ELSE_FORMATTING, else_span, &format!("this looks like {} but the `else` is missing", looks_like), - else_span, + None, &format!( "to remove this lint, add the missing `else` or add a new line before {}", next_thing, diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 27e31222d00..270e306e15f 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -637,7 +637,7 @@ fn check_overlapping_arms<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ex: &'tcx Expr<' MATCH_OVERLAPPING_ARM, start.span, "some ranges overlap", - end.span, + Some(end.span), "overlaps with this", ); } @@ -675,7 +675,7 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>]) MATCH_WILD_ERR_ARM, arm.pat.span, &format!("`Err({})` matches all errors", &ident_bind_name), - arm.pat.span, + None, "match each error separately or use the error output", ); } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 578ee9e0bfd..7c652229d33 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2577,7 +2577,7 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( }, expr.span, msg, - expr.span, + None, &format!( "replace `map({0}).unwrap_or_else({1})` with `map_or_else({1}, {0})`", map_snippet, unwrap_snippet, @@ -2757,7 +2757,7 @@ fn lint_filter_next<'a, 'tcx>( FILTER_NEXT, expr.span, msg, - expr.span, + None, &format!("replace `filter({0}).next()` with `find({0})`", filter_snippet), ); } else { @@ -2816,7 +2816,7 @@ fn lint_filter_map_next<'a, 'tcx>( FILTER_MAP_NEXT, expr.span, msg, - expr.span, + None, &format!("replace `filter_map({0}).next()` with `find_map({0})`", filter_snippet), ); } else { diff --git a/clippy_lints/src/utils/diagnostics.rs b/clippy_lints/src/utils/diagnostics.rs index 3fb6cf966af..d596d86370f 100644 --- a/clippy_lints/src/utils/diagnostics.rs +++ b/clippy_lints/src/utils/diagnostics.rs @@ -108,15 +108,15 @@ pub fn span_lint_and_note<'a, T: LintContext>( lint: &'static Lint, span: Span, msg: &str, - note_span: Span, + note_span: Option, note: &str, ) { - cx.struct_span_lint(lint, span, |diag| { - let mut diag = diag.build(msg); - if note_span == span { - diag.note(note); + cx.struct_span_lint(lint, span, |ldb| { + let mut db = ldb.build(msg); + if let Some(note_span) = note_span { + db.span_note(note_span, note); } else { - diag.span_note(note_span, note); + db.note(note); } docs_link(&mut diag, lint); diag.emit(); diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 803d3b2bc86..6ac8d5e71b3 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -198,8 +198,8 @@ declare_clippy_lint! { /// ); /// span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg); /// span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg); - /// span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, expr.span, note_msg); - /// span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, expr.span, note_msg); + /// span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg); + /// span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg); /// ``` pub COLLAPSIBLE_SPAN_LINT_CALLS, internal, @@ -486,7 +486,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CollapsibleCalls { }, "span_note" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => { let note_snippet = snippet(cx, span_call_args[2].span, r#""...""#); - suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow()); + suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true); }, "help" => { let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#); @@ -494,7 +494,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CollapsibleCalls { } "note" => { let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#); - suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow()); + suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false); } _ => (), } @@ -606,7 +606,19 @@ fn suggest_help( ); } -fn suggest_note(cx: &LateContext<'_, '_>, expr: &Expr<'_>, and_then_snippets: &AndThenSnippets<'_>, note: &str) { +fn suggest_note( + cx: &LateContext<'_, '_>, + expr: &Expr<'_>, + and_then_snippets: &AndThenSnippets<'_>, + note: &str, + with_span: bool, +) { + let note_span = if with_span { + format!("Some({})", and_then_snippets.span) + } else { + "None".to_string() + }; + span_lint_and_sugg( cx, COLLAPSIBLE_SPAN_LINT_CALLS, @@ -619,7 +631,7 @@ fn suggest_note(cx: &LateContext<'_, '_>, expr: &Expr<'_>, and_then_snippets: &A and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg, - and_then_snippets.span, + note_span, note ), Applicability::MachineApplicable, diff --git a/tests/ui/collapsible_span_lint_calls.fixed b/tests/ui/collapsible_span_lint_calls.fixed index a22046d34a2..e588c23345e 100644 --- a/tests/ui/collapsible_span_lint_calls.fixed +++ b/tests/ui/collapsible_span_lint_calls.fixed @@ -38,7 +38,7 @@ fn span_lint_and_note<'a, T: LintContext>( lint: &'static Lint, span: Span, msg: &str, - note_span: Span, + note_span: Option, note: &str, ) { } @@ -75,8 +75,8 @@ impl EarlyLintPass for Pass { span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable); span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg); span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg); - span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, expr.span, note_msg); - span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, expr.span, note_msg); + span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg); + span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg); // This expr shouldn't trigger this lint. span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { diff --git a/tests/ui/collapsible_span_lint_calls.rs b/tests/ui/collapsible_span_lint_calls.rs index 69b95255751..d5dd3bb562b 100644 --- a/tests/ui/collapsible_span_lint_calls.rs +++ b/tests/ui/collapsible_span_lint_calls.rs @@ -38,7 +38,7 @@ fn span_lint_and_note<'a, T: LintContext>( lint: &'static Lint, span: Span, msg: &str, - note_span: Span, + note_span: Option, note: &str, ) { } diff --git a/tests/ui/collapsible_span_lint_calls.stderr b/tests/ui/collapsible_span_lint_calls.stderr index e6d5c3efa22..874d4a9f255 100644 --- a/tests/ui/collapsible_span_lint_calls.stderr +++ b/tests/ui/collapsible_span_lint_calls.stderr @@ -35,7 +35,7 @@ error: this call is collspible LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | db.span_note(expr.span, note_msg); LL | | }); - | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, expr.span, note_msg)` + | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg)` error: this call is collspible --> $DIR/collapsible_span_lint_calls.rs:87:9 @@ -43,7 +43,7 @@ error: this call is collspible LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | db.note(note_msg); LL | | }); - | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, expr.span, note_msg)` + | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg)` error: aborting due to 5 previous errors