diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6bd5cde12abb..8acbff53cf01 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1021,7 +1021,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box wildcard_imports::WildcardImports); store.register_early_pass(|| box macro_use::MacroUseImports); store.register_late_pass(|| box verbose_file_reads::VerboseFileReads); - store.register_early_pass(|| box utils::internal_lints::CollapsibleCalls); + store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1125,13 +1125,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![ LintId::of(&utils::internal_lints::CLIPPY_LINTS_INTERNAL), + LintId::of(&utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS), LintId::of(&utils::internal_lints::COMPILER_LINT_FUNCTIONS), LintId::of(&utils::internal_lints::DEFAULT_LINT), LintId::of(&utils::internal_lints::LINT_WITHOUT_LINT_PASS), LintId::of(&utils::internal_lints::OUTER_EXPN_EXPN_DATA), LintId::of(&utils::internal_lints::PRODUCE_ICE), - LintId::of(&utils::internal_lints::DEFAULT_LINT), - LintId::of(&utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS), ]); store.register_group(true, "clippy::all", Some("clippy"), vec![ diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 35c2040c8b0a..a08b227e7c5d 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,25 +1,23 @@ +use crate::utils::SpanlessEq; use crate::utils::{ - is_expn_of, match_def_path, match_type, method_calls, paths, span_lint, span_lint_and_help, span_lint_and_sugg, - walk_ptrs_ty, snippet as other_snippet, match_path_ast + is_expn_of, match_def_path, match_qpath, match_type, method_calls, paths, snippet as other_snippet, span_lint, + span_lint_and_help, span_lint_and_sugg, walk_ptrs_ty, }; use if_chain::if_chain; use rustc::hir::map::Map; -use rustc_ast::ast; -use rustc_ast::ast::{Crate as AstCrate, Expr as AstExpr, ItemKind, LitKind, Name, NodeId}; +use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, Name, NodeId}; use rustc_ast::visit::FnKind; -use rustc_ast::ptr::P; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::{Crate, Expr, ExprKind, HirId, Item, MutTy, Mutability, Path, Ty, TyKind}; +use rustc_hir::{Crate, Expr, ExprKind, HirId, Item, MutTy, Mutability, Path, StmtKind, Ty, TyKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::SymbolStr; - use std::borrow::Cow; declare_clippy_lint! { @@ -176,7 +174,7 @@ impl EarlyLintPass for ClippyLintsInternal { CLIPPY_LINTS_INTERNAL, item.span, "this constant should be before the previous constant due to lexical \ - ordering", + ordering", ); } } @@ -206,8 +204,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { if let ExprKind::AddrOf(_, _, ref inner_exp) = expr.kind; if let ExprKind::Struct(_, ref fields, _) = inner_exp.kind; let field = fields.iter() - .find(|f| f.ident.as_str() == "desc") - .expect("lints must have a description field"); + .find(|f| f.ident.as_str() == "desc") + .expect("lints must have a description field"); if let ExprKind::Lit(Spanned { node: LitKind::Str(ref sym, _), .. @@ -343,7 +341,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions { if let Some(sugg) = self.map.get(&*fn_name.as_str()); let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0])); if match_type(cx, ty, &paths::EARLY_CONTEXT) - || match_type(cx, ty, &paths::LATE_CONTEXT); + || match_type(cx, ty, &paths::LATE_CONTEXT); then { span_lint_and_help( cx, @@ -405,30 +403,49 @@ fn is_trigger_fn(fn_kind: FnKind<'_>) -> bool { declare_lint_pass!(CollapsibleCalls => [COLLAPSIBLE_SPAN_LINT_CALLS]); -impl EarlyLintPass for CollapsibleCalls { - fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &AstExpr) { - use ast::{StmtKind, ExprKind}; - +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CollapsibleCalls { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { if_chain! { if let ExprKind::Call(ref func, ref and_then_args) = expr.kind; - if let ExprKind::Path(None, ref path) = func.kind; - if match_path_ast(path, &["span_lint_and_then"]); + if let ExprKind::Path(ref path) = func.kind; + if match_qpath(path, &["span_lint_and_then"]); if and_then_args.len() == 5; - if let ExprKind::Closure(_, _, _, _, block, _) = &and_then_args[4].kind; - if let ExprKind::Block(block, _) = &block.kind; + if let ExprKind::Closure(_, _, body_id, _, _) = &and_then_args[4].kind; + if let body = cx.tcx.hir().body(*body_id); + if let ExprKind::Block(block, _) = &body.value.kind; let stmts = &block.stmts; if stmts.len() == 1; - if let StmtKind::Expr(only_expr) = &stmts[0].kind; - if let ExprKind::MethodCall(ref ps, ref span_call_args) = &only_expr.kind; - let and_then_args = get_and_then_args(cx, and_then_args); + // + if let StmtKind::Semi(only_expr) = &stmts[0].kind; + if let ExprKind::MethodCall(ref ps, _, ref span_call_args) = &only_expr.kind; + let and_then_snippets = get_and_then_snippets(cx, and_then_args); + let mut sle = SpanlessEq::new(cx).ignore_fn(); then { match &*ps.ident.as_str() { - "span_suggestion" => - suggest_span_suggestion(cx, expr, and_then_args, suggestion_args(cx, span_call_args)), - "span_help" => - suggest_span_help(cx, expr, and_then_args, help_args(cx, span_call_args)), - "span_note" => - suggest_span_note(cx, expr, and_then_args, note_args(cx, span_call_args)), + "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => { + suggest_suggestion(cx, expr, and_then_snippets, span_suggestion_snippets(cx, span_call_args)); + }, + "span_suggestion" => { + dbg!(&span_call_args[0]); + dbg!(&span_call_args[1]); + dbg!(&span_call_args[2]); + } + "span_help" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => { + let help_snippet = snippet(cx, span_call_args[2].span); + suggest_help(cx, expr, and_then_snippets, help_snippet); + }, + "span_note" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => { + let note_snippet = snippet(cx, span_call_args[2].span); + suggest_note(cx, expr, and_then_snippets, note_snippet); + }, + "help" => { + let help_snippet = snippet(cx, span_call_args[1].span); + suggest_help(cx, expr, and_then_snippets, help_snippet); + } + "note" => { + let note_snippet = snippet(cx, span_call_args[1].span); + suggest_note(cx, expr, and_then_snippets, note_snippet); + } _ => (), } } @@ -436,20 +453,23 @@ impl EarlyLintPass for CollapsibleCalls { } } -struct AndThenArgs<'a> { +struct AndThenSnippets<'a> { cx: Cow<'a, str>, lint: Cow<'a, str>, span: Cow<'a, str>, msg: Cow<'a, str>, } -fn get_and_then_args<'a>(cx: &EarlyContext<'_>, and_then_args: &Vec>) -> AndThenArgs<'a>{ - let cx_snippet = snippet(cx, and_then_args[0].span); - let lint_snippet= snippet(cx, and_then_args[1].span); - let span_snippet = snippet(cx, and_then_args[2].span); - let msg_snippet= snippet(cx, and_then_args[3].span); +fn get_and_then_snippets<'a, 'hir>( + cx: &LateContext<'_, '_>, + and_then_snippets: &'hir [Expr<'hir>], +) -> AndThenSnippets<'a> { + let cx_snippet = snippet(cx, and_then_snippets[0].span); + let lint_snippet = snippet(cx, and_then_snippets[1].span); + let span_snippet = snippet(cx, and_then_snippets[2].span); + let msg_snippet = snippet(cx, and_then_snippets[3].span); - AndThenArgs { + AndThenSnippets { cx: cx_snippet, lint: lint_snippet, span: span_snippet, @@ -457,123 +477,88 @@ fn get_and_then_args<'a>(cx: &EarlyContext<'_>, and_then_args: &Vec>) } } -struct SuggestionArgs<'a> { - span: Cow<'a, str>, +struct SpanSuggestionSnippets<'a> { help: Cow<'a, str>, sugg: Cow<'a, str>, applicability: Cow<'a, str>, } -fn suggestion_args<'a>(cx: &EarlyContext<'_>, span_call_args: &Vec>) -> SuggestionArgs<'a> { - let span_snippet_of_span_call = snippet(cx, span_call_args[0].span); - let help_snippet = snippet(cx, span_call_args[1].span); - let sugg_snippet = snippet(cx, span_call_args[2].span); - let applicability_snippet = snippet(cx, span_call_args[3].span); +fn span_suggestion_snippets<'a, 'hir>( + cx: &LateContext<'_, '_>, + span_call_args: &'hir [Expr<'hir>], +) -> SpanSuggestionSnippets<'a> { + let help_snippet = snippet(cx, span_call_args[2].span); + let sugg_snippet = snippet(cx, span_call_args[3].span); + let applicability_snippet = snippet(cx, span_call_args[4].span); - SuggestionArgs { - span: span_snippet_of_span_call, + SpanSuggestionSnippets { help: help_snippet, sugg: sugg_snippet, applicability: applicability_snippet, } } -fn suggest_span_suggestion(cx: &EarlyContext<'_>, expr: &AstExpr, and_then_args: AndThenArgs<'_>, suggestion_args: SuggestionArgs<'_>) { - if and_then_args.span == suggestion_args.span { - println!("suggestion true"); - span_lint_and_sugg ( - cx, - COLLAPSIBLE_SPAN_LINT_CALLS, - expr.span, - "this call is collapsible", - "collapse into", - format!( - "span_lint_and_sugg({}, {}, {}, {}, {}, {},{})", - and_then_args.cx, - and_then_args.lint, - and_then_args.span, - and_then_args.msg, - suggestion_args.help, - suggestion_args.sugg, - suggestion_args.applicability - ), - Applicability::MachineApplicable - ); - } -} - -struct HelpArgs<'a> { - span: Cow<'a, str>, - help: Cow<'a, str>, -} - -fn help_args<'a>(cx: &EarlyContext<'_>, span_call_args: &Vec>) -> HelpArgs<'a>{ - let span_snippet_of_span_call = snippet(cx, span_call_args[0].span); - let help_snippet = snippet(cx, span_call_args[1].span); - - HelpArgs { - span: span_snippet_of_span_call, - help: help_snippet, - } -} - -fn suggest_span_help(cx: &EarlyContext<'_>, expr: &AstExpr, and_then_args: AndThenArgs<'_>, help_args: HelpArgs<'_>) { - if and_then_args.span == help_args.span { - span_lint_and_sugg( - cx, - COLLAPSIBLE_SPAN_LINT_CALLS, - expr.span, - "this call is collapsible", - "collapse into", - format!( - "span_lint_and_help({}, {}, {}, {},{})", - and_then_args.cx, - and_then_args.lint, - and_then_args.span, - and_then_args.msg, - help_args.help - ), - Applicability::MachineApplicable - ); - } -} - -struct NoteArgs<'a> { - span: Cow<'a, str>, - note: Cow<'a, str>, -} - -fn note_args<'a>(cx: &EarlyContext<'_>, span_call_args: &Vec>) -> NoteArgs<'a> { - let span_snippet_of_span_call = snippet(cx, span_call_args[0].span); - let note_snippet = snippet(cx, span_call_args[1].span); - - NoteArgs { - span: span_snippet_of_span_call, - note: note_snippet, - } -} - -fn suggest_span_note(cx: &EarlyContext<'_>, expr: &AstExpr, and_then_args: AndThenArgs<'_> , note_args: NoteArgs<'_> ) { - if and_then_args.span == note_args.span { - span_lint_and_sugg( - cx, - COLLAPSIBLE_SPAN_LINT_CALLS, - expr.span, - "this call is collspible", - "collapse into", - format!( - "span_lint_and_note({},{}, {}, {}, {})", - and_then_args.cx, - and_then_args.lint, - and_then_args.span, - and_then_args.msg, - note_args.note - ), - Applicability::MachineApplicable - ); - } -} - -fn snippet<'a>(cx: &EarlyContext<'_>, span: Span) -> Cow<'a, str> { - other_snippet(cx, span, "Should not be") +fn suggest_suggestion( + cx: &LateContext<'_, '_>, + expr: &Expr<'_>, + and_then_snippets: AndThenSnippets<'_>, + span_suggestion_snippets: SpanSuggestionSnippets<'_>, +) { + span_lint_and_sugg( + cx, + COLLAPSIBLE_SPAN_LINT_CALLS, + expr.span, + "this call is collapsible", + "collapse into", + format!( + "span_lint_and_sugg({}, {}, {}, {}, {}, {}, {})", + and_then_snippets.cx, + and_then_snippets.lint, + and_then_snippets.span, + and_then_snippets.msg, + span_suggestion_snippets.help, + span_suggestion_snippets.sugg, + span_suggestion_snippets.applicability + ), + Applicability::MachineApplicable, + ); +} + +fn suggest_help(cx: &LateContext<'_, '_>, expr: &Expr<'_>, and_then_snippets: AndThenSnippets<'_>, help: Cow<'_, str>) { + span_lint_and_sugg( + cx, + COLLAPSIBLE_SPAN_LINT_CALLS, + expr.span, + "this call is collapsible", + "collapse into", + format!( + "span_lint_and_help({}, {}, {}, {}, {})", + and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg, help + ), + Applicability::MachineApplicable, + ); +} + +fn suggest_note(cx: &LateContext<'_, '_>, expr: &Expr<'_>, and_then_snippets: AndThenSnippets<'_>, note: Cow<'_, str>) { + span_lint_and_sugg( + cx, + COLLAPSIBLE_SPAN_LINT_CALLS, + expr.span, + "this call is collspible", + "collapse into", + format!( + "span_lint_and_note({}, {}, {}, {}, {}, {})", + and_then_snippets.cx, + and_then_snippets.lint, + and_then_snippets.span, + and_then_snippets.msg, + and_then_snippets.span, + note + ), + Applicability::MachineApplicable, + ); +} + +fn snippet<'a>(cx: &LateContext<'_, '_>, span: Span) -> Cow<'a, str> { + other_snippet(cx, span, "Should not be this snippet") } diff --git a/tests/ui/collapsible_span_lint_calls.fixed b/tests/ui/collapsible_span_lint_calls.fixed index e84fae032fa2..4d896459ddcb 100644 --- a/tests/ui/collapsible_span_lint_calls.fixed +++ b/tests/ui/collapsible_span_lint_calls.fixed @@ -2,16 +2,16 @@ #![deny(clippy::internal)] #![feature(rustc_private)] -extern crate rustc_session; +extern crate rustc_ast; extern crate rustc_errors; extern crate rustc_lint; -extern crate syntax; +extern crate rustc_session; extern crate rustc_span; -use rustc_session::{declare_tool_lint, declare_lint_pass}; -use rustc_errors::{DiagnosticBuilder, Applicability}; -use rustc_lint::{EarlyContext, EarlyLintPass, LintContext, Lint}; -use syntax::ast::Expr; +use rustc_ast::ast::Expr; +use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; #[allow(unused_variables)] @@ -21,7 +21,33 @@ where { } -declare_tool_lint!{ +#[allow(unused_variables)] +fn span_lint_and_help<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) {} + +#[allow(unused_variables)] +fn span_lint_and_note<'a, T: LintContext>( + cx: &'a T, + lint: &'static Lint, + span: Span, + msg: &str, + note_span: Span, + note: &str, +) { +} + +#[allow(unused_variables)] +fn span_lint_and_sugg<'a, T: LintContext>( + cx: &'a T, + lint: &'static Lint, + sp: Span, + msg: &str, + help: &str, + sugg: String, + applicability: Applicability, +) { +} + +declare_tool_lint! { pub clippy::TEST_LINT, Warn, "", @@ -31,21 +57,17 @@ declare_tool_lint!{ declare_lint_pass!(Pass => [TEST_LINT]); impl EarlyLintPass for Pass { - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { let lint_msg = "lint message"; let help_msg = "help message"; let note_msg = "note message"; let sugg = "new_call()"; - span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { - db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable); - }); - span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { - db.span_help(expr.span, help_msg); - }); - span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| - db.span_note(expr.span, note_msg) - ); + 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, help_msg); + span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, 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); } } diff --git a/tests/ui/collapsible_span_lint_calls.rs b/tests/ui/collapsible_span_lint_calls.rs index 432eb0b55a22..3c365f1cb9f3 100644 --- a/tests/ui/collapsible_span_lint_calls.rs +++ b/tests/ui/collapsible_span_lint_calls.rs @@ -2,16 +2,16 @@ #![deny(clippy::internal)] #![feature(rustc_private)] -extern crate rustc_session; +extern crate rustc_ast; extern crate rustc_errors; extern crate rustc_lint; -extern crate rustc_ast; +extern crate rustc_session; extern crate rustc_span; -use rustc_session::{declare_tool_lint, declare_lint_pass}; -use rustc_errors::{DiagnosticBuilder, Applicability}; -use rustc_lint::{EarlyContext, EarlyLintPass, LintContext, Lint}; use rustc_ast::ast::Expr; +use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; #[allow(unused_variables)] @@ -21,7 +21,33 @@ where { } -declare_tool_lint!{ +#[allow(unused_variables)] +fn span_lint_and_help<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) {} + +#[allow(unused_variables)] +fn span_lint_and_note<'a, T: LintContext>( + cx: &'a T, + lint: &'static Lint, + span: Span, + msg: &str, + note_span: Span, + note: &str, +) { +} + +#[allow(unused_variables)] +fn span_lint_and_sugg<'a, T: LintContext>( + cx: &'a T, + lint: &'static Lint, + sp: Span, + msg: &str, + help: &str, + sugg: String, + applicability: Applicability, +) { +} + +declare_tool_lint! { pub clippy::TEST_LINT, Warn, "", @@ -31,7 +57,7 @@ declare_tool_lint!{ declare_lint_pass!(Pass => [TEST_LINT]); impl EarlyLintPass for Pass { - fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) { let lint_msg = "lint message"; let help_msg = "help message"; let note_msg = "note message"; @@ -43,15 +69,15 @@ impl EarlyLintPass for Pass { span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { db.span_help(expr.span, help_msg); }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + db.help(help_msg); + }); span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { db.span_note(expr.span, note_msg); }); span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { db.note(note_msg); }); - span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { - db.help(help_msg); - }) } } diff --git a/tests/ui/collapsible_span_lint_calls.stderr b/tests/ui/collapsible_span_lint_calls.stderr index 1bb38cdfccae..a86d4f7f6aeb 100644 --- a/tests/ui/collapsible_span_lint_calls.stderr +++ b/tests/ui/collapsible_span_lint_calls.stderr @@ -1,17 +1,49 @@ -error[E0308]: mismatched types - --> $DIR/collapsible_span_lint_calls.rs:44:13 +error: this call is collapsible + --> $DIR/collapsible_span_lint_calls.rs:66:9 | -LL | db.span_help(expr.span, help_msg) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try adding a semicolon: `;` - | | - | expected `()`, found `&mut rustc_errors::DiagnosticBuilder<'_>` +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable)` + | +note: the lint level is defined here + --> $DIR/collapsible_span_lint_calls.rs:2:9 + | +LL | #![deny(clippy::internal)] + | ^^^^^^^^^^^^^^^^ + = note: `#[deny(clippy::collapsible_span_lint_calls)]` implied by `#[deny(clippy::internal)]` + +error: this call is collapsible + --> $DIR/collapsible_span_lint_calls.rs:69:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | db.span_help(expr.span, help_msg); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, help_msg)` + +error: this call is collapsible + --> $DIR/collapsible_span_lint_calls.rs:72:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | db.help(help_msg); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, help_msg)` + +error: this call is collspible + --> $DIR/collapsible_span_lint_calls.rs:75:9 + | +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)` -error[E0308]: mismatched types - --> $DIR/collapsible_span_lint_calls.rs:47:13 +error: this call is collspible + --> $DIR/collapsible_span_lint_calls.rs:78:9 | -LL | db.span_note(expr.span, note_msg) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&mut rustc_errors::DiagnosticBuilder<'_>` +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)` -error: aborting due to 2 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0308`.