From 7c58ffe874142e1943e2674d7e75989938a7d21b Mon Sep 17 00:00:00 2001 From: jumbatm Date: Fri, 31 Jan 2020 22:24:57 +1000 Subject: [PATCH 01/11] Invert control in struct_lint_level. Caller now passes in a `decorate` function, which is only run if the lint is allowed. --- src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/lint.rs | 41 +- src/librustc/middle/stability.rs | 19 +- src/librustc/mir/interpret/error.rs | 81 ++-- src/librustc/traits/object_safety.rs | 56 +-- src/librustc/traits/specialize/mod.rs | 114 ++--- src/librustc/ty/context.rs | 24 +- src/librustc_attr/builtin.rs | 4 +- src/librustc_errors/diagnostic.rs | 1 + src/librustc_errors/diagnostic_builder.rs | 3 +- src/librustc_expand/base.rs | 2 +- src/librustc_lint/array_into_iter.rs | 7 +- src/librustc_lint/builtin.rs | 392 ++++++++++-------- src/librustc_lint/context.rs | 198 ++++----- src/librustc_lint/internal.rs | 81 ++-- src/librustc_lint/levels.rs | 86 ++-- src/librustc_lint/non_ascii_idents.rs | 8 +- src/librustc_lint/nonstandard_style.rs | 43 +- src/librustc_lint/redundant_semicolon.rs | 28 +- src/librustc_lint/types.rs | 146 +++---- src/librustc_lint/unused.rs | 110 ++--- src/librustc_mir/borrow_check/mod.rs | 32 +- src/librustc_mir/const_eval/eval_queries.rs | 9 +- src/librustc_mir/interpret/intern.rs | 11 +- src/librustc_mir/transform/check_unsafety.rs | 40 +- src/librustc_mir/transform/const_prop.rs | 67 +-- src/librustc_mir_build/hair/pattern/_match.rs | 30 +- .../hair/pattern/check_match.rs | 49 ++- .../hair/pattern/const_to_pat.rs | 23 +- src/librustc_mir_build/lints.rs | 20 +- src/librustc_parse/config.rs | 7 +- .../lexer/unescape_error_reporting.rs | 2 +- src/librustc_parse/parser/attr.rs | 4 +- src/librustc_parse/parser/diagnostics.rs | 2 +- src/librustc_parse/parser/mod.rs | 2 +- src/librustc_parse/parser/pat.rs | 2 +- src/librustc_parse/validate_attr.rs | 4 +- src/librustc_passes/check_attr.rs | 40 +- src/librustc_passes/dead.rs | 9 +- src/librustc_passes/liveness.rs | 72 ++-- src/librustc_passes/stability.rs | 14 +- src/librustc_privacy/lib.rs | 29 +- src/librustc_resolve/lifetimes.rs | 59 +-- src/librustc_typeck/astconv.rs | 49 +-- src/librustc_typeck/check/cast.rs | 30 +- src/librustc_typeck/check/method/probe.rs | 47 ++- src/librustc_typeck/check/mod.rs | 18 +- src/librustc_typeck/check_unused.rs | 56 +-- src/librustc_typeck/collect.rs | 8 +- .../passes/collect_intra_doc_links.rs | 238 +++++------ src/librustdoc/passes/mod.rs | 10 +- 51 files changed, 1299 insertions(+), 1130 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 57a52a991edc8..01390f2c7195b 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1701,7 +1701,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { sub: Region<'tcx>, ) { self.construct_generic_bound_failure(region_scope_tree, span, origin, bound_kind, sub) - .emit() + .emit(); } pub fn construct_generic_bound_failure( diff --git a/src/librustc/lint.rs b/src/librustc/lint.rs index 8c18b1368a9d8..e7291d7a4ab0d 100644 --- a/src/librustc/lint.rs +++ b/src/librustc/lint.rs @@ -11,6 +11,7 @@ use rustc_span::hygiene::MacroKind; use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan}; use rustc_span::{Span, Symbol}; + /// How a lint level was set. #[derive(Clone, Copy, PartialEq, Eq, HashStable)] pub enum LintSource { @@ -174,20 +175,37 @@ impl<'a> HashStable> for LintLevelMap { } } -pub fn struct_lint_level<'a>( - sess: &'a Session, + +pub struct LintDiagnosticBuilder<'a>(DiagnosticBuilder<'a>); + +impl<'a> LintDiagnosticBuilder<'a> { + /// Return the inner DiagnosticBuilder, first setting the primary message to `msg`. + pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a> { + self.0.set_primary_message(msg); + self.0 + } + + /// Create a LintDiagnosticBuilder from some existing DiagnosticBuilder. + pub fn new(err: DiagnosticBuilder<'a>) -> LintDiagnosticBuilder<'a>{ + LintDiagnosticBuilder(err) + } +} + +pub fn struct_lint_level<'s>( + sess: &'s Session, lint: &'static Lint, level: Level, src: LintSource, span: Option, - msg: &str, -) -> DiagnosticBuilder<'a> { + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) { + + // FIXME: Move the guts of this function into a fn which takes dyn Fn to reduce code bloat. let mut err = match (level, span) { - (Level::Allow, _) => return sess.diagnostic().struct_dummy(), - (Level::Warn, Some(span)) => sess.struct_span_warn(span, msg), - (Level::Warn, None) => sess.struct_warn(msg), - (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, msg), - (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(msg), + (Level::Allow, _) => { return; }, + (Level::Warn, Some(span)) => sess.struct_span_warn(span, ""), + (Level::Warn, None) => sess.struct_warn(""), + (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, ""), + (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(""), }; // Check for future incompatibility lints and issue a stronger warning. @@ -209,7 +227,7 @@ pub fn struct_lint_level<'a>( err.cancel(); // Don't continue further, since we don't want to have // `diag_span_note_once` called for a diagnostic that isn't emitted. - return err; + return; } } @@ -299,7 +317,8 @@ pub fn struct_lint_level<'a>( err.note(&citation); } - return err; + // Finally, run `decorate`. This function is also responsible for emitting the diagnostic. + decorate(LintDiagnosticBuilder::new(err)); } /// Returns whether `span` originates in a foreign crate's external macro. diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 7cbe77b9e82f0..dd30fb23c2e76 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -222,11 +222,13 @@ fn late_report_deprecation( return; } - let mut diag = tcx.struct_span_lint_hir(lint, hir_id, span, message); - if let hir::Node::Expr(_) = tcx.hir().get(hir_id) { - deprecation_suggestion(&mut diag, suggestion, span); - } - diag.emit(); + tcx.struct_span_lint_hir(lint, hir_id, span, |lint| { + let mut diag = lint.build(message); + if let hir::Node::Expr(_) = tcx.hir().get(hir_id) { + deprecation_suggestion(&mut diag, suggestion, span); + } + diag.emit() + }); if hir_id == hir::DUMMY_HIR_ID { span_bug!(span, "emitted a {} lint with dummy HIR id: {:?}", lint.name, def_id); } @@ -387,8 +389,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Additionally, this function will also check if the item is deprecated. If so, and `id` is /// not `None`, a deprecated lint attached to `id` will be emitted. pub fn check_stability(self, def_id: DefId, id: Option, span: Span) { - let soft_handler = - |lint, span, msg: &_| self.lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg); + let soft_handler = |lint, span, msg: &_| { + self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| { + lint.build(msg).emit() + }) + }; match self.eval_stability(def_id, id, span) { EvalResult::Allow => {} EvalResult::Deny { feature, reason, issue, is_soft } => { diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 349dbd74ad1c9..bb84458cf7b0b 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -83,18 +83,15 @@ impl<'tcx> ConstEvalErr<'tcx> { &self, tcx: TyCtxtAt<'tcx>, message: &str, - ) -> Result, ErrorHandled> { - self.struct_generic(tcx, message, None) + emit: impl FnOnce(DiagnosticBuilder<'_>), + ) -> Result<(), ErrorHandled> { + self.struct_generic(tcx, message, emit, None) } pub fn report_as_error(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled { - let err = self.struct_error(tcx, message); - match err { - Ok(mut err) => { - err.emit(); - ErrorHandled::Reported - } - Err(err) => err, + match self.struct_error(tcx, message, |mut e| e.emit()) { + Ok(_) => ErrorHandled::Reported, + Err(x) => x, } } @@ -105,9 +102,11 @@ impl<'tcx> ConstEvalErr<'tcx> { lint_root: hir::HirId, span: Option, ) -> ErrorHandled { - let lint = self.struct_generic(tcx, message, Some(lint_root)); - match lint { - Ok(mut lint) => { + match self.struct_generic( + tcx, + message, + |mut lint: DiagnosticBuilder<'_>| { + // Apply the span. if let Some(span) = span { let primary_spans = lint.span.primary_spans().to_vec(); // point at the actual error as the primary span @@ -121,18 +120,26 @@ impl<'tcx> ConstEvalErr<'tcx> { } } lint.emit(); + } + , Some(lint_root)) { + Ok(_) => { ErrorHandled::Reported } Err(err) => err, } } + /// Sets the message passed in via `message`, then adds the span labels for you, before applying + /// further modifications in `emit`. It's up to you to call emit(), stash(..), etc. within the + /// `emit` method. If you don't need to do any additional processing, just use + /// struct_generic. fn struct_generic( &self, tcx: TyCtxtAt<'tcx>, message: &str, + emit: impl FnOnce(DiagnosticBuilder<'_>), lint_root: Option, - ) -> Result, ErrorHandled> { + ) -> Result<(), ErrorHandled> { let must_error = match self.error { InterpError::MachineStop(_) => bug!("CTFE does not stop"), err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => { @@ -143,7 +150,22 @@ impl<'tcx> ConstEvalErr<'tcx> { _ => false, }; trace!("reporting const eval failure at {:?}", self.span); - let mut err = if let (Some(lint_root), false) = (lint_root, must_error) { + + let add_span_labels = |err: &mut DiagnosticBuilder<'_>| { + if !must_error { + err.span_label(self.span, self.error.to_string()); + } + // Skip the last, which is just the environment of the constant. The stacktrace + // is sometimes empty because we create "fake" eval contexts in CTFE to do work + // on constant values. + if self.stacktrace.len() > 0 { + for frame_info in &self.stacktrace[..self.stacktrace.len() - 1] { + err.span_label(frame_info.call_site, frame_info.to_string()); + } + } + }; + + if let (Some(lint_root), false) = (lint_root, must_error) { let hir_id = self .stacktrace .iter() @@ -155,25 +177,22 @@ impl<'tcx> ConstEvalErr<'tcx> { rustc_session::lint::builtin::CONST_ERR, hir_id, tcx.span, - message, - ) - } else if must_error { - struct_error(tcx, &self.error.to_string()) + |lint| { + let mut err = lint.build(message); + add_span_labels(&mut err); + emit(err); + }, + ); } else { - struct_error(tcx, message) + let mut err = if must_error { + struct_error(tcx, &self.error.to_string()) + } else { + struct_error(tcx, message) + }; + add_span_labels(&mut err); + emit(err); }; - if !must_error { - err.span_label(self.span, self.error.to_string()); - } - // Skip the last, which is just the environment of the constant. The stacktrace - // is sometimes empty because we create "fake" eval contexts in CTFE to do work - // on constant values. - if self.stacktrace.len() > 0 { - for frame_info in &self.stacktrace[..self.stacktrace.len() - 1] { - err.span_label(frame_info.call_site, frame_info.to_string()); - } - } - Ok(err) + Ok(()) } } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 3c886ce7f3eb7..0e6347897d2ba 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -227,37 +227,39 @@ fn object_safety_violations_for_trait( { // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id. // It's also hard to get a use site span, so we use the method definition span. - let mut err = tcx.struct_span_lint_hir( + tcx.struct_span_lint_hir( WHERE_CLAUSES_OBJECT_SAFETY, hir::CRATE_HIR_ID, *span, - &format!( - "the trait `{}` cannot be made into an object", - tcx.def_path_str(trait_def_id) - ), + |lint| { + let mut err = lint.build(&format!( + "the trait `{}` cannot be made into an object", + tcx.def_path_str(trait_def_id) + )); + let node = tcx.hir().get_if_local(trait_def_id); + let msg = if let Some(hir::Node::Item(item)) = node { + err.span_label(item.ident.span, "this trait cannot be made into an object..."); + format!("...because {}", violation.error_msg()) + } else { + format!( + "the trait cannot be made into an object because {}", + violation.error_msg() + ) + }; + err.span_label(*span, &msg); + match (node, violation.solution()) { + (Some(_), Some((note, None))) => { + err.help(¬e); + } + (Some(_), Some((note, Some((sugg, span))))) => { + err.span_suggestion(span, ¬e, sugg, Applicability::MachineApplicable); + } + // Only provide the help if its a local trait, otherwise it's not actionable. + _ => {} + } + err.emit(); + }, ); - let node = tcx.hir().get_if_local(trait_def_id); - let msg = if let Some(hir::Node::Item(item)) = node { - err.span_label(item.ident.span, "this trait cannot be made into an object..."); - format!("...because {}", violation.error_msg()) - } else { - format!( - "the trait cannot be made into an object because {}", - violation.error_msg() - ) - }; - err.span_label(*span, &msg); - match (node, violation.solution()) { - (Some(_), Some((note, None))) => { - err.help(¬e); - } - (Some(_), Some((note, Some((sugg, span))))) => { - err.span_suggestion(span, ¬e, sugg, Applicability::MachineApplicable); - } - // Only provide the help if its a local trait, otherwise it's not actionable. - _ => {} - } - err.emit(); false } else { true diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 071b5277dd95d..33a78ae896b35 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -22,6 +22,7 @@ use rustc_hir::def_id::DefId; use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK; use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS; use rustc_span::DUMMY_SP; +use rustc::lint::LintDiagnosticBuilder; use super::util::impl_trait_ref_and_oblig; use super::{FulfillmentContext, SelectionContext}; @@ -317,22 +318,69 @@ pub(super) fn specialization_graph_provider( }; if let Some(overlap) = overlap { - let msg = format!( - "conflicting implementations of trait `{}`{}:{}", - overlap.trait_desc, - overlap - .self_desc - .clone() - .map_or(String::new(), |ty| { format!(" for type `{}`", ty) }), - match used_to_be_allowed { - Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)", - _ => "", - } - ); let impl_span = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap()); - let mut err = match used_to_be_allowed { - None => struct_span_err!(tcx.sess, impl_span, E0119, "{}", msg), + + // Work to be done after we've built the DiagnosticBuilder. We have to define it + // now because the struct_lint methods don't return back the DiagnosticBuilder + // that's passed in. + let decorate = |err: LintDiagnosticBuilder<'_>| { + let msg = format!( + "conflicting implementations of trait `{}`{}:{}", + overlap.trait_desc, + overlap + .self_desc + .clone() + .map_or(String::new(), |ty| { format!(" for type `{}`", ty) }), + match used_to_be_allowed { + Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)", + _ => "", + } + ); + let mut err = err.build(&msg); + match tcx.span_of_impl(overlap.with_impl) { + Ok(span) => { + err.span_label( + tcx.sess.source_map().def_span(span), + "first implementation here".to_string(), + ); + + err.span_label( + impl_span, + format!( + "conflicting implementation{}", + overlap + .self_desc + .map_or(String::new(), |ty| format!(" for `{}`", ty)) + ), + ); + } + Err(cname) => { + let msg = match to_pretty_impl_header(tcx, overlap.with_impl) { + Some(s) => { + format!("conflicting implementation in crate `{}`:\n- {}", cname, s) + } + None => format!("conflicting implementation in crate `{}`", cname), + }; + err.note(&msg); + } + } + + for cause in &overlap.intercrate_ambiguity_causes { + cause.add_intercrate_ambiguity_hint(&mut err); + } + + if overlap.involves_placeholder { + coherence::add_placeholder_note(&mut err); + } + err.emit() + }; + + match used_to_be_allowed { + None => { + let err = struct_span_err!(tcx.sess, impl_span, E0119, ""); + decorate(LintDiagnosticBuilder::new(err)); + } Some(kind) => { let lint = match kind { FutureCompatOverlapErrorKind::Issue33140 => { @@ -344,47 +392,11 @@ pub(super) fn specialization_graph_provider( lint, tcx.hir().as_local_hir_id(impl_def_id).unwrap(), impl_span, - &msg, + decorate, ) } }; - match tcx.span_of_impl(overlap.with_impl) { - Ok(span) => { - err.span_label( - tcx.sess.source_map().def_span(span), - "first implementation here".to_string(), - ); - err.span_label( - impl_span, - format!( - "conflicting implementation{}", - overlap - .self_desc - .map_or(String::new(), |ty| format!(" for `{}`", ty)) - ), - ); - } - Err(cname) => { - let msg = match to_pretty_impl_header(tcx, overlap.with_impl) { - Some(s) => { - format!("conflicting implementation in crate `{}`:\n- {}", cname, s) - } - None => format!("conflicting implementation in crate `{}`", cname), - }; - err.note(&msg); - } - } - - for cause in &overlap.intercrate_ambiguity_causes { - cause.add_intercrate_ambiguity_hint(&mut err); - } - - if overlap.involves_placeholder { - coherence::add_placeholder_note(&mut err); - } - - err.emit(); } } else { let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 92c5600362e01..a885f9e960093 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -42,6 +42,7 @@ use crate::ty::{InferConst, ParamConst}; use crate::ty::{List, TyKind, TyS}; use crate::util::common::ErrorReported; use rustc_attr as attr; +use rustc::lint::LintDiagnosticBuilder; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; @@ -49,7 +50,6 @@ use rustc_data_structures::stable_hasher::{ hash_stable_hashmap, HashStable, StableHasher, StableVec, }; use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; -use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex, LOCAL_CRATE}; @@ -2551,16 +2551,6 @@ impl<'tcx> TyCtxt<'tcx> { iter.intern_with(|xs| self.intern_goals(xs)) } - pub fn lint_hir( - self, - lint: &'static Lint, - hir_id: HirId, - span: impl Into, - msg: &str, - ) { - self.struct_span_lint_hir(lint, hir_id, span.into(), msg).emit() - } - /// Walks upwards from `id` to find a node which might change lint levels with attributes. /// It stops at `bound` and just returns it if reached. pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId { @@ -2604,20 +2594,20 @@ impl<'tcx> TyCtxt<'tcx> { lint: &'static Lint, hir_id: HirId, span: impl Into, - msg: &str, - ) -> DiagnosticBuilder<'tcx> { + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>) + ) { let (level, src) = self.lint_level_at_node(lint, hir_id); - struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg) + struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate); } pub fn struct_lint_node( self, lint: &'static Lint, id: HirId, - msg: &str, - ) -> DiagnosticBuilder<'tcx> { + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), + ) { let (level, src) = self.lint_level_at_node(lint, id); - struct_lint_level(self.sess, lint, level, src, None, msg) + struct_lint_level(self.sess, lint, level, src, None, decorate); } pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx StableVec> { diff --git a/src/librustc_attr/builtin.rs b/src/librustc_attr/builtin.rs index ab03297fffe84..e5381a58dab55 100644 --- a/src/librustc_attr/builtin.rs +++ b/src/librustc_attr/builtin.rs @@ -37,7 +37,7 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) { .span_label(span, format!("expected one of {}", expected.join(", "))) .emit(); } - AttrError::MissingSince => struct_span_err!(diag, span, E0542, "missing 'since'").emit(), + AttrError::MissingSince => { struct_span_err!(diag, span, E0542, "missing 'since'").emit(); }, AttrError::MissingFeature => { struct_span_err!(diag, span, E0546, "missing 'feature'").emit(); } @@ -639,7 +639,7 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &F let (cfg, feature, has_feature) = gated_cfg; if !has_feature(features) && !cfg_span.allows_unstable(*feature) { let explain = format!("`cfg({})` is experimental and subject to change", cfg); - feature_err(sess, *feature, cfg_span, &explain).emit() + feature_err(sess, *feature, cfg_span, &explain).emit(); } } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 5286e8c19b462..189b5bd0f9e87 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -194,6 +194,7 @@ impl Diagnostic { found_extra: &dyn fmt::Display, ) -> &mut Self { let expected_label = format!("expected {}", expected_label); + let found_label = format!("found {}", found_label); let (found_padding, expected_padding) = if expected_label.len() > found_label.len() { (expected_label.len() - found_label.len(), 0) diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 82bbae18a9c0b..84bfa07d267da 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -106,7 +106,7 @@ impl<'a> DiagnosticBuilder<'a> { /// /// See `emit` and `delay_as_bug` for details. pub fn emit_unless(&mut self, delay: bool) { - if delay { self.delay_as_bug() } else { self.emit() } + if delay { self.delay_as_bug(); } else { self.emit(); } } /// Stashes diagnostic for possible later improvement in a different, @@ -369,6 +369,7 @@ impl<'a> DiagnosticBuilder<'a> { /// Creates a new `DiagnosticBuilder` with an already constructed /// diagnostic. crate fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> { + debug!("Created new diagnostic"); DiagnosticBuilder(Box::new(DiagnosticBuilderInner { handler, diagnostic, diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index e167089b93a35..9e583d7e19d79 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -1113,7 +1113,7 @@ pub fn expr_to_string( err_msg: &str, ) -> Option<(Symbol, ast::StrStyle)> { expr_to_spanned_string(cx, expr, err_msg) - .map_err(|err| err.map(|mut err| err.emit())) + .map_err(|err| err.map(|mut err| { err.emit(); })) .ok() .map(|(symbol, style, _)| (symbol, style)) } diff --git a/src/librustc_lint/array_into_iter.rs b/src/librustc_lint/array_into_iter.rs index fb11b6771e9ca..a91d735622f4e 100644 --- a/src/librustc_lint/array_into_iter.rs +++ b/src/librustc_lint/array_into_iter.rs @@ -77,13 +77,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIntoIter { // to an array or to a slice. _ => bug!("array type coerced to something other than array or slice"), }; - let msg = format!( + cx.struct_span_lint(ARRAY_INTO_ITER, *span, |lint| { + lint.build(&format!( "this method call currently resolves to `<&{} as IntoIterator>::into_iter` (due \ to autoref coercions), but that might change in the future when \ `IntoIterator` impls for arrays are added.", target, - ); - cx.struct_span_lint(ARRAY_INTO_ITER, *span, &msg) + )) .span_suggestion( call.ident.span, "use `.iter()` instead of `.into_iter()` to avoid ambiguity", @@ -91,6 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIntoIter { Applicability::MachineApplicable, ) .emit(); + }) } } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ca66717ac5eba..e84ef713b42d3 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -77,14 +77,16 @@ impl EarlyLintPass for WhileTrue { if !lit.span.from_expansion() { let msg = "denote infinite loops with `loop { ... }`"; let condition_span = cx.sess.source_map().def_span(e.span); - cx.struct_span_lint(WHILE_TRUE, condition_span, msg) - .span_suggestion_short( + cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| { + lint.build(msg) + .span_suggestion_short( condition_span, "use `loop`", "loop".to_owned(), Applicability::MachineApplicable, ) .emit(); + }) } } } @@ -174,29 +176,31 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns { if cx.tcx.find_field_index(ident, &variant) == Some(cx.tcx.field_index(fieldpat.hir_id, cx.tables)) { - let mut err = cx.struct_span_lint( + cx.struct_span_lint( NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, - &format!("the `{}:` in this pattern is redundant", ident), - ); - let binding = match binding_annot { - hir::BindingAnnotation::Unannotated => None, - hir::BindingAnnotation::Mutable => Some("mut"), - hir::BindingAnnotation::Ref => Some("ref"), - hir::BindingAnnotation::RefMut => Some("ref mut"), - }; - let ident = if let Some(binding) = binding { - format!("{} {}", binding, ident) - } else { - ident.to_string() - }; - err.span_suggestion( - fieldpat.span, - "use shorthand field pattern", - ident, - Applicability::MachineApplicable, + |lint| { + let mut err = lint.build(&format!("the `{}:` in this pattern is redundant", ident)); + let binding = match binding_annot { + hir::BindingAnnotation::Unannotated => None, + hir::BindingAnnotation::Mutable => Some("mut"), + hir::BindingAnnotation::Ref => Some("ref"), + hir::BindingAnnotation::RefMut => Some("ref mut"), + }; + let ident = if let Some(binding) = binding { + format!("{} {}", binding, ident) + } else { + ident.to_string() + }; + err.span_suggestion( + fieldpat.span, + "use shorthand field pattern", + ident, + Applicability::MachineApplicable, + ); + err.emit(); + } ); - err.emit(); } } } @@ -643,17 +647,19 @@ impl EarlyLintPass for AnonymousParameters { cx.struct_span_lint( ANONYMOUS_PARAMETERS, arg.pat.span, - "anonymous parameters are deprecated and will be \ - removed in the next edition.", - ) - .span_suggestion( - arg.pat.span, - "try naming the parameter or explicitly \ - ignoring it", - format!("_: {}", ty_snip), - appl, + |lint| { + lint.build("anonymous parameters are deprecated and will be \ + removed in the next edition.") + .span_suggestion( + arg.pat.span, + "try naming the parameter or explicitly \ + ignoring it", + format!("_: {}", ty_snip), + appl, + ) + .emit(); + }, ) - .emit(); } } _ => (), @@ -687,14 +693,16 @@ fn lint_deprecated_attr( msg: &str, suggestion: Option<&str>, ) { - cx.struct_span_lint(DEPRECATED, attr.span, &msg) - .span_suggestion_short( - attr.span, - suggestion.unwrap_or("remove this attribute"), - String::new(), - Applicability::MachineApplicable, - ) - .emit(); + cx.struct_span_lint(DEPRECATED, attr.span, |lint| { + lint.build(msg) + .span_suggestion_short( + attr.span, + suggestion.unwrap_or("remove this attribute"), + String::new(), + Applicability::MachineApplicable, + ) + .emit(); + }) } impl EarlyLintPass for DeprecatedAttr { @@ -759,21 +767,20 @@ impl UnusedDocComment { let span = sugared_span.take().unwrap_or_else(|| attr.span); if attr.is_doc_comment() || attr.check_name(sym::doc) { - let mut err = cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, "unused doc comment"); - - err.span_label( - node_span, - format!("rustdoc does not generate documentation for {}", node_kind), - ); - - if is_macro_expansion { - err.help( - "to document an item produced by a macro, \ - the macro must produce the documentation as part of its expansion", + cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| { + let mut err = lint.build("unused doc comment"); + err.span_label( + node_span, + format!("rustdoc does not generate documentation for {}", node_kind), ); - } - - err.emit(); + if is_macro_expansion { + err.help( + "to document an item produced by a macro, \ + the macro must produce the documentation as part of its expansion", + ); + } + err.emit(); + }); } } } @@ -831,20 +838,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { match param.kind { GenericParamKind::Lifetime { .. } => {} GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - let mut err = cx.struct_span_lint( + cx.struct_span_lint( NO_MANGLE_GENERIC_ITEMS, it.span, - "functions generic over types or consts must be mangled", - ); - err.span_suggestion_short( - no_mangle_attr.span, - "remove this attribute", - String::new(), - // Use of `#[no_mangle]` suggests FFI intent; correct - // fix may be to monomorphize source by hand - Applicability::MaybeIncorrect, + |lint| { + lint.build("functions generic over types or consts must be mangled") + .span_suggestion_short( + no_mangle_attr.span, + "remove this attribute", + String::new(), + // Use of `#[no_mangle]` suggests FFI intent; correct + // fix may be to monomorphize source by hand + Applicability::MaybeIncorrect, + ) + .emit(); + }, ); - err.emit(); break; } } @@ -856,25 +865,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { // Const items do not refer to a particular location in memory, and therefore // don't have anything to attach a symbol to let msg = "const items should never be `#[no_mangle]`"; - let mut err = cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg); - - // account for "pub const" (#45562) - let start = cx - .tcx - .sess - .source_map() - .span_to_snippet(it.span) - .map(|snippet| snippet.find("const").unwrap_or(0)) - .unwrap_or(0) as u32; - // `const` is 5 chars - let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5)); - err.span_suggestion( - const_span, - "try a static value", - "pub static".to_owned(), - Applicability::MachineApplicable, - ); - err.emit(); + cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, |lint| { + let mut err = lint.build(msg); + + // account for "pub const" (#45562) + let start = cx + .tcx + .sess + .source_map() + .span_to_snippet(it.span) + .map(|snippet| snippet.find("const").unwrap_or(0)) + .unwrap_or(0) as u32; + // `const` is 5 chars + let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5)); + err.span_suggestion( + const_span, + "try a static value", + "pub static".to_owned(), + Applicability::MachineApplicable, + ); + err.emit(); + }); } } _ => {} @@ -984,28 +995,30 @@ impl UnreachablePub { applicability = Applicability::MaybeIncorrect; } let def_span = cx.tcx.sess.source_map().def_span(span); - let mut err = cx.struct_span_lint( + cx.struct_span_lint( UNREACHABLE_PUB, def_span, - &format!("unreachable `pub` {}", what), - ); - let replacement = if cx.tcx.features().crate_visibility_modifier { - "crate" - } else { - "pub(crate)" - } - .to_owned(); + |lint| { + let mut err = lint.build(&format!("unreachable `pub` {}", what)); + let replacement = if cx.tcx.features().crate_visibility_modifier { + "crate" + } else { + "pub(crate)" + } + .to_owned(); - err.span_suggestion( - vis.span, - "consider restricting its visibility", - replacement, - applicability, + err.span_suggestion( + vis.span, + "consider restricting its visibility", + replacement, + applicability, + ); + if exportable { + err.help("or consider exporting it for use by other crates"); + } + err.emit(); + } ); - if exportable { - err.help("or consider exporting it for use by other crates"); - } - err.emit(); } _ => {} } @@ -1120,22 +1133,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { .iter() .map(|pred| pred.span()) .collect(); - let mut err = cx.struct_span_lint( + cx.struct_span_lint( TYPE_ALIAS_BOUNDS, spans, - "where clauses are not enforced in type aliases", - ); - err.span_suggestion( - type_alias_generics.where_clause.span_for_predicates_or_empty_place(), - "the clause will not be checked when the type alias is used, and should be removed", - String::new(), - Applicability::MachineApplicable, + |lint| { + let mut err = lint.build("where clauses are not enforced in type aliases"); + err.span_suggestion( + type_alias_generics.where_clause.span_for_predicates_or_empty_place(), + "the clause will not be checked when the type alias is used, and should be removed", + String::new(), + Applicability::MachineApplicable, + ); + if !suggested_changing_assoc_types { + TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); + suggested_changing_assoc_types = true; + } + err.emit(); + }, ); - if !suggested_changing_assoc_types { - TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); - suggested_changing_assoc_types = true; - } - err.emit(); } // The parameters must not have bounds for param in type_alias_generics.params.iter() { @@ -1148,19 +1163,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { }) .collect(); if !spans.is_empty() { - let mut err = cx.struct_span_lint( + cx.struct_span_lint( TYPE_ALIAS_BOUNDS, spans, - "bounds on generic parameters are not enforced in type aliases", + |lint| { + let mut err = lint.build("bounds on generic parameters are not enforced in type aliases"); + let msg = "the bound will not be checked when the type alias is used, \ + and should be removed"; + err.multipart_suggestion(&msg, suggestion, Applicability::MachineApplicable); + if !suggested_changing_assoc_types { + TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); + suggested_changing_assoc_types = true; + } + err.emit(); + }, ); - let msg = "the bound will not be checked when the type alias is used, \ - and should be removed"; - err.multipart_suggestion(&msg, suggestion, Applicability::MachineApplicable); - if !suggested_changing_assoc_types { - TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); - suggested_changing_assoc_types = true; - } - err.emit(); } } } @@ -1322,23 +1339,27 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { Some(start) => format!("&({}..={})", expr_to_string(&start), end), None => format!("&(..={})", end), }; - let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg); - err.span_suggestion( - pat.span, - suggestion, - replace, - Applicability::MachineApplicable, - ); - err.emit(); + cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, |lint| { + lint.build(msg) + .span_suggestion( + pat.span, + suggestion, + replace, + Applicability::MachineApplicable, + ) + .emit(); + }); } else { - let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, msg); - err.span_suggestion_short( - join, - suggestion, - "..=".to_owned(), - Applicability::MachineApplicable, - ); - err.emit(); + cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, |lint| { + lint.build(msg) + .span_suggestion_short( + join, + suggestion, + "..=".to_owned(), + Applicability::MachineApplicable + ) + .emit(); + }); }; } } @@ -1384,7 +1405,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems { } if let Some(attr) = attr::find_by_name(&it.attrs, sym::rustc_test_marker) { - cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, "cannot test inner items").emit(); + cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| lint.build("cannot test inner items").emit()); } } @@ -1465,18 +1486,20 @@ impl KeywordIdents { return; } - let mut lint = cx.struct_span_lint( + cx.struct_span_lint( KEYWORD_IDENTS, ident.span, - &format!("`{}` is a keyword in the {} edition", ident, next_edition), - ); - lint.span_suggestion( - ident.span, - "you can use a raw identifier to stay compatible", - format!("r#{}", ident), - Applicability::MachineApplicable, + |lint| { + lint.build(&format!("`{}` is a keyword in the {} edition", ident, next_edition)) + .span_suggestion( + ident.span, + "you can use a raw identifier to stay compatible", + format!("r#{}", ident), + Applicability::MachineApplicable, + ) + .emit() + }, ); - lint.emit() } } @@ -1780,17 +1803,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements { } if !lint_spans.is_empty() { - let mut err = cx.struct_span_lint( + cx.struct_span_lint( EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), - "outlives requirements can be inferred", - ); - err.multipart_suggestion( - if bound_count == 1 { "remove this bound" } else { "remove these bounds" }, - lint_spans.into_iter().map(|span| (span, "".to_owned())).collect::>(), - Applicability::MachineApplicable, + |lint| { + lint.build("outlives requirements can be inferred") + .multipart_suggestion( + if bound_count == 1 { "remove this bound" } else { "remove these bounds" }, + lint_spans.into_iter().map(|span| (span, "".to_owned())).collect::>(), + Applicability::MachineApplicable, + ) + .emit(); + }, ); - err.emit(); } } } @@ -1820,12 +1845,11 @@ impl EarlyLintPass for IncompleteFeatures { cx.struct_span_lint( INCOMPLETE_FEATURES, span, - &format!( + |lint| lint.build(&format!( "the feature `{}` is incomplete and may cause the compiler to crash", name, - ), + )).emit(), ) - .emit(); }); } } @@ -2015,30 +2039,32 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { // We are extremely conservative with what we warn about. let conjured_ty = cx.tables.expr_ty(expr); if let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty, init) { - let mut err = cx.struct_span_lint( + cx.struct_span_lint( INVALID_VALUE, expr.span, - &format!( - "the type `{}` does not permit {}", - conjured_ty, - match init { - InitKind::Zeroed => "zero-initialization", - InitKind::Uninit => "being left uninitialized", - }, - ), - ); - err.span_label(expr.span, "this code causes undefined behavior when executed"); - err.span_label( - expr.span, - "help: use `MaybeUninit` instead, \ - and only call `assume_init` after initialization is done", + |lint| { + let mut err = lint.build(&format!( + "the type `{}` does not permit {}", + conjured_ty, + match init { + InitKind::Zeroed => "zero-initialization", + InitKind::Uninit => "being left uninitialized", + }, + )); + err.span_label(expr.span, "this code causes undefined behavior when executed"); + err.span_label( + expr.span, + "help: use `MaybeUninit` instead, \ + and only call `assume_init` after initialization is done", + ); + if let Some(span) = span { + err.span_note(span, &msg); + } else { + err.note(&msg); + } + err.emit(); + }, ); - if let Some(span) = span { - err.span_note(span, &msg); - } else { - err.note(&msg); - } - err.emit(); } } } diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs index 3b8cce5635d07..7b085f6c2b3d4 100644 --- a/src/librustc_lint/context.rs +++ b/src/librustc_lint/context.rs @@ -26,7 +26,8 @@ use rustc::ty::layout::{LayoutError, LayoutOf, TyLayout}; use rustc::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync; -use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; +use rustc_errors::{struct_span_err, Applicability}; +use rustc::lint::LintDiagnosticBuilder; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_session::lint::BuiltinLintDiagnostics; @@ -474,7 +475,7 @@ pub trait LintContext: Sized { fn lints(&self) -> &LintStore; fn lookup_and_emit>(&self, lint: &'static Lint, span: Option, msg: &str) { - self.lookup(lint, span, msg).emit(); + self.lookup(lint, span, |lint| lint.build(msg).emit()); } fn lookup_and_emit_with_diagnostics>( @@ -484,95 +485,96 @@ pub trait LintContext: Sized { msg: &str, diagnostic: BuiltinLintDiagnostics, ) { - let mut db = self.lookup(lint, span, msg); - - let sess = self.sess(); - match diagnostic { - BuiltinLintDiagnostics::Normal => (), - BuiltinLintDiagnostics::BareTraitObject(span, is_global) => { - let (sugg, app) = match sess.source_map().span_to_snippet(span) { - Ok(s) if is_global => { - (format!("dyn ({})", s), Applicability::MachineApplicable) - } - Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable), - Err(_) => ("dyn ".to_string(), Applicability::HasPlaceholders), - }; - db.span_suggestion(span, "use `dyn`", sugg, app); - } - BuiltinLintDiagnostics::AbsPathWithModule(span) => { - let (sugg, app) = match sess.source_map().span_to_snippet(span) { - Ok(ref s) => { - // FIXME(Manishearth) ideally the emitting code - // can tell us whether or not this is global - let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" }; - - (format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable) - } - Err(_) => ("crate::".to_string(), Applicability::HasPlaceholders), - }; - db.span_suggestion(span, "use `crate`", sugg, app); - } - BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => { - db.span_label( - span, - "names from parent modules are not accessible without an explicit import", - ); - } - BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => { - db.span_note(span_def, "the macro is defined here"); - } - BuiltinLintDiagnostics::ElidedLifetimesInPaths( - n, - path_span, - incl_angl_brckt, - insertion_span, - anon_lts, - ) => { - add_elided_lifetime_in_path_suggestion( - sess, - &mut db, + self.lookup(lint, span, |lint| { + let mut db = lint.build(msg); + let sess = self.sess(); + match diagnostic { + BuiltinLintDiagnostics::Normal => (), + BuiltinLintDiagnostics::BareTraitObject(span, is_global) => { + let (sugg, app) = match sess.source_map().span_to_snippet(span) { + Ok(s) if is_global => { + (format!("dyn ({})", s), Applicability::MachineApplicable) + } + Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable), + Err(_) => ("dyn ".to_string(), Applicability::HasPlaceholders), + }; + db.span_suggestion(span, "use `dyn`", sugg, app); + } + BuiltinLintDiagnostics::AbsPathWithModule(span) => { + let (sugg, app) = match sess.source_map().span_to_snippet(span) { + Ok(ref s) => { + // FIXME(Manishearth) ideally the emitting code + // can tell us whether or not this is global + let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" }; + + (format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable) + } + Err(_) => ("crate::".to_string(), Applicability::HasPlaceholders), + }; + db.span_suggestion(span, "use `crate`", sugg, app); + } + BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => { + db.span_label( + span, + "names from parent modules are not accessible without an explicit import", + ); + } + BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => { + db.span_note(span_def, "the macro is defined here"); + } + BuiltinLintDiagnostics::ElidedLifetimesInPaths( n, path_span, incl_angl_brckt, insertion_span, anon_lts, - ); - } - BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => { - db.span_suggestion(span, ¬e, sugg, Applicability::MaybeIncorrect); - } - BuiltinLintDiagnostics::UnusedImports(message, replaces) => { - if !replaces.is_empty() { - db.tool_only_multipart_suggestion( - &message, - replaces, - Applicability::MachineApplicable, + ) => { + add_elided_lifetime_in_path_suggestion( + sess, + &mut db, + n, + path_span, + incl_angl_brckt, + insertion_span, + anon_lts, ); } - } - BuiltinLintDiagnostics::RedundantImport(spans, ident) => { - for (span, is_imported) in spans { - let introduced = if is_imported { "imported" } else { "defined" }; - db.span_label( - span, - format!("the item `{}` is already {} here", ident, introduced), - ); + BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => { + db.span_suggestion(span, ¬e, sugg, Applicability::MaybeIncorrect); + } + BuiltinLintDiagnostics::UnusedImports(message, replaces) => { + if !replaces.is_empty() { + db.tool_only_multipart_suggestion( + &message, + replaces, + Applicability::MachineApplicable, + ); + } + } + BuiltinLintDiagnostics::RedundantImport(spans, ident) => { + for (span, is_imported) in spans { + let introduced = if is_imported { "imported" } else { "defined" }; + db.span_label( + span, + format!("the item `{}` is already {} here", ident, introduced), + ); + } + } + BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => { + stability::deprecation_suggestion(&mut db, suggestion, span) } } - BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => { - stability::deprecation_suggestion(&mut db, suggestion, span) - } - } - db.emit(); + db.emit(); + }); } fn lookup>( &self, lint: &'static Lint, span: Option, - msg: &str, - ) -> DiagnosticBuilder<'_>; + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), + ); /// Emit a lint at the appropriate level, for a particular span. fn span_lint>(&self, lint: &'static Lint, span: S, msg: &str) { @@ -583,9 +585,9 @@ pub trait LintContext: Sized { &self, lint: &'static Lint, span: S, - msg: &str, - ) -> DiagnosticBuilder<'_> { - self.lookup(lint, Some(span), msg) + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>) + ) { + self.lookup(lint, Some(span), decorate); } /// Emit a lint and note at the appropriate level, for a particular span. @@ -597,21 +599,25 @@ pub trait LintContext: Sized { note_span: Span, note: &str, ) { - let mut err = self.lookup(lint, Some(span), msg); - if note_span == span { - err.note(note); - } else { - err.span_note(note_span, note); - } - err.emit(); + self.lookup(lint, Some(span), |lint| { + let mut err = lint.build(msg); + if note_span == span { + err.note(note); + } else { + err.span_note(note_span, note); + } + err.emit(); + }); } /// Emit a lint and help at the appropriate level, for a particular span. fn span_lint_help(&self, lint: &'static Lint, span: Span, msg: &str, help: &str) { - let mut err = self.lookup(lint, Some(span), msg); - self.span_lint(lint, span, msg); - err.span_help(span, help); - err.emit(); + self.lookup(lint, Some(span), |err| { + let mut err = err.build(msg); + self.span_lint(lint, span, msg); + err.span_help(span, help); + err.emit(); + }); } /// Emit a lint at the appropriate level, with no associated span. @@ -654,13 +660,13 @@ impl LintContext for LateContext<'_, '_> { &self, lint: &'static Lint, span: Option, - msg: &str, - ) -> DiagnosticBuilder<'_> { + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), + ) { let hir_id = self.last_node_with_lint_attrs; match span { - Some(s) => self.tcx.struct_span_lint_hir(lint, hir_id, s, msg), - None => self.tcx.struct_lint_node(lint, hir_id, msg), + Some(s) => self.tcx.struct_span_lint_hir(lint, hir_id, s, decorate), + None => self.tcx.struct_lint_node(lint, hir_id, decorate), } } } @@ -681,9 +687,9 @@ impl LintContext for EarlyContext<'_> { &self, lint: &'static Lint, span: Option, - msg: &str, - ) -> DiagnosticBuilder<'_> { - self.builder.struct_lint(lint, span.map(|s| s.into()), msg) + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), + ) { + self.builder.struct_lint(lint, span.map(|s| s.into()), decorate) } } diff --git a/src/librustc_lint/internal.rs b/src/librustc_lint/internal.rs index 8480c85075dd4..19778a044a498 100644 --- a/src/librustc_lint/internal.rs +++ b/src/librustc_lint/internal.rs @@ -37,16 +37,19 @@ impl_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]); impl EarlyLintPass for DefaultHashTypes { fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { if let Some(replace) = self.map.get(&ident.name) { + // FIXME: We can avoid a copy here. Would require us to take String instead of &str. let msg = format!("Prefer {} over {}, it has better performance", replace, ident); - let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg); - db.span_suggestion( - ident.span, - "use", - replace.to_string(), - Applicability::MaybeIncorrect, // FxHashMap, ... needs another import - ); - db.note(&format!("a `use rustc_data_structures::fx::{}` may be necessary", replace)) - .emit(); + cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, |lint| { + lint.build(&msg) + .span_suggestion( + ident.span, + "use", + replace.to_string(), + Applicability::MaybeIncorrect, // FxHashMap, ... needs another import + ) + .note(&format!("a `use rustc_data_structures::fx::{}` may be necessary", replace)) + .emit(); + }); } } } @@ -85,7 +88,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { if let Some(last) = segments.last() { let span = path.span.with_hi(last.ident.span.hi()); if lint_ty_kind_usage(cx, last) { - cx.struct_span_lint(USAGE_OF_TY_TYKIND, span, "usage of `ty::TyKind::`") + cx.struct_span_lint(USAGE_OF_TY_TYKIND, span, |lint| { + lint.build("usage of `ty::TyKind::`") .span_suggestion( span, "try using ty:: directly", @@ -93,6 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { Applicability::MaybeIncorrect, // ty maybe needs an import ) .emit(); + }) } } } @@ -106,10 +111,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { cx.struct_span_lint( USAGE_OF_TY_TYKIND, path.span, - "usage of `ty::TyKind`", + |lint| { + lint.build("usage of `ty::TyKind`") + .help("try using `Ty` instead") + .emit(); + }, ) - .help("try using `Ty` instead") - .emit(); } else { if ty.span.from_expansion() { return; @@ -119,16 +126,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { cx.struct_span_lint( USAGE_OF_QUALIFIED_TY, path.span, - &format!("usage of qualified `ty::{}`", t), + |lint| { + lint.build(&format!("usage of qualified `ty::{}`", t)) + .span_suggestion( + path.span, + "try using it unqualified", + t, + // The import probably needs to be changed + Applicability::MaybeIncorrect, + ) + .emit(); + }, ) - .span_suggestion( - path.span, - "try using it unqualified", - t, - // The import probably needs to be changed - Applicability::MaybeIncorrect, - ) - .emit(); } } } @@ -145,16 +154,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { cx.struct_span_lint( TY_PASS_BY_REFERENCE, ty.span, - &format!("passing `{}` by reference", t), - ) - .span_suggestion( - ty.span, - "try passing by value", - t, - // Changing type of function argument - Applicability::MaybeIncorrect, + |lint| { + lint.build(&format!("passing `{}` by reference", t)) + .span_suggestion( + ty.span, + "try passing by value", + t, + // Changing type of function argument + Applicability::MaybeIncorrect, + ) + .emit(); + }, ) - .emit(); } } _ => {} @@ -234,10 +245,12 @@ impl EarlyLintPass for LintPassImpl { cx.struct_span_lint( LINT_PASS_IMPL_WITHOUT_MACRO, lint_pass.path.span, - "implementing `LintPass` by hand", + |lint| { + lint.build("implementing `LintPass` by hand") + .help("try using `declare_lint_pass!` or `impl_lint_pass!` instead") + .emit(); + }, ) - .help("try using `declare_lint_pass!` or `impl_lint_pass!` instead") - .emit(); } } } diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs index 4f30d2b222684..6dd899d146182 100644 --- a/src/librustc_lint/levels.rs +++ b/src/librustc_lint/levels.rs @@ -6,7 +6,8 @@ use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; +use rustc_errors::{struct_span_err, Applicability}; +use rustc::lint::LintDiagnosticBuilder; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::{intravisit, HirId}; @@ -39,8 +40,8 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap { tcx.arena.alloc(builder.levels.build_map()) } -pub struct LintLevelsBuilder<'a> { - sess: &'a Session, +pub struct LintLevelsBuilder<'s> { + sess: &'s Session, sets: LintLevelSets, id_to_set: FxHashMap, cur: u32, @@ -52,8 +53,8 @@ pub struct BuilderPush { pub changed: bool, } -impl<'a> LintLevelsBuilder<'a> { - pub fn new(sess: &'a Session, warn_about_weird_lints: bool, store: &LintStore) -> Self { +impl<'s> LintLevelsBuilder<'s> { + pub fn new(sess: &'s Session, warn_about_weird_lints: bool, store: &LintStore) -> Self { let mut builder = LintLevelsBuilder { sess, sets: LintLevelSets::new(), @@ -245,15 +246,17 @@ impl<'a> LintLevelsBuilder<'a> { lvl, src, Some(li.span().into()), - &msg, - ) - .span_suggestion( - li.span(), - "change it to", - new_lint_name.to_string(), - Applicability::MachineApplicable, - ) - .emit(); + |lint| { + lint.build(&msg) + .span_suggestion( + li.span(), + "change it to", + new_lint_name.to_string(), + Applicability::MachineApplicable, + ) + .emit(); + }, + ); let src = LintSource::Node( Symbol::intern(&new_lint_name), @@ -279,48 +282,51 @@ impl<'a> LintLevelsBuilder<'a> { let lint = builtin::RENAMED_AND_REMOVED_LINTS; let (level, src) = self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess); - let mut err = struct_lint_level( + struct_lint_level( self.sess, lint, level, src, Some(li.span().into()), - &msg, + |lint| { + let mut err = lint.build(&msg); + if let Some(new_name) = renamed { + err.span_suggestion( + li.span(), + "use the new name", + new_name, + Applicability::MachineApplicable, + ); + } + err.emit(); + }, ); - if let Some(new_name) = renamed { - err.span_suggestion( - li.span(), - "use the new name", - new_name, - Applicability::MachineApplicable, - ); - } - err.emit(); } CheckLintNameResult::NoLint(suggestion) => { let lint = builtin::UNKNOWN_LINTS; let (level, src) = self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess); let msg = format!("unknown lint: `{}`", name); - let mut db = struct_lint_level( + struct_lint_level( self.sess, lint, level, src, Some(li.span().into()), - &msg, + |lint| { + let mut db = lint.build(&msg); + if let Some(suggestion) = suggestion { + db.span_suggestion( + li.span(), + "did you mean", + suggestion.to_string(), + Applicability::MachineApplicable, + ); + } + db.emit(); + }, ); - if let Some(suggestion) = suggestion { - db.span_suggestion( - li.span(), - "did you mean", - suggestion.to_string(), - Applicability::MachineApplicable, - ); - } - - db.emit(); } } } @@ -390,10 +396,10 @@ impl<'a> LintLevelsBuilder<'a> { &self, lint: &'static Lint, span: Option, - msg: &str, - ) -> DiagnosticBuilder<'a> { + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), + ) { let (level, src) = self.sets.get_lint_level(lint, self.cur, None, self.sess); - struct_lint_level(self.sess, lint, level, src, span, msg) + struct_lint_level(self.sess, lint, level, src, span, decorate) } /// Registers the ID provided with the current set of lints stored in diff --git a/src/librustc_lint/non_ascii_idents.rs b/src/librustc_lint/non_ascii_idents.rs index 3c85a1b31b244..df91df8f8b594 100644 --- a/src/librustc_lint/non_ascii_idents.rs +++ b/src/librustc_lint/non_ascii_idents.rs @@ -25,16 +25,14 @@ impl EarlyLintPass for NonAsciiIdents { cx.struct_span_lint( NON_ASCII_IDENTS, ident.span, - "identifier contains non-ASCII characters", - ) - .emit(); + |lint| lint.build("identifier contains non-ASCII characters").emit(), + ); if !name_str.chars().all(GeneralSecurityProfile::identifier_allowed) { cx.struct_span_lint( UNCOMMON_CODEPOINTS, ident.span, - "identifier contains uncommon Unicode codepoints", + |lint| lint.build("identifier contains uncommon Unicode codepoints").emit(), ) - .emit(); } } } diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 6fdbfea7f03b3..9e291d2cb74e7 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -108,14 +108,14 @@ impl NonCamelCaseTypes { if !is_camel_case(name) { let msg = format!("{} `{}` should have an upper camel case name", sort, name); - cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, &msg) - .span_suggestion( + cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, |lint| { + lint.build(&msg).span_suggestion( ident.span, "convert the identifier to upper camel case", to_camel_case(name), Applicability::MaybeIncorrect, - ) - .emit(); + ).emit() + }) } } } @@ -226,22 +226,24 @@ impl NonSnakeCase { let sc = NonSnakeCase::to_snake_case(name); let msg = format!("{} `{}` should have a snake case name", sort, name); - let mut err = cx.struct_span_lint(NON_SNAKE_CASE, ident.span, &msg); + cx.struct_span_lint(NON_SNAKE_CASE, ident.span, |lint| { + let mut err = lint.build(&msg); + // We have a valid span in almost all cases, but we don't have one when linting a crate + // name provided via the command line. + if !ident.span.is_dummy() { + err.span_suggestion( + ident.span, + "convert the identifier to snake case", + sc, + Applicability::MaybeIncorrect, + ); + } else { + err.help(&format!("convert the identifier to snake case: `{}`", sc)); + } - // We have a valid span in almost all cases, but we don't have one when linting a crate - // name provided via the command line. - if !ident.span.is_dummy() { - err.span_suggestion( - ident.span, - "convert the identifier to snake case", - sc, - Applicability::MaybeIncorrect, - ); - } else { - err.help(&format!("convert the identifier to snake case: `{}`", sc)); - } + err.emit(); + }); - err.emit(); } } } @@ -390,8 +392,8 @@ impl NonUpperCaseGlobals { if name.chars().any(|c| c.is_lowercase()) { let uc = NonSnakeCase::to_snake_case(&name).to_uppercase(); - let msg = format!("{} `{}` should have an upper case name", sort, name); - cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, &msg) + cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| { + lint.build(&format!("{} `{}` should have an upper case name", sort, name)) .span_suggestion( ident.span, "convert the identifier to upper case", @@ -399,6 +401,7 @@ impl NonUpperCaseGlobals { Applicability::MaybeIncorrect, ) .emit(); + }) } } } diff --git a/src/librustc_lint/redundant_semicolon.rs b/src/librustc_lint/redundant_semicolon.rs index 21b244ad75d4e..68cb0b54f56c5 100644 --- a/src/librustc_lint/redundant_semicolon.rs +++ b/src/librustc_lint/redundant_semicolon.rs @@ -26,19 +26,21 @@ impl EarlyLintPass for RedundantSemicolon { } else { "unnecessary trailing semicolon" }; - let mut err = cx.struct_span_lint(REDUNDANT_SEMICOLON, stmt.span, &msg); - let suggest_msg = if multiple { - "remove these semicolons" - } else { - "remove this semicolon" - }; - err.span_suggestion( - stmt.span, - &suggest_msg, - String::new(), - Applicability::MaybeIncorrect, - ); - err.emit(); + cx.struct_span_lint(REDUNDANT_SEMICOLON, stmt.span, |lint| { + let mut err = lint.build(&msg); + let suggest_msg = if multiple { + "remove these semicolons" + } else { + "remove this semicolon" + }; + err.span_suggestion( + stmt.span, + &suggest_msg, + String::new(), + Applicability::MaybeIncorrect, + ); + err.emit(); + }); } } } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 6bc6f58f3e7fd..30a903a2a30d2 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -67,6 +67,7 @@ fn lint_overflowing_range_endpoint<'a, 'tcx>( ) -> bool { // We only want to handle exclusive (`..`) ranges, // which are represented as `ExprKind::Struct`. + let mut overwritten = false; if let ExprKind::Struct(_, eps, _) = &parent_expr.kind { if eps.len() != 2 { return false; @@ -75,35 +76,36 @@ fn lint_overflowing_range_endpoint<'a, 'tcx>( // (`..=`) instead only if it is the `end` that is // overflowing and only by 1. if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max { - let mut err = cx.struct_span_lint( + cx.struct_span_lint( OVERFLOWING_LITERALS, parent_expr.span, - &format!("range endpoint is out of range for `{}`", ty), + |lint| { + let mut err = lint.build(&format!("range endpoint is out of range for `{}`", ty)); + if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) { + use ast::{LitIntType, LitKind}; + // We need to preserve the literal's suffix, + // as it may determine typing information. + let suffix = match lit.node { + LitKind::Int(_, LitIntType::Signed(s)) => format!("{}", s.name_str()), + LitKind::Int(_, LitIntType::Unsigned(s)) => format!("{}", s.name_str()), + LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(), + _ => bug!(), + }; + let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix); + err.span_suggestion( + parent_expr.span, + &"use an inclusive range instead", + suggestion, + Applicability::MachineApplicable, + ); + err.emit(); + overwritten = true; + } + }, ); - if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) { - use ast::{LitIntType, LitKind}; - // We need to preserve the literal's suffix, - // as it may determine typing information. - let suffix = match lit.node { - LitKind::Int(_, LitIntType::Signed(s)) => format!("{}", s.name_str()), - LitKind::Int(_, LitIntType::Unsigned(s)) => format!("{}", s.name_str()), - LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(), - _ => bug!(), - }; - let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix); - err.span_suggestion( - parent_expr.span, - &"use an inclusive range instead", - suggestion, - Applicability::MachineApplicable, - ); - err.emit(); - return true; - } } } - - false + overwritten } // For `isize` & `usize`, be conservative with the warnings, so that the @@ -163,31 +165,32 @@ fn report_bin_hex_error( (t.name_str(), actually.to_string()) } }; - let mut err = cx.struct_span_lint( + cx.struct_span_lint( OVERFLOWING_LITERALS, expr.span, - &format!("literal out of range for {}", t), + |lint| { + let mut err = lint.build(&format!("literal out of range for {}", t)); + err.note(&format!( + "the literal `{}` (decimal `{}`) does not fit into \ + an `{}` and will become `{}{}`", + repr_str, val, t, actually, t + )); + if let Some(sugg_ty) = get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative) { + if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { + let (sans_suffix, _) = repr_str.split_at(pos); + err.span_suggestion( + expr.span, + &format!("consider using `{}` instead", sugg_ty), + format!("{}{}", sans_suffix, sugg_ty), + Applicability::MachineApplicable, + ); + } else { + err.help(&format!("consider using `{}` instead", sugg_ty)); + } + } + err.emit(); + }, ); - err.note(&format!( - "the literal `{}` (decimal `{}`) does not fit into \ - an `{}` and will become `{}{}`", - repr_str, val, t, actually, t - )); - if let Some(sugg_ty) = get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative) { - if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { - let (sans_suffix, _) = repr_str.split_at(pos); - err.span_suggestion( - expr.span, - &format!("consider using `{}` instead", sugg_ty), - format!("{}{}", sans_suffix, sugg_ty), - Applicability::MachineApplicable, - ); - } else { - err.help(&format!("consider using `{}` instead", sugg_ty)); - } - } - - err.emit(); } // This function finds the next fitting type and generates a suggestion string. @@ -298,18 +301,16 @@ fn lint_uint_literal<'a, 'tcx>( match par_e.kind { hir::ExprKind::Cast(..) => { if let ty::Char = cx.tables.expr_ty(par_e).kind { - let mut err = cx.struct_span_lint( - OVERFLOWING_LITERALS, - par_e.span, - "only `u8` can be cast into `char`", - ); - err.span_suggestion( - par_e.span, - &"use a `char` literal instead", - format!("'\\u{{{:X}}}'", lit_val), - Applicability::MachineApplicable, - ); - err.emit(); + cx.struct_span_lint(OVERFLOWING_LITERALS, par_e.span, |lint| { + lint.build("only `u8` can be cast into `char`") + .span_suggestion( + par_e.span, + &"use a `char` literal instead", + format!("'\\u{{{:X}}}'", lit_val), + Applicability::MachineApplicable, + ) + .emit(); + }); return; } } @@ -883,22 +884,21 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { note: &str, help: Option<&str>, ) { - let mut diag = self.cx.struct_span_lint( - IMPROPER_CTYPES, - sp, - &format!("`extern` block uses type `{}`, which is not FFI-safe", ty), - ); - diag.span_label(sp, "not FFI-safe"); - if let Some(help) = help { - diag.help(help); - } - diag.note(note); - if let ty::Adt(def, _) = ty.kind { - if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) { - diag.span_note(sp, "the type is defined here"); + self.cx.struct_span_lint(IMPROPER_CTYPES, sp, |lint| { + let mut diag = + lint.build(&format!("`extern` block uses type `{}`, which is not FFI-safe", ty)); + diag.span_label(sp, "not FFI-safe"); + if let Some(help) = help { + diag.help(help); } - } - diag.emit(); + diag.note(note); + if let ty::Adt(def, _) = ty.kind { + if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) { + diag.span_note(sp, "the type is defined here"); + } + } + diag.emit(); + }); } fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 5490e5e2b4d55..2f4a9572a8349 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -213,18 +213,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { ) -> bool { for attr in cx.tcx.get_attrs(def_id).iter() { if attr.check_name(sym::must_use) { - let msg = format!( - "unused {}`{}`{} that must be used", - descr_pre_path, - cx.tcx.def_path_str(def_id), - descr_post_path - ); - let mut err = cx.struct_span_lint(UNUSED_MUST_USE, span, &msg); - // check for #[must_use = "..."] - if let Some(note) = attr.value_str() { - err.note(¬e.as_str()); - } - err.emit(); + cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| { + let msg = format!( + "unused {}`{}`{} that must be used", + descr_pre_path, + cx.tcx.def_path_str(def_id), + descr_post_path + ); + let mut err = lint.build(&msg); + // check for #[must_use = "..."] + if let Some(note) = attr.value_str() { + err.note(¬e.as_str()); + } + err.emit(); + }); return true; } } @@ -406,52 +408,54 @@ impl UnusedParens { msg: &str, keep_space: (bool, bool), ) { - let span_msg = format!("unnecessary parentheses around {}", msg); - let mut err = cx.struct_span_lint(UNUSED_PARENS, span, &span_msg); - let mut ate_left_paren = false; - let mut ate_right_paren = false; - let parens_removed = pattern.trim_matches(|c| match c { - '(' => { - if ate_left_paren { - false - } else { - ate_left_paren = true; - true + cx.struct_span_lint(UNUSED_PARENS, span, |lint| { + let span_msg = format!("unnecessary parentheses around {}", msg); + let mut err = lint.build(&span_msg); + let mut ate_left_paren = false; + let mut ate_right_paren = false; + let parens_removed = pattern.trim_matches(|c| match c { + '(' => { + if ate_left_paren { + false + } else { + ate_left_paren = true; + true + } } - } - ')' => { - if ate_right_paren { - false - } else { - ate_right_paren = true; - true + ')' => { + if ate_right_paren { + false + } else { + ate_right_paren = true; + true + } } - } - _ => false, - }); + _ => false, + }); - let replace = { - let mut replace = if keep_space.0 { - let mut s = String::from(" "); - s.push_str(parens_removed); - s - } else { - String::from(parens_removed) - }; + let replace = { + let mut replace = if keep_space.0 { + let mut s = String::from(" "); + s.push_str(parens_removed); + s + } else { + String::from(parens_removed) + }; - if keep_space.1 { - replace.push(' '); - } - replace - }; + if keep_space.1 { + replace.push(' '); + } + replace + }; - err.span_suggestion_short( - span, - "remove these parentheses", - replace, - Applicability::MachineApplicable, - ); - err.emit(); + err.span_suggestion_short( + span, + "remove these parentheses", + replace, + Applicability::MachineApplicable, + ); + err.emit(); + }); } } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index e528159fcef17..25f1a495ad3e4 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -319,18 +319,20 @@ fn do_mir_borrowck<'a, 'tcx>( }; // Span and message don't matter; we overwrite them below anyway - let mut diag = mbcx.infcx.tcx.struct_span_lint_hir( + mbcx.infcx.tcx.struct_span_lint_hir( MUTABLE_BORROW_RESERVATION_CONFLICT, lint_root, DUMMY_SP, - "", - ); + |lint| { + let mut diag = lint.build(""); - diag.message = initial_diag.styled_message().clone(); - diag.span = initial_diag.span.clone(); + diag.message = initial_diag.styled_message().clone(); + diag.span = initial_diag.span.clone(); + diag.buffer(&mut mbcx.errors_buffer); + }, + ); initial_diag.cancel(); - diag.buffer(&mut mbcx.errors_buffer); } // For each non-user used mutable variable, check if it's been assigned from @@ -381,15 +383,17 @@ fn do_mir_borrowck<'a, 'tcx>( UNUSED_MUT, lint_root, span, - "variable does not need to be mutable", - ) - .span_suggestion_short( - mut_span, - "remove this `mut`", - String::new(), - Applicability::MachineApplicable, + |lint| { + lint.build("variable does not need to be mutable") + .span_suggestion_short( + mut_span, + "remove this `mut`", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); + }, ) - .emit(); } // Buffer any move errors that we collected and de-duplicated. diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 428db8356b122..99d3b281945eb 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -209,10 +209,11 @@ fn validate_and_turn_into_const<'tcx>( val.map_err(|error| { let err = error_to_const_error(&ecx, error); - match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") { - Ok(mut diag) => { - diag.note(note_on_undefined_behavior_error()); - diag.emit(); + match err.struct_error(ecx.tcx, "it is undefined behavior to use this value", |mut diag| { + diag.note(note_on_undefined_behavior_error()); + diag.emit(); + }) { + Ok(_) => { ErrorHandled::Reported } Err(err) => err, diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 0c65b77a38240..9fea82d78c94f 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -326,12 +326,15 @@ pub fn intern_const_alloc_recursive>( // to read enum discriminants in order to find references in enum variant fields. if let err_unsup!(ValidationFailure(_)) = error.kind { let err = crate::const_eval::error_to_const_error(&ecx, error); - match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") { - Ok(mut diag) => { + match err.struct_error( + ecx.tcx, + "it is undefined behavior to use this value", + |mut diag| { diag.note(crate::const_eval::note_on_undefined_behavior_error()); diag.emit(); - } - Err(ErrorHandled::TooGeneric) | Err(ErrorHandled::Reported) => {} + }, + ) { + Ok(()) | Err(ErrorHandled::TooGeneric) | Err(ErrorHandled::Reported) => {} } } } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 8dc185cd82b3b..c019fa57fb783 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -527,7 +527,9 @@ fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: DefId) { does not derive Copy (error E0133)" .to_string() }; - tcx.lint_hir(SAFE_PACKED_BORROWS, lint_hir_id, tcx.def_span(def_id), &message); + tcx.struct_span_lint_hir(SAFE_PACKED_BORROWS, lint_hir_id, tcx.def_span(def_id), |lint| { + lint.build(&message).emit() + }); } /// Returns the `HirId` for an enclosing scope that is also `unsafe`. @@ -559,15 +561,17 @@ fn is_enclosed( fn report_unused_unsafe(tcx: TyCtxt<'_>, used_unsafe: &FxHashSet, id: hir::HirId) { let span = tcx.sess.source_map().def_span(tcx.hir().span(id)); let msg = "unnecessary `unsafe` block"; - let mut db = tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, msg); - db.span_label(span, msg); - if let Some((kind, id)) = is_enclosed(tcx, used_unsafe, id) { - db.span_label( - tcx.sess.source_map().def_span(tcx.hir().span(id)), - format!("because it's nested under this `unsafe` {}", kind), - ); - } - db.emit(); + tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, |lint| { + let mut db = lint.build(msg); + db.span_label(span, msg); + if let Some((kind, id)) = is_enclosed(tcx, used_unsafe, id) { + db.span_label( + tcx.sess.source_map().def_span(tcx.hir().span(id)), + format!("because it's nested under this `unsafe` {}", kind), + ); + } + db.emit(); + }); } fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { @@ -619,13 +623,17 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) { SAFE_PACKED_BORROWS, lint_hir_id, source_info.span, - &format!( - "{} is unsafe and requires unsafe function or block (error E0133)", - description - ), + |lint| { + lint.build( + &format!( + "{} is unsafe and requires unsafe function or block (error E0133)", + description + ) + ) + .note(&details.as_str()) + .emit() + } ) - .note(&details.as_str()) - .emit(); } } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index d645f6cf183b4..aeeca52ba3ba2 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -557,11 +557,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if r_bits.map_or(false, |b| b >= left_bits as u128) { let lint_root = self.lint_root(source_info)?; let dir = if op == BinOp::Shr { "right" } else { "left" }; - self.tcx.lint_hir( + self.tcx.struct_span_lint_hir( ::rustc::lint::builtin::EXCEEDING_BITSHIFTS, lint_root, source_info.span, - &format!("attempt to shift {} with overflow", dir), + |lint| lint.build(&format!("attempt to shift {} with overflow", dir)).emit(), ); return None; } @@ -912,35 +912,42 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { .hir() .as_local_hir_id(self.source.def_id()) .expect("some part of a failing const eval must be local"); - let msg = match msg { - PanicInfo::Overflow(_) - | PanicInfo::OverflowNeg - | PanicInfo::DivisionByZero - | PanicInfo::RemainderByZero => msg.description().to_owned(), - PanicInfo::BoundsCheck { ref len, ref index } => { - let len = - self.eval_operand(len, source_info).expect("len must be const"); - let len = match self.ecx.read_scalar(len) { - Ok(ScalarMaybeUndef::Scalar(Scalar::Raw { data, .. })) => data, - other => bug!("const len not primitive: {:?}", other), - }; - let index = self - .eval_operand(index, source_info) - .expect("index must be const"); - let index = match self.ecx.read_scalar(index) { - Ok(ScalarMaybeUndef::Scalar(Scalar::Raw { data, .. })) => data, - other => bug!("const index not primitive: {:?}", other), + self.tcx.struct_span_lint_hir( + ::rustc::lint::builtin::CONST_ERR, + hir_id, + span, + |lint| { + let msg = match msg { + PanicInfo::Overflow(_) + | PanicInfo::OverflowNeg + | PanicInfo::DivisionByZero + | PanicInfo::RemainderByZero => msg.description().to_owned(), + PanicInfo::BoundsCheck { ref len, ref index } => { + let len = + self.eval_operand(len, source_info).expect("len must be const"); + let len = match self.ecx.read_scalar(len) { + Ok(ScalarMaybeUndef::Scalar(Scalar::Raw { data, .. })) => data, + other => bug!("const len not primitive: {:?}", other), + }; + let index = self + .eval_operand(index, source_info) + .expect("index must be const"); + let index = match self.ecx.read_scalar(index) { + Ok(ScalarMaybeUndef::Scalar(Scalar::Raw { data, .. })) => data, + other => bug!("const index not primitive: {:?}", other), + }; + format!( + "index out of bounds: \ + the len is {} but the index is {}", + len, index, + ) + } + // Need proper const propagator for these + _ => return, }; - format!( - "index out of bounds: \ - the len is {} but the index is {}", - len, index, - ) - } - // Need proper const propagator for these - _ => return, - }; - self.tcx.lint_hir(::rustc::lint::builtin::CONST_ERR, hir_id, span, &msg); + lint.build(&msg).emit() + }, + ); } else { if self.should_const_prop(value) { if let ScalarMaybeUndef::Scalar(scalar) = value_const { diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 4f0e5bb45822b..7ed6c81eb63bd 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -2235,24 +2235,26 @@ fn lint_overlapping_patterns<'tcx>( overlaps: Vec>, ) { if let (true, Some(hir_id)) = (!overlaps.is_empty(), hir_id) { - let mut err = tcx.struct_span_lint_hir( + tcx.struct_span_lint_hir( lint::builtin::OVERLAPPING_PATTERNS, hir_id, ctor_range.span, - "multiple patterns covering the same range", + |lint| { + let mut err = lint.build("multiple patterns covering the same range"); + err.span_label(ctor_range.span, "overlapping patterns"); + for int_range in overlaps { + // Use the real type for user display of the ranges: + err.span_label( + int_range.span, + &format!( + "this range overlaps on `{}`", + IntRange { range: int_range.range, ty, span: DUMMY_SP }.to_pat(tcx), + ), + ); + } + err.emit(); + }, ); - err.span_label(ctor_range.span, "overlapping patterns"); - for int_range in overlaps { - // Use the real type for user display of the ranges: - err.span_label( - int_range.span, - &format!( - "this range overlaps on `{}`", - IntRange { range: int_range.range, ty, span: DUMMY_SP }.to_pat(tcx), - ), - ); - } - err.emit(); } } diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index b77bd4ecb8e1f..421f7958e5f49 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -292,20 +292,25 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa BINDINGS_WITH_VARIANT_NAME, p.hir_id, p.span, - &format!( - "pattern binding `{}` is named the same as one \ - of the variants of the type `{}`", - ident, ty_path - ), + |lint| { + lint + .build( + &format!( + "pattern binding `{}` is named the same as one \ + of the variants of the type `{}`", + ident, ty_path + ) + ) + .code(error_code!(E0170)) + .span_suggestion( + p.span, + "to match on the variant, qualify the path", + format!("{}::{}", ty_path, ident), + Applicability::MachineApplicable, + ) + .emit(); + }, ) - .code(error_code!(E0170)) - .span_suggestion( - p.span, - "to match on the variant, qualify the path", - format!("{}::{}", ty_path, ident), - Applicability::MachineApplicable, - ) - .emit(); } } } @@ -325,13 +330,15 @@ fn pat_is_catchall(pat: &super::Pat<'_>) -> bool { } fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option) { - let mut err = tcx.struct_span_lint_hir(UNREACHABLE_PATTERNS, id, span, "unreachable pattern"); - if let Some(catchall) = catchall { - // We had a catchall pattern, hint at that. - err.span_label(span, "unreachable pattern"); - err.span_label(catchall, "matches any value"); - } - err.emit(); + tcx.struct_span_lint_hir(UNREACHABLE_PATTERNS, id, span, |lint| { + let mut err = lint.build("unreachable pattern"); + if let Some(catchall) = catchall { + // We had a catchall pattern, hint at that. + err.span_label(span, "unreachable pattern"); + err.span_label(catchall, "matches any value"); + } + err.emit(); + }); } fn irrefutable_let_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, source: hir::MatchSource) { @@ -340,7 +347,7 @@ fn irrefutable_let_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, source: hir:: hir::MatchSource::WhileLetDesugar => "irrefutable while-let pattern", _ => bug!(), }; - tcx.lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, msg); + tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| lint.build(msg).emit()); } /// Check for unreachable patterns. diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs index a21a0ee8a1b20..5fbe764430c54 100644 --- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs +++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs @@ -109,11 +109,14 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { } }; let path = self.tcx().def_path_str(adt_def.did); - let msg = format!( - "to use a constant of type `{}` in a pattern, \ - `{}` must be annotated with `#[derive(PartialEq, Eq)]`", - path, path, - ); + + let make_msg = || -> String { + format!( + "to use a constant of type `{}` in a pattern, \ + `{}` must be annotated with `#[derive(PartialEq, Eq)]`", + path, path, + ) + }; // double-check there even *is* a semantic `PartialEq` to dispatch to. // @@ -143,13 +146,13 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { if !ty_is_partial_eq { // span_fatal avoids ICE from resolution of non-existent method (rare case). - self.tcx().sess.span_fatal(self.span, &msg); + self.tcx().sess.span_fatal(self.span, &make_msg()); } else { - self.tcx().lint_hir( + self.tcx().struct_span_lint_hir( lint::builtin::INDIRECT_STRUCTURAL_MATCH, self.id, self.span, - &msg, + |lint| lint.build(&make_msg()).emit(), ); } } @@ -177,11 +180,11 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { let kind = match cv.ty.kind { ty::Float(_) => { - tcx.lint_hir( + tcx.struct_span_lint_hir( ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, id, span, - "floating-point types cannot be used in patterns", + |lint| lint.build("floating-point types cannot be used in patterns").emit(), ); PatKind::Constant { value: cv } } diff --git a/src/librustc_mir_build/lints.rs b/src/librustc_mir_build/lints.rs index 4244e1b8d80a6..4704f8d034dca 100644 --- a/src/librustc_mir_build/lints.rs +++ b/src/librustc_mir_build/lints.rs @@ -124,18 +124,20 @@ fn check_fn_for_unconditional_recursion<'tcx>( if !reached_exit_without_self_call && !self_call_locations.is_empty() { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); let sp = tcx.sess.source_map().def_span(tcx.hir().span(hir_id)); - let mut db = tcx.struct_span_lint_hir( + tcx.struct_span_lint_hir( UNCONDITIONAL_RECURSION, hir_id, sp, - "function cannot return without recursing", + |lint| { + let mut db = lint.build("function cannot return without recursing"); + db.span_label(sp, "cannot return without recursing"); + // offer some help to the programmer. + for location in &self_call_locations { + db.span_label(location.span, "recursive call site"); + } + db.help("a `loop` may express intention better if this is on purpose"); + db.emit(); + }, ); - db.span_label(sp, "cannot return without recursing"); - // offer some help to the programmer. - for location in &self_call_locations { - db.span_label(location.span, "recursive call site"); - } - db.help("a `loop` may express intention better if this is on purpose"); - db.emit(); } } diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index 0edd56680f933..cd935a37f7dda 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -315,10 +315,11 @@ impl<'a> StripUnconfigured<'a> { validate_attr::check_meta_bad_delim(self.sess, dspan, delim, msg); match parse_in(self.sess, tts.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) { Ok(r) => return Some(r), - Err(mut e) => e - .help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP)) + Err(mut e) => { + e.help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP)) .note(CFG_ATTR_NOTE_REF) - .emit(), + .emit(); + }, } } _ => self.error_malformed_cfg_attr_missing(attr.span), diff --git a/src/librustc_parse/lexer/unescape_error_reporting.rs b/src/librustc_parse/lexer/unescape_error_reporting.rs index 88762dabd8a29..d41775a143ad6 100644 --- a/src/librustc_parse/lexer/unescape_error_reporting.rs +++ b/src/librustc_parse/lexer/unescape_error_reporting.rs @@ -69,7 +69,7 @@ pub(crate) fn emit_unescape_error( format!("\"{}\"", lit), Applicability::MachineApplicable, ) - .emit() + .emit(); } EscapeError::EscapeOnlyChar => { let (c, _span) = last_char(); diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs index e58eb9ffc51e7..905f6bef58e85 100644 --- a/src/librustc_parse/parser/attr.rs +++ b/src/librustc_parse/parser/attr.rs @@ -149,7 +149,7 @@ impl<'a> Parser<'a> { source files. Outer attributes, like `#[test]`, annotate the \ item following them.", ) - .emit() + .emit(); } } @@ -239,7 +239,7 @@ impl<'a> Parser<'a> { (`1u8`, `1.0f32`, etc.), use an unsuffixed version \ (`1`, `1.0`, etc.)", ) - .emit() + .emit(); } Ok(lit) diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 237b3cc13d394..018aef3c13cee 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -1014,7 +1014,7 @@ impl<'a> Parser<'a> { String::new(), Applicability::MachineApplicable, ) - .emit() + .emit(); } } diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 7131eb1144e06..ba97f3feb8021 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -1407,6 +1407,6 @@ pub fn emit_unclosed_delims(unclosed_delims: &mut Vec, sess: &Pa *sess.reached_eof.borrow_mut() |= unclosed_delims.iter().any(|unmatched_delim| unmatched_delim.found_delim.is_none()); for unmatched in unclosed_delims.drain(..) { - make_unclosed_delims_error(unmatched, sess).map(|mut e| e.emit()); + make_unclosed_delims_error(unmatched, sess).map(|mut e| { e.emit(); }); } } diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index 985185230f26a..ec6d4db610285 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -572,7 +572,7 @@ impl<'a> Parser<'a> { self.struct_span_err(span, problem) .span_suggestion(span, suggestion, fix, Applicability::MachineApplicable) .note("`mut` may be followed by `variable` and `variable @ pattern`") - .emit() + .emit(); } /// Eat any extraneous `mut`s and error + recover if we ate any. diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs index 84562fbb46ff2..f6d5da68be3b6 100644 --- a/src/librustc_parse/validate_attr.rs +++ b/src/librustc_parse/validate_attr.rs @@ -27,7 +27,7 @@ pub fn check_meta(sess: &ParseSess, attr: &Attribute) { _ => { if let MacArgs::Eq(..) = attr.get_normal_item().args { // All key-value attributes are restricted to meta-item syntax. - parse_meta(sess, attr).map_err(|mut err| err.emit()).ok(); + parse_meta(sess, attr).map_err(|mut err| { err.emit(); }).ok(); } } } @@ -152,6 +152,6 @@ pub fn check_builtin_attribute( } } } - Err(mut err) => err.emit(), + Err(mut err) => { err.emit(); }, } } diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs index a877c1de175e1..6bae61d787b9b 100644 --- a/src/librustc_passes/check_attr.rs +++ b/src/librustc_passes/check_attr.rs @@ -97,9 +97,8 @@ impl CheckAttrVisitor<'tcx> { UNUSED_ATTRIBUTES, hir_id, attr.span, - "`#[inline]` is ignored on function prototypes", - ) - .emit(); + |lint| lint.build("`#[inline]` is ignored on function prototypes").emit(), + ); true } // FIXME(#65833): We permit associated consts to have an `#[inline]` attribute with @@ -112,18 +111,19 @@ impl CheckAttrVisitor<'tcx> { UNUSED_ATTRIBUTES, hir_id, attr.span, - "`#[inline]` is ignored on constants", - ) - .warn( - "this was previously accepted by the compiler but is \ - being phased out; it will become a hard error in \ - a future release!", - ) - .note( - "see issue #65833 \ - for more information", - ) - .emit(); + |lint| { + lint.build("`#[inline]` is ignored on constants") + .warn( + "this was previously accepted by the compiler but is \ + being phased out; it will become a hard error in \ + a future release!", + ) + .note( + "see issue #65833 \ + for more information", + ) + .emit(); + }); true } _ => { @@ -336,10 +336,12 @@ impl CheckAttrVisitor<'tcx> { CONFLICTING_REPR_HINTS, hir_id, hint_spans.collect::>(), - "conflicting representation hints", - ) - .code(rustc_errors::error_code!(E0566)) - .emit(); + |lint| { + lint.build("conflicting representation hints") + .code(rustc_errors::error_code!(E0566)) + .emit(); + } + ); } } diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index 9367909d10c30..25b8b8fcd444b 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -554,12 +554,9 @@ impl DeadVisitor<'tcx> { participle: &str, ) { if !name.as_str().starts_with("_") { - self.tcx.lint_hir( - lint::builtin::DEAD_CODE, - id, - span, - &format!("{} is never {}: `{}`", node_type, participle, name), - ); + self.tcx.struct_span_lint_hir(lint::builtin::DEAD_CODE, id, span, |lint| { + lint.build(&format!("{} is never {}: `{}`", node_type, participle, name)).emit() + }); } } } diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index b355a47c39470..27ad953e4fa6b 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -1527,39 +1527,41 @@ impl<'tcx> Liveness<'_, 'tcx> { lint::builtin::UNUSED_VARIABLES, hir_id, spans, - &format!("variable `{}` is assigned to, but never used", name), + |lint| { + lint.build(&format!("variable `{}` is assigned to, but never used", name)) + .note(&format!("consider using `_{}` instead", name)) + .emit(); + }, ) - .note(&format!("consider using `_{}` instead", name)) - .emit(); } else { - let mut err = self.ir.tcx.struct_span_lint_hir( + self.ir.tcx.struct_span_lint_hir( lint::builtin::UNUSED_VARIABLES, hir_id, spans.clone(), - &format!("unused variable: `{}`", name), + |lint| { + let mut err = lint.build(&format!("unused variable: `{}`", name)); + if self.ir.variable_is_shorthand(var) { + if let Node::Binding(pat) = self.ir.tcx.hir().get(hir_id) { + // Handle `ref` and `ref mut`. + let spans = + spans.iter().map(|_span| (pat.span, format!("{}: _", name))).collect(); + + err.multipart_suggestion( + "try ignoring the field", + spans, + Applicability::MachineApplicable, + ); + } + } else { + err.multipart_suggestion( + "consider prefixing with an underscore", + spans.iter().map(|span| (*span, format!("_{}", name))).collect(), + Applicability::MachineApplicable, + ); + } + err.emit() + }, ); - - if self.ir.variable_is_shorthand(var) { - if let Node::Binding(pat) = self.ir.tcx.hir().get(hir_id) { - // Handle `ref` and `ref mut`. - let spans = - spans.iter().map(|_span| (pat.span, format!("{}: _", name))).collect(); - - err.multipart_suggestion( - "try ignoring the field", - spans, - Applicability::MachineApplicable, - ); - } - } else { - err.multipart_suggestion( - "consider prefixing with an underscore", - spans.iter().map(|span| (*span, format!("_{}", name))).collect(), - Applicability::MachineApplicable, - ); - } - - err.emit() } } } @@ -1579,10 +1581,12 @@ impl<'tcx> Liveness<'_, 'tcx> { lint::builtin::UNUSED_ASSIGNMENTS, hir_id, spans, - &format!("value passed to `{}` is never read", name), + |lint| { + lint.build(&format!("value passed to `{}` is never read", name)) + .help("maybe it is overwritten before being read?") + .emit(); + }, ) - .help("maybe it is overwritten before being read?") - .emit(); } else { self.ir .tcx @@ -1590,10 +1594,12 @@ impl<'tcx> Liveness<'_, 'tcx> { lint::builtin::UNUSED_ASSIGNMENTS, hir_id, spans, - &format!("value assigned to `{}` is never read", name), + |lint| { + lint.build(&format!("value assigned to `{}` is never read", name)) + .help("maybe it is overwritten before being read?") + .emit(); + }, ) - .help("maybe it is overwritten before being read?") - .emit(); } } } diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 12debfb66a431..374b7d1cf7a15 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -604,15 +604,13 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { } fn unnecessary_stable_feature_lint(tcx: TyCtxt<'_>, span: Span, feature: Symbol, since: Symbol) { - tcx.lint_hir( - lint::builtin::STABLE_FEATURES, - hir::CRATE_HIR_ID, - span, - &format!( + tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| { + lint.build(&format!( "the feature `{}` has been stable since {} and no longer requires \ - an attribute to enable", - feature, since - ), + an attribute to enable", + feature, since + )).emit(); + } ); } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 74bb72d6fad7f..43f92ae69c46b 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1781,17 +1781,21 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { if self.leaks_private_dep(def_id) { - self.tcx.lint_hir( + self.tcx.struct_span_lint_hir( lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES, self.item_id, self.span, - &format!( - "{} `{}` from private dependency '{}' in public \ - interface", - kind, - descr, - self.tcx.crate_name(def_id.krate) - ), + |lint| { + lint.build( + &format!( + "{} `{}` from private dependency '{}' in public \ + interface", + kind, + descr, + self.tcx.crate_name(def_id.krate) + ) + ).emit() + }, ); } @@ -1814,12 +1818,9 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { err.emit(); } else { let err_code = if kind == "trait" { "E0445" } else { "E0446" }; - self.tcx.lint_hir( - lint::builtin::PRIVATE_IN_PUBLIC, - hir_id, - self.span, - &format!("{} (error {})", msg, err_code), - ); + self.tcx.struct_span_lint_hir(lint::builtin::PRIVATE_IN_PUBLIC, hir_id, self.span, |lint| { + lint.build(&format!("{} (error {})", msg, err_code)).emit() + }); } } diff --git a/src/librustc_resolve/lifetimes.rs b/src/librustc_resolve/lifetimes.rs index 87522d28d1e80..cef5e025741d7 100644 --- a/src/librustc_resolve/lifetimes.rs +++ b/src/librustc_resolve/lifetimes.rs @@ -1575,22 +1575,23 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } - let mut err = self.tcx.struct_span_lint_hir( + self.tcx.struct_span_lint_hir( lint::builtin::SINGLE_USE_LIFETIMES, id, span, - &format!("lifetime parameter `{}` only used once", name), + |lint| { + let mut err = lint.build(&format!("lifetime parameter `{}` only used once", name)); + if span == lifetime.span { + // spans are the same for in-band lifetime declarations + err.span_label(span, "this lifetime is only used here"); + } else { + err.span_label(span, "this lifetime..."); + err.span_label(lifetime.span, "...is used only here"); + } + self.suggest_eliding_single_use_lifetime(&mut err, def_id, lifetime); + err.emit(); + }, ); - - if span == lifetime.span { - // spans are the same for in-band lifetime declarations - err.span_label(span, "this lifetime is only used here"); - } else { - err.span_label(span, "this lifetime..."); - err.span_label(lifetime.span, "...is used only here"); - } - self.suggest_eliding_single_use_lifetime(&mut err, def_id, lifetime); - err.emit(); } } Some(LifetimeUseSet::Many) => { @@ -1610,26 +1611,28 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { _ => None, } { debug!("id ={:?} span = {:?} name = {:?}", id, span, name); - let mut err = self.tcx.struct_span_lint_hir( + self.tcx.struct_span_lint_hir( lint::builtin::UNUSED_LIFETIMES, id, span, - &format!("lifetime parameter `{}` never used", name), - ); - if let Some(parent_def_id) = self.tcx.parent(def_id) { - if let Some(generics) = self.tcx.hir().get_generics(parent_def_id) { - let unused_lt_span = self.lifetime_deletion_span(name, generics); - if let Some(span) = unused_lt_span { - err.span_suggestion( - span, - "elide the unused lifetime", - String::new(), - Applicability::MachineApplicable, - ); + |lint| { + let mut err = lint.build(&format!("lifetime parameter `{}` never used", name)); + if let Some(parent_def_id) = self.tcx.parent(def_id) { + if let Some(generics) = self.tcx.hir().get_generics(parent_def_id) { + let unused_lt_span = self.lifetime_deletion_span(name, generics); + if let Some(span) = unused_lt_span { + err.span_suggestion( + span, + "elide the unused lifetime", + String::new(), + Applicability::MachineApplicable, + ); + } + } } - } - } - err.emit(); + err.emit(); + }, + ); } } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 2909d0f8c54e7..c26b47c313023 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -331,11 +331,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { let mut multispan = MultiSpan::from_span(span); multispan.push_span_label(span_late, note.to_string()); - tcx.lint_hir( + tcx.struct_span_lint_hir( lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, args.args[0].id(), multispan, - msg, + |lint| lint.build(msg).emit(), ); reported_late_bound_region_err = Some(false); } @@ -2216,34 +2216,31 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.check_stability(item.def_id, Some(hir_ref_id), span); if let Some(variant_def_id) = variant_resolution { - let mut err = tcx.struct_span_lint_hir( - AMBIGUOUS_ASSOCIATED_ITEMS, - hir_ref_id, - span, - "ambiguous associated item", - ); + tcx.struct_span_lint_hir(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| { + let mut err = lint.build("ambiguous associated item"); + let mut could_refer_to = |kind: DefKind, def_id, also| { + let note_msg = format!( + "`{}` could{} refer to the {} defined here", + assoc_ident, + also, + kind.descr(def_id) + ); + err.span_note(tcx.def_span(def_id), ¬e_msg); + }; - let mut could_refer_to = |kind: DefKind, def_id, also| { - let note_msg = format!( - "`{}` could{} refer to the {} defined here", - assoc_ident, - also, - kind.descr(def_id) + could_refer_to(DefKind::Variant, variant_def_id, ""); + could_refer_to(kind, item.def_id, " also"); + + err.span_suggestion( + span, + "use fully-qualified syntax", + format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident), + Applicability::MachineApplicable, ); - err.span_note(tcx.def_span(def_id), ¬e_msg); - }; - could_refer_to(DefKind::Variant, variant_def_id, ""); - could_refer_to(kind, item.def_id, " also"); - err.span_suggestion( - span, - "use fully-qualified syntax", - format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident), - Applicability::MachineApplicable, - ) - .emit(); + err.emit(); + }); } - Ok((ty, kind, item.def_id)) } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index d254a84df72ce..02da2766ec661 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -468,23 +468,27 @@ impl<'a, 'tcx> CastCheck<'tcx> { } else { ("", lint::builtin::TRIVIAL_CASTS) }; - let mut err = fcx.tcx.struct_span_lint_hir( + fcx.tcx.struct_span_lint_hir( lint, self.expr.hir_id, self.span, - &format!( - "trivial {}cast: `{}` as `{}`", - adjective, - fcx.ty_to_string(t_expr), - fcx.ty_to_string(t_cast) - ), + |err| { + err.build( + &format!( + "trivial {}cast: `{}` as `{}`", + adjective, + fcx.ty_to_string(t_expr), + fcx.ty_to_string(t_cast) + ) + ) + .help(&format!( + "cast can be replaced by coercion; this might \ + require {}a temporary variable", + type_asc_or + )) + .emit(); + }, ); - err.help(&format!( - "cast can be replaced by coercion; this might \ - require {}a temporary variable", - type_asc_or - )); - err.emit(); } pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) { diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 497a401a031e5..599f7dfe2d41c 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -382,11 +382,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) .emit(); } else { - self.tcx.lint_hir( + self.tcx.struct_span_lint_hir( lint::builtin::TYVAR_BEHIND_RAW_POINTER, scope_expr_id, span, - "type annotations needed", + |lint| lint.build("type annotations needed").emit(), ); } } else { @@ -1280,33 +1280,34 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { stable_pick: &Pick<'_>, unstable_candidates: &[(&Candidate<'tcx>, Symbol)], ) { - let mut diag = self.tcx.struct_span_lint_hir( + self.tcx.struct_span_lint_hir( lint::builtin::UNSTABLE_NAME_COLLISIONS, self.fcx.body_id, self.span, - "a method with this name may be added to the standard library in the future", - ); - - // FIXME: This should be a `span_suggestion` instead of `help` - // However `self.span` only - // highlights the method name, so we can't use it. Also consider reusing the code from - // `report_method_error()`. - diag.help(&format!( - "call with fully qualified syntax `{}(...)` to keep using the current method", - self.tcx.def_path_str(stable_pick.item.def_id), - )); - - if nightly_options::is_nightly_build() { - for (candidate, feature) in unstable_candidates { + |lint| { + let mut diag = lint.build("a method with this name may be added to the standard library in the future"); + // FIXME: This should be a `span_suggestion` instead of `help` + // However `self.span` only + // highlights the method name, so we can't use it. Also consider reusing the code from + // `report_method_error()`. diag.help(&format!( - "add `#![feature({})]` to the crate attributes to enable `{}`", - feature, - self.tcx.def_path_str(candidate.item.def_id), + "call with fully qualified syntax `{}(...)` to keep using the current method", + self.tcx.def_path_str(stable_pick.item.def_id), )); - } - } - diag.emit(); + if nightly_options::is_nightly_build() { + for (candidate, feature) in unstable_candidates { + diag.help(&format!( + "add `#![feature({})]` to the crate attributes to enable `{}`", + feature, + self.tcx.def_path_str(candidate.item.def_id), + )); + } + } + + diag.emit(); + }, + ); } fn select_trait_candidate( diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b82a83171d1eb..2fff5106dd1d2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2895,15 +2895,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind); - let msg = format!("unreachable {}", kind); self.tcx() - .struct_span_lint_hir(lint::builtin::UNREACHABLE_CODE, id, span, &msg) - .span_label(span, &msg) - .span_label( - orig_span, - custom_note.unwrap_or("any code following this expression is unreachable"), - ) - .emit(); + .struct_span_lint_hir(lint::builtin::UNREACHABLE_CODE, id, span, |lint| { + let msg = format!("unreachable {}", kind); + lint.build(&msg) + .span_label(span, &msg) + .span_label( + orig_span, + custom_note.unwrap_or("any code following this expression is unreachable"), + ) + .emit(); + }) } } } diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index ec098c1d89679..71ce5ce0f02ce 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -55,12 +55,14 @@ impl CheckVisitor<'tcx> { return; } - let msg = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - format!("unused import: `{}`", snippet) - } else { - "unused import".to_owned() - }; - self.tcx.lint_hir(lint::builtin::UNUSED_IMPORTS, id, span, &msg); + self.tcx.struct_span_lint_hir(lint::builtin::UNUSED_IMPORTS, id, span, |lint| { + let msg = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { + format!("unused import: `{}`", snippet) + } else { + "unused import".to_owned() + }; + lint.build(&msg).emit(); + }); } } @@ -130,14 +132,16 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { .map(|attr| attr.span) .fold(span, |acc, attr_span| acc.to(attr_span)); - tcx.struct_span_lint_hir(lint, id, span, msg) - .span_suggestion_short( - span_with_attrs, - "remove it", - String::new(), - Applicability::MachineApplicable, - ) - .emit(); + tcx.struct_span_lint_hir(lint, id, span, |lint| { + lint.build(msg) + .span_suggestion_short( + span_with_attrs, + "remove it", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); + }); continue; } } @@ -170,21 +174,25 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { } // Otherwise, we can convert it into a `use` of some kind. - let msg = "`extern crate` is not idiomatic in the new edition"; - let help = format!("convert it to a `{}`", visibility_qualified(&item.vis, "use")); let base_replacement = match extern_crate.orig_name { Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name), None => format!("use {};", item.ident.name), }; let replacement = visibility_qualified(&item.vis, base_replacement); - tcx.struct_span_lint_hir(lint, id, extern_crate.span, msg) - .span_suggestion_short( - extern_crate.span, - &help, - replacement, - Applicability::MachineApplicable, - ) - .emit(); + tcx.struct_span_lint_hir(lint, id, extern_crate.span, |lint| { + + let msg = "`extern crate` is not idiomatic in the new edition"; + let help = format!("convert it to a `{}`", visibility_qualified(&item.vis, "use")); + + lint.build(msg) + .span_suggestion_short( + extern_crate.span, + &help, + replacement, + Applicability::MachineApplicable, + ) + .emit(); + }) } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1a3016cd9d33b..d26a4cdc5ca77 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1151,14 +1151,16 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { GenericParamKind::Type { ref default, synthetic, .. } => { if !allow_defaults && default.is_some() { if !tcx.features().default_type_parameter_fallback { - tcx.lint_hir( + tcx.struct_span_lint_hir( lint::builtin::INVALID_TYPE_PARAM_DEFAULT, param.hir_id, param.span, - &format!( + |lint| { + lint.build(&format!( "defaults for type parameters are only allowed in \ `struct`, `enum`, `type`, or `trait` definitions." - ), + )).emit(); + }, ); } } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 9ecf6d531299f..dfb75c5a98e73 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -669,39 +669,41 @@ fn build_diagnostic( let attrs = &item.attrs; let sp = span_of_attrs(attrs).unwrap_or(item.source.span()); - let mut diag = cx.tcx.struct_span_lint_hir( + cx.tcx.struct_span_lint_hir( lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, hir_id, sp, - &format!("`[{}]` {}", path_str, err_msg), + |lint| { + let mut diag = lint.build(&format!("`[{}]` {}", path_str, err_msg)); + if let Some(link_range) = link_range { + if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) { + diag.set_span(sp); + diag.span_label(sp, short_err_msg); + } else { + // blah blah blah\nblah\nblah [blah] blah blah\nblah blah + // ^ ~~~~ + // | link_range + // last_new_line_offset + let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1); + let line = dox[last_new_line_offset..].lines().next().unwrap_or(""); + + // Print the line containing the `link_range` and manually mark it with '^'s. + diag.note(&format!( + "the link appears in this line:\n\n{line}\n\ + {indicator: >(); - match candidates.as_slice() { - [(first_def, _), (second_def, _)] => { - msg += &format!( - "both {} {} and {} {}", - first_def.article(), - first_def.descr(), - second_def.article(), - second_def.descr(), - ); - } - _ => { - let mut candidates = candidates.iter().peekable(); - while let Some((res, _)) = candidates.next() { - if candidates.peek().is_some() { - msg += &format!("{} {}, ", res.article(), res.descr()); - } else { - msg += &format!("and {} {}", res.article(), res.descr()); - } - } - } - } - - let mut diag = cx.tcx.struct_span_lint_hir( + cx.tcx.struct_span_lint_hir( lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, hir_id, sp, - &msg, - ); + |lint| { + let mut msg = format!("`{}` is ", path_str); - if let Some(link_range) = link_range { - if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) { - diag.set_span(sp); - diag.span_label(sp, "ambiguous link"); - - for (res, ns) in candidates { - let (action, mut suggestion) = match res { - Res::Def(DefKind::Method, _) | Res::Def(DefKind::Fn, _) => { - ("add parentheses", format!("{}()", path_str)) - } - Res::Def(DefKind::Macro(..), _) => { - ("add an exclamation mark", format!("{}!", path_str)) + let candidates = [TypeNS, ValueNS, MacroNS] + .iter() + .filter_map(|&ns| candidates[ns].map(|res| (res, ns))) + .collect::>(); + match candidates.as_slice() { + [(first_def, _), (second_def, _)] => { + msg += &format!( + "both {} {} and {} {}", + first_def.article(), + first_def.descr(), + second_def.article(), + second_def.descr(), + ); + } + _ => { + let mut candidates = candidates.iter().peekable(); + while let Some((res, _)) = candidates.next() { + if candidates.peek().is_some() { + msg += &format!("{} {}, ", res.article(), res.descr()); + } else { + msg += &format!("and {} {}", res.article(), res.descr()); + } } - _ => { - let type_ = match (res, ns) { - (Res::Def(DefKind::Const, _), _) => "const", - (Res::Def(DefKind::Static, _), _) => "static", - (Res::Def(DefKind::Struct, _), _) => "struct", - (Res::Def(DefKind::Enum, _), _) => "enum", - (Res::Def(DefKind::Union, _), _) => "union", - (Res::Def(DefKind::Trait, _), _) => "trait", - (Res::Def(DefKind::Mod, _), _) => "module", - (_, TypeNS) => "type", - (_, ValueNS) => "value", - (_, MacroNS) => "macro", + } + } + + let mut diag = lint.build(&msg); + + if let Some(link_range) = link_range { + if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) { + diag.set_span(sp); + diag.span_label(sp, "ambiguous link"); + + for (res, ns) in candidates { + let (action, mut suggestion) = match res { + Res::Def(DefKind::Method, _) | Res::Def(DefKind::Fn, _) => { + ("add parentheses", format!("{}()", path_str)) + } + Res::Def(DefKind::Macro(..), _) => { + ("add an exclamation mark", format!("{}!", path_str)) + } + _ => { + let type_ = match (res, ns) { + (Res::Def(DefKind::Const, _), _) => "const", + (Res::Def(DefKind::Static, _), _) => "static", + (Res::Def(DefKind::Struct, _), _) => "struct", + (Res::Def(DefKind::Enum, _), _) => "enum", + (Res::Def(DefKind::Union, _), _) => "union", + (Res::Def(DefKind::Trait, _), _) => "trait", + (Res::Def(DefKind::Mod, _), _) => "module", + (_, TypeNS) => "type", + (_, ValueNS) => "value", + (_, MacroNS) => "macro", + }; + + // FIXME: if this is an implied shortcut link, it's bad style to suggest `@` + ("prefix with the item type", format!("{}@{}", type_, path_str)) + } }; - // FIXME: if this is an implied shortcut link, it's bad style to suggest `@` - ("prefix with the item type", format!("{}@{}", type_, path_str)) - } - }; + if dox.bytes().nth(link_range.start) == Some(b'`') { + suggestion = format!("`{}`", suggestion); + } - if dox.bytes().nth(link_range.start) == Some(b'`') { - suggestion = format!("`{}`", suggestion); + diag.span_suggestion( + sp, + &format!("to link to the {}, {}", res.descr(), action), + suggestion, + Applicability::MaybeIncorrect, + ); + } + } else { + // blah blah blah\nblah\nblah [blah] blah blah\nblah blah + // ^ ~~~~ + // | link_range + // last_new_line_offset + let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1); + let line = dox[last_new_line_offset..].lines().next().unwrap_or(""); + + // Print the line containing the `link_range` and manually mark it with '^'s. + diag.note(&format!( + "the link appears in this line:\n\n{line}\n\ + {indicator: ( if check_missing_code == true && tests.found_tests == 0 { let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span()); - let mut diag = cx.tcx.struct_span_lint_hir( + cx.tcx.struct_span_lint_hir( lint::builtin::MISSING_DOC_CODE_EXAMPLES, hir_id, sp, - "missing code example in this documentation", + |lint| lint.build("missing code example in this documentation").emit(), ); - diag.emit(); } else if check_missing_code == false && tests.found_tests > 0 && !cx.renderinfo.borrow().access_levels.is_public(item.def_id) { - let mut diag = cx.tcx.struct_span_lint_hir( + cx.tcx.struct_span_lint_hir( lint::builtin::PRIVATE_DOC_TESTS, hir_id, span_of_attrs(&item.attrs).unwrap_or(item.source.span()), - "documentation test in private item", + |lint| lint.build("documentation test in private item").emit(), ); - diag.emit(); } } From 0df1ca3033cfbdb6d57966fa67be03dac5df07b3 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Sat, 1 Feb 2020 06:57:50 +1000 Subject: [PATCH 02/11] Box `decorate` to avoid code bloat. --- src/librustc/lint.rs | 226 +++++++++++++++++++++++-------------------- 1 file changed, 119 insertions(+), 107 deletions(-) diff --git a/src/librustc/lint.rs b/src/librustc/lint.rs index e7291d7a4ab0d..a9273fcb8acde 100644 --- a/src/librustc/lint.rs +++ b/src/librustc/lint.rs @@ -191,134 +191,146 @@ impl<'a> LintDiagnosticBuilder<'a> { } } -pub fn struct_lint_level<'s>( +pub fn struct_lint_level<'s, 'd>( sess: &'s Session, lint: &'static Lint, level: Level, src: LintSource, span: Option, - decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) { - - // FIXME: Move the guts of this function into a fn which takes dyn Fn to reduce code bloat. - let mut err = match (level, span) { - (Level::Allow, _) => { return; }, - (Level::Warn, Some(span)) => sess.struct_span_warn(span, ""), - (Level::Warn, None) => sess.struct_warn(""), - (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, ""), - (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(""), - }; + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>) + 'd, +) { + // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to + // the "real" work. + fn struct_lint_level_impl( + sess: &'s Session, + lint: &'static Lint, + level: Level, + src: LintSource, + span: Option, + decorate: Box FnOnce(LintDiagnosticBuilder<'b>) + 'd>) { + let mut err = match (level, span) { + (Level::Allow, _) => { + return; + } + (Level::Warn, Some(span)) => sess.struct_span_warn(span, ""), + (Level::Warn, None) => sess.struct_warn(""), + (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, ""), + (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(""), + }; - // Check for future incompatibility lints and issue a stronger warning. - let lint_id = LintId::of(lint); - let future_incompatible = lint.future_incompatible; - - // If this code originates in a foreign macro, aka something that this crate - // did not itself author, then it's likely that there's nothing this crate - // can do about it. We probably want to skip the lint entirely. - if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { - // Any suggestions made here are likely to be incorrect, so anything we - // emit shouldn't be automatically fixed by rustfix. - err.allow_suggestions(false); - - // If this is a future incompatible lint it'll become a hard error, so - // we have to emit *something*. Also allow lints to whitelist themselves - // on a case-by-case basis for emission in a foreign macro. - if future_incompatible.is_none() && !lint.report_in_external_macro { - err.cancel(); - // Don't continue further, since we don't want to have - // `diag_span_note_once` called for a diagnostic that isn't emitted. - return; + // Check for future incompatibility lints and issue a stronger warning. + let lint_id = LintId::of(lint); + let future_incompatible = lint.future_incompatible; + + // If this code originates in a foreign macro, aka something that this crate + // did not itself author, then it's likely that there's nothing this crate + // can do about it. We probably want to skip the lint entirely. + if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { + // Any suggestions made here are likely to be incorrect, so anything we + // emit shouldn't be automatically fixed by rustfix. + err.allow_suggestions(false); + + // If this is a future incompatible lint it'll become a hard error, so + // we have to emit *something*. Also allow lints to whitelist themselves + // on a case-by-case basis for emission in a foreign macro. + if future_incompatible.is_none() && !lint.report_in_external_macro { + err.cancel(); + // Don't continue further, since we don't want to have + // `diag_span_note_once` called for a diagnostic that isn't emitted. + return; + } } - } - let name = lint.name_lower(); - match src { - LintSource::Default => { - sess.diag_note_once( - &mut err, - DiagnosticMessageId::from(lint), - &format!("`#[{}({})]` on by default", level.as_str(), name), - ); - } - LintSource::CommandLine(lint_flag_val) => { - let flag = match level { - Level::Warn => "-W", - Level::Deny => "-D", - Level::Forbid => "-F", - Level::Allow => panic!(), - }; - let hyphen_case_lint_name = name.replace("_", "-"); - if lint_flag_val.as_str() == name { + let name = lint.name_lower(); + match src { + LintSource::Default => { sess.diag_note_once( &mut err, DiagnosticMessageId::from(lint), - &format!( - "requested on the command line with `{} {}`", - flag, hyphen_case_lint_name - ), - ); - } else { - let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); - sess.diag_note_once( - &mut err, - DiagnosticMessageId::from(lint), - &format!( - "`{} {}` implied by `{} {}`", - flag, hyphen_case_lint_name, flag, hyphen_case_flag_val - ), + &format!("`#[{}({})]` on by default", level.as_str(), name), ); } - } - LintSource::Node(lint_attr_name, src, reason) => { - if let Some(rationale) = reason { - err.note(&rationale.as_str()); + LintSource::CommandLine(lint_flag_val) => { + let flag = match level { + Level::Warn => "-W", + Level::Deny => "-D", + Level::Forbid => "-F", + Level::Allow => panic!(), + }; + let hyphen_case_lint_name = name.replace("_", "-"); + if lint_flag_val.as_str() == name { + sess.diag_note_once( + &mut err, + DiagnosticMessageId::from(lint), + &format!( + "requested on the command line with `{} {}`", + flag, hyphen_case_lint_name + ), + ); + } else { + let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); + sess.diag_note_once( + &mut err, + DiagnosticMessageId::from(lint), + &format!( + "`{} {}` implied by `{} {}`", + flag, hyphen_case_lint_name, flag, hyphen_case_flag_val + ), + ); + } } - sess.diag_span_note_once( - &mut err, - DiagnosticMessageId::from(lint), - src, - "the lint level is defined here", - ); - if lint_attr_name.as_str() != name { - let level_str = level.as_str(); - sess.diag_note_once( + LintSource::Node(lint_attr_name, src, reason) => { + if let Some(rationale) = reason { + err.note(&rationale.as_str()); + } + sess.diag_span_note_once( &mut err, DiagnosticMessageId::from(lint), - &format!( - "`#[{}({})]` implied by `#[{}({})]`", - level_str, name, level_str, lint_attr_name - ), + src, + "the lint level is defined here", ); + if lint_attr_name.as_str() != name { + let level_str = level.as_str(); + sess.diag_note_once( + &mut err, + DiagnosticMessageId::from(lint), + &format!( + "`#[{}({})]` implied by `#[{}({})]`", + level_str, name, level_str, lint_attr_name + ), + ); + } } } - } - err.code(DiagnosticId::Lint(name)); - - if let Some(future_incompatible) = future_incompatible { - const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \ - it will become a hard error"; - - let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) { - "once this method is added to the standard library, \ - the ambiguity may cause an error or change in behavior!" - .to_owned() - } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) { - "this borrowing pattern was not meant to be accepted, \ - and may become a hard error in the future" - .to_owned() - } else if let Some(edition) = future_incompatible.edition { - format!("{} in the {} edition!", STANDARD_MESSAGE, edition) - } else { - format!("{} in a future release!", STANDARD_MESSAGE) - }; - let citation = format!("for more information, see {}", future_incompatible.reference); - err.warn(&explanation); - err.note(&citation); - } + err.code(DiagnosticId::Lint(name)); + + if let Some(future_incompatible) = future_incompatible { + const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \ + it will become a hard error"; + + let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) { + "once this method is added to the standard library, \ + the ambiguity may cause an error or change in behavior!" + .to_owned() + } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) { + "this borrowing pattern was not meant to be accepted, \ + and may become a hard error in the future" + .to_owned() + } else if let Some(edition) = future_incompatible.edition { + format!("{} in the {} edition!", STANDARD_MESSAGE, edition) + } else { + format!("{} in a future release!", STANDARD_MESSAGE) + }; + let citation = format!("for more information, see {}", future_incompatible.reference); + err.warn(&explanation); + err.note(&citation); + } - // Finally, run `decorate`. This function is also responsible for emitting the diagnostic. - decorate(LintDiagnosticBuilder::new(err)); + // Finally, run `decorate`. This function is also responsible for emitting the diagnostic. + decorate(LintDiagnosticBuilder::new(err)); + } + struct_lint_level_impl(sess, lint, level, src, span, Box::new(decorate)) } /// Returns whether `span` originates in a foreign crate's external macro. From 0634a5007306f3951ec28c0b9986452a91eebda8 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Sat, 1 Feb 2020 13:27:05 +1000 Subject: [PATCH 03/11] Also check for "use fully-qualified syntax". --- .../enum-variant-priority-lint-ambiguous_associated_items.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs index 7f69590400b3c..5f3b711b31aa9 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs +++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs @@ -32,6 +32,7 @@ impl Tr for E { fn f() -> Self::V { 0 } //~^ ERROR ambiguous associated item //~| WARN this was previously accepted + //~| HELP use fully-qualified syntax } fn main() {} From d246385122ffd7dd6cc5c490b7e648f58c2ff7fd Mon Sep 17 00:00:00 2001 From: jumbatm Date: Sun, 2 Feb 2020 09:47:58 +1000 Subject: [PATCH 04/11] Run RustFmt --- src/librustc/lint.rs | 11 +- src/librustc/mir/interpret/error.rs | 17 +- src/librustc/traits/object_safety.rs | 12 +- src/librustc/traits/specialize/mod.rs | 10 +- src/librustc/ty/context.rs | 4 +- src/librustc_attr/builtin.rs | 4 +- src/librustc_errors/diagnostic_builder.rs | 6 +- src/librustc_expand/base.rs | 6 +- src/librustc_lint/builtin.rs | 298 ++++++++---------- src/librustc_lint/context.rs | 11 +- src/librustc_lint/internal.rs | 69 ++-- src/librustc_lint/levels.rs | 17 +- src/librustc_lint/non_ascii_idents.rs | 16 +- src/librustc_lint/nonstandard_style.rs | 29 +- src/librustc_lint/types.rs | 95 +++--- src/librustc_mir/borrow_check/mod.rs | 11 +- src/librustc_mir/const_eval/eval_queries.rs | 4 +- src/librustc_mir/transform/check_unsafety.rs | 12 +- src/librustc_mir/transform/const_prop.rs | 15 +- .../hair/pattern/check_match.rs | 42 ++- src/librustc_mir_build/lints.rs | 25 +- src/librustc_parse/config.rs | 6 +- src/librustc_parse/parser/mod.rs | 4 +- src/librustc_parse/validate_attr.rs | 10 +- src/librustc_passes/check_attr.rs | 31 +- src/librustc_passes/liveness.rs | 72 ++--- src/librustc_passes/stability.rs | 8 +- src/librustc_privacy/lib.rs | 24 +- src/librustc_resolve/lifetimes.rs | 19 +- src/librustc_typeck/check/cast.rs | 33 +- src/librustc_typeck/check/method/probe.rs | 4 +- src/librustc_typeck/check/mod.rs | 22 +- src/librustc_typeck/check_unused.rs | 1 - src/librustc_typeck/collect.rs | 5 +- .../passes/collect_intra_doc_links.rs | 13 +- src/librustdoc/passes/mod.rs | 9 +- 36 files changed, 476 insertions(+), 499 deletions(-) diff --git a/src/librustc/lint.rs b/src/librustc/lint.rs index a9273fcb8acde..004835b230ab4 100644 --- a/src/librustc/lint.rs +++ b/src/librustc/lint.rs @@ -11,7 +11,6 @@ use rustc_span::hygiene::MacroKind; use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan}; use rustc_span::{Span, Symbol}; - /// How a lint level was set. #[derive(Clone, Copy, PartialEq, Eq, HashStable)] pub enum LintSource { @@ -175,7 +174,6 @@ impl<'a> HashStable> for LintLevelMap { } } - pub struct LintDiagnosticBuilder<'a>(DiagnosticBuilder<'a>); impl<'a> LintDiagnosticBuilder<'a> { @@ -186,7 +184,7 @@ impl<'a> LintDiagnosticBuilder<'a> { } /// Create a LintDiagnosticBuilder from some existing DiagnosticBuilder. - pub fn new(err: DiagnosticBuilder<'a>) -> LintDiagnosticBuilder<'a>{ + pub fn new(err: DiagnosticBuilder<'a>) -> LintDiagnosticBuilder<'a> { LintDiagnosticBuilder(err) } } @@ -207,14 +205,17 @@ pub fn struct_lint_level<'s, 'd>( level: Level, src: LintSource, span: Option, - decorate: Box FnOnce(LintDiagnosticBuilder<'b>) + 'd>) { + decorate: Box FnOnce(LintDiagnosticBuilder<'b>) + 'd>, + ) { let mut err = match (level, span) { (Level::Allow, _) => { return; } (Level::Warn, Some(span)) => sess.struct_span_warn(span, ""), (Level::Warn, None) => sess.struct_warn(""), - (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, ""), + (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => { + sess.struct_span_err(span, "") + } (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(""), }; diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index bb84458cf7b0b..df3971a5ac3f1 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -120,19 +120,18 @@ impl<'tcx> ConstEvalErr<'tcx> { } } lint.emit(); - } - , Some(lint_root)) { - Ok(_) => { - ErrorHandled::Reported - } + }, + Some(lint_root), + ) { + Ok(_) => ErrorHandled::Reported, Err(err) => err, } } - /// Sets the message passed in via `message`, then adds the span labels for you, before applying - /// further modifications in `emit`. It's up to you to call emit(), stash(..), etc. within the - /// `emit` method. If you don't need to do any additional processing, just use - /// struct_generic. + /// Sets the message passed in via `message`, then adds the span labels for you, before applying + /// further modifications in `emit`. It's up to you to call emit(), stash(..), etc. within the + /// `emit` method. If you don't need to do any additional processing, just use + /// struct_generic. fn struct_generic( &self, tcx: TyCtxtAt<'tcx>, diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 0e6347897d2ba..4c5cd866b4a01 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -238,7 +238,10 @@ fn object_safety_violations_for_trait( )); let node = tcx.hir().get_if_local(trait_def_id); let msg = if let Some(hir::Node::Item(item)) = node { - err.span_label(item.ident.span, "this trait cannot be made into an object..."); + err.span_label( + item.ident.span, + "this trait cannot be made into an object...", + ); format!("...because {}", violation.error_msg()) } else { format!( @@ -252,7 +255,12 @@ fn object_safety_violations_for_trait( err.help(¬e); } (Some(_), Some((note, Some((sugg, span))))) => { - err.span_suggestion(span, ¬e, sugg, Applicability::MachineApplicable); + err.span_suggestion( + span, + ¬e, + sugg, + Applicability::MachineApplicable, + ); } // Only provide the help if its a local trait, otherwise it's not actionable. _ => {} diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 33a78ae896b35..7c93a35158b08 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -16,13 +16,13 @@ use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; use crate::ty::subst::{InternalSubsts, Subst, SubstsRef}; use crate::ty::{self, TyCtxt, TypeFoldable}; +use rustc::lint::LintDiagnosticBuilder; use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir::def_id::DefId; use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK; use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS; use rustc_span::DUMMY_SP; -use rustc::lint::LintDiagnosticBuilder; use super::util::impl_trait_ref_and_oblig; use super::{FulfillmentContext, SelectionContext}; @@ -357,9 +357,10 @@ pub(super) fn specialization_graph_provider( } Err(cname) => { let msg = match to_pretty_impl_header(tcx, overlap.with_impl) { - Some(s) => { - format!("conflicting implementation in crate `{}`:\n- {}", cname, s) - } + Some(s) => format!( + "conflicting implementation in crate `{}`:\n- {}", + cname, s + ), None => format!("conflicting implementation in crate `{}`", cname), }; err.note(&msg); @@ -396,7 +397,6 @@ pub(super) fn specialization_graph_provider( ) } }; - } } else { let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a885f9e960093..f2ad01b3d5961 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -41,8 +41,8 @@ use crate::ty::{ExistentialPredicate, InferTy, ParamTy, PolyFnSig, Predicate, Pr use crate::ty::{InferConst, ParamConst}; use crate::ty::{List, TyKind, TyS}; use crate::util::common::ErrorReported; -use rustc_attr as attr; use rustc::lint::LintDiagnosticBuilder; +use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; @@ -2594,7 +2594,7 @@ impl<'tcx> TyCtxt<'tcx> { lint: &'static Lint, hir_id: HirId, span: impl Into, - decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>) + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), ) { let (level, src) = self.lint_level_at_node(lint, hir_id); struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate); diff --git a/src/librustc_attr/builtin.rs b/src/librustc_attr/builtin.rs index e5381a58dab55..3c13735bbf41f 100644 --- a/src/librustc_attr/builtin.rs +++ b/src/librustc_attr/builtin.rs @@ -37,7 +37,9 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) { .span_label(span, format!("expected one of {}", expected.join(", "))) .emit(); } - AttrError::MissingSince => { struct_span_err!(diag, span, E0542, "missing 'since'").emit(); }, + AttrError::MissingSince => { + struct_span_err!(diag, span, E0542, "missing 'since'").emit(); + } AttrError::MissingFeature => { struct_span_err!(diag, span, E0546, "missing 'feature'").emit(); } diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 84bfa07d267da..39f585231eea4 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -106,7 +106,11 @@ impl<'a> DiagnosticBuilder<'a> { /// /// See `emit` and `delay_as_bug` for details. pub fn emit_unless(&mut self, delay: bool) { - if delay { self.delay_as_bug(); } else { self.emit(); } + if delay { + self.delay_as_bug(); + } else { + self.emit(); + } } /// Stashes diagnostic for possible later improvement in a different, diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index 9e583d7e19d79..a5614f900b6fb 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -1113,7 +1113,11 @@ pub fn expr_to_string( err_msg: &str, ) -> Option<(Symbol, ast::StrStyle)> { expr_to_spanned_string(cx, expr, err_msg) - .map_err(|err| err.map(|mut err| { err.emit(); })) + .map_err(|err| { + err.map(|mut err| { + err.emit(); + }) + }) .ok() .map(|(symbol, style, _)| (symbol, style)) } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index e84ef713b42d3..9fc81a4a1fdaf 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -80,12 +80,12 @@ impl EarlyLintPass for WhileTrue { cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| { lint.build(msg) .span_suggestion_short( - condition_span, - "use `loop`", - "loop".to_owned(), - Applicability::MachineApplicable, - ) - .emit(); + condition_span, + "use `loop`", + "loop".to_owned(), + Applicability::MachineApplicable, + ) + .emit(); }) } } @@ -176,31 +176,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns { if cx.tcx.find_field_index(ident, &variant) == Some(cx.tcx.field_index(fieldpat.hir_id, cx.tables)) { - cx.struct_span_lint( - NON_SHORTHAND_FIELD_PATTERNS, - fieldpat.span, - |lint| { - let mut err = lint.build(&format!("the `{}:` in this pattern is redundant", ident)); - let binding = match binding_annot { - hir::BindingAnnotation::Unannotated => None, - hir::BindingAnnotation::Mutable => Some("mut"), - hir::BindingAnnotation::Ref => Some("ref"), - hir::BindingAnnotation::RefMut => Some("ref mut"), - }; - let ident = if let Some(binding) = binding { - format!("{} {}", binding, ident) - } else { - ident.to_string() - }; - err.span_suggestion( - fieldpat.span, - "use shorthand field pattern", - ident, - Applicability::MachineApplicable, - ); - err.emit(); - } - ); + cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, |lint| { + let mut err = lint + .build(&format!("the `{}:` in this pattern is redundant", ident)); + let binding = match binding_annot { + hir::BindingAnnotation::Unannotated => None, + hir::BindingAnnotation::Mutable => Some("mut"), + hir::BindingAnnotation::Ref => Some("ref"), + hir::BindingAnnotation::RefMut => Some("ref mut"), + }; + let ident = if let Some(binding) = binding { + format!("{} {}", binding, ident) + } else { + ident.to_string() + }; + err.span_suggestion( + fieldpat.span, + "use shorthand field pattern", + ident, + Applicability::MachineApplicable, + ); + err.emit(); + }); } } } @@ -644,22 +641,20 @@ impl EarlyLintPass for AnonymousParameters { ("".to_owned(), Applicability::HasPlaceholders) }; - cx.struct_span_lint( - ANONYMOUS_PARAMETERS, - arg.pat.span, - |lint| { - lint.build("anonymous parameters are deprecated and will be \ - removed in the next edition.") - .span_suggestion( - arg.pat.span, - "try naming the parameter or explicitly \ + cx.struct_span_lint(ANONYMOUS_PARAMETERS, arg.pat.span, |lint| { + lint.build( + "anonymous parameters are deprecated and will be \ + removed in the next edition.", + ) + .span_suggestion( + arg.pat.span, + "try naming the parameter or explicitly \ ignoring it", - format!("_: {}", ty_snip), - appl, - ) - .emit(); - }, - ) + format!("_: {}", ty_snip), + appl, + ) + .emit(); + }) } } _ => (), @@ -838,22 +833,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { match param.kind { GenericParamKind::Lifetime { .. } => {} GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - cx.struct_span_lint( - NO_MANGLE_GENERIC_ITEMS, - it.span, - |lint| { - lint.build("functions generic over types or consts must be mangled") - .span_suggestion_short( - no_mangle_attr.span, - "remove this attribute", - String::new(), - // Use of `#[no_mangle]` suggests FFI intent; correct - // fix may be to monomorphize source by hand - Applicability::MaybeIncorrect, - ) - .emit(); - }, - ); + cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, it.span, |lint| { + lint.build( + "functions generic over types or consts must be mangled", + ) + .span_suggestion_short( + no_mangle_attr.span, + "remove this attribute", + String::new(), + // Use of `#[no_mangle]` suggests FFI intent; correct + // fix may be to monomorphize source by hand + Applicability::MaybeIncorrect, + ) + .emit(); + }); break; } } @@ -995,30 +988,26 @@ impl UnreachablePub { applicability = Applicability::MaybeIncorrect; } let def_span = cx.tcx.sess.source_map().def_span(span); - cx.struct_span_lint( - UNREACHABLE_PUB, - def_span, - |lint| { - let mut err = lint.build(&format!("unreachable `pub` {}", what)); - let replacement = if cx.tcx.features().crate_visibility_modifier { - "crate" - } else { - "pub(crate)" - } - .to_owned(); + cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| { + let mut err = lint.build(&format!("unreachable `pub` {}", what)); + let replacement = if cx.tcx.features().crate_visibility_modifier { + "crate" + } else { + "pub(crate)" + } + .to_owned(); - err.span_suggestion( - vis.span, - "consider restricting its visibility", - replacement, - applicability, - ); - if exportable { - err.help("or consider exporting it for use by other crates"); - } - err.emit(); + err.span_suggestion( + vis.span, + "consider restricting its visibility", + replacement, + applicability, + ); + if exportable { + err.help("or consider exporting it for use by other crates"); } - ); + err.emit(); + }); } _ => {} } @@ -1163,21 +1152,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { }) .collect(); if !spans.is_empty() { - cx.struct_span_lint( - TYPE_ALIAS_BOUNDS, - spans, - |lint| { - let mut err = lint.build("bounds on generic parameters are not enforced in type aliases"); - let msg = "the bound will not be checked when the type alias is used, \ + cx.struct_span_lint(TYPE_ALIAS_BOUNDS, spans, |lint| { + let mut err = + lint.build("bounds on generic parameters are not enforced in type aliases"); + let msg = "the bound will not be checked when the type alias is used, \ and should be removed"; - err.multipart_suggestion(&msg, suggestion, Applicability::MachineApplicable); - if !suggested_changing_assoc_types { - TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); - suggested_changing_assoc_types = true; - } - err.emit(); - }, - ); + err.multipart_suggestion(&msg, suggestion, Applicability::MachineApplicable); + if !suggested_changing_assoc_types { + TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); + suggested_changing_assoc_types = true; + } + err.emit(); + }); } } } @@ -1356,7 +1342,7 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { join, suggestion, "..=".to_owned(), - Applicability::MachineApplicable + Applicability::MachineApplicable, ) .emit(); }); @@ -1405,7 +1391,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems { } if let Some(attr) = attr::find_by_name(&it.attrs, sym::rustc_test_marker) { - cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| lint.build("cannot test inner items").emit()); + cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| { + lint.build("cannot test inner items").emit() + }); } } @@ -1486,20 +1474,16 @@ impl KeywordIdents { return; } - cx.struct_span_lint( - KEYWORD_IDENTS, - ident.span, - |lint| { - lint.build(&format!("`{}` is a keyword in the {} edition", ident, next_edition)) - .span_suggestion( - ident.span, - "you can use a raw identifier to stay compatible", - format!("r#{}", ident), - Applicability::MachineApplicable, - ) - .emit() - }, - ); + cx.struct_span_lint(KEYWORD_IDENTS, ident.span, |lint| { + lint.build(&format!("`{}` is a keyword in the {} edition", ident, next_edition)) + .span_suggestion( + ident.span, + "you can use a raw identifier to stay compatible", + format!("r#{}", ident), + Applicability::MachineApplicable, + ) + .emit() + }); } } @@ -1803,19 +1787,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements { } if !lint_spans.is_empty() { - cx.struct_span_lint( - EXPLICIT_OUTLIVES_REQUIREMENTS, - lint_spans.clone(), - |lint| { - lint.build("outlives requirements can be inferred") - .multipart_suggestion( - if bound_count == 1 { "remove this bound" } else { "remove these bounds" }, - lint_spans.into_iter().map(|span| (span, "".to_owned())).collect::>(), - Applicability::MachineApplicable, - ) - .emit(); - }, - ); + cx.struct_span_lint(EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), |lint| { + lint.build("outlives requirements can be inferred") + .multipart_suggestion( + if bound_count == 1 { + "remove this bound" + } else { + "remove these bounds" + }, + lint_spans + .into_iter() + .map(|span| (span, "".to_owned())) + .collect::>(), + Applicability::MachineApplicable, + ) + .emit(); + }); } } } @@ -1842,14 +1829,13 @@ impl EarlyLintPass for IncompleteFeatures { .chain(features.declared_lib_features.iter().map(|(name, span)| (name, span))) .filter(|(name, _)| rustc_feature::INCOMPLETE_FEATURES.iter().any(|f| name == &f)) .for_each(|(name, &span)| { - cx.struct_span_lint( - INCOMPLETE_FEATURES, - span, - |lint| lint.build(&format!( + cx.struct_span_lint(INCOMPLETE_FEATURES, span, |lint| { + lint.build(&format!( "the feature `{}` is incomplete and may cause the compiler to crash", name, - )).emit(), - ) + )) + .emit() + }) }); } } @@ -2039,32 +2025,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { // We are extremely conservative with what we warn about. let conjured_ty = cx.tables.expr_ty(expr); if let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty, init) { - cx.struct_span_lint( - INVALID_VALUE, - expr.span, - |lint| { - let mut err = lint.build(&format!( - "the type `{}` does not permit {}", - conjured_ty, - match init { - InitKind::Zeroed => "zero-initialization", - InitKind::Uninit => "being left uninitialized", - }, - )); - err.span_label(expr.span, "this code causes undefined behavior when executed"); - err.span_label( - expr.span, - "help: use `MaybeUninit` instead, \ + cx.struct_span_lint(INVALID_VALUE, expr.span, |lint| { + let mut err = lint.build(&format!( + "the type `{}` does not permit {}", + conjured_ty, + match init { + InitKind::Zeroed => "zero-initialization", + InitKind::Uninit => "being left uninitialized", + }, + )); + err.span_label(expr.span, "this code causes undefined behavior when executed"); + err.span_label( + expr.span, + "help: use `MaybeUninit` instead, \ and only call `assume_init` after initialization is done", - ); - if let Some(span) = span { - err.span_note(span, &msg); - } else { - err.note(&msg); - } - err.emit(); - }, - ); + ); + if let Some(span) = span { + err.span_note(span, &msg); + } else { + err.note(&msg); + } + err.emit(); + }); } } } diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs index 7b085f6c2b3d4..d9ad97654e04b 100644 --- a/src/librustc_lint/context.rs +++ b/src/librustc_lint/context.rs @@ -20,6 +20,7 @@ use crate::levels::LintLevelsBuilder; use crate::passes::{EarlyLintPassObject, LateLintPassObject}; use rustc::hir::map::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc::lint::add_elided_lifetime_in_path_suggestion; +use rustc::lint::LintDiagnosticBuilder; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; use rustc::ty::layout::{LayoutError, LayoutOf, TyLayout}; @@ -27,7 +28,6 @@ use rustc::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync; use rustc_errors::{struct_span_err, Applicability}; -use rustc::lint::LintDiagnosticBuilder; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_session::lint::BuiltinLintDiagnostics; @@ -505,7 +505,8 @@ pub trait LintContext: Sized { Ok(ref s) => { // FIXME(Manishearth) ideally the emitting code // can tell us whether or not this is global - let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" }; + let opt_colon = + if s.trim_start().starts_with("::") { "" } else { "::" }; (format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable) } @@ -519,7 +520,9 @@ pub trait LintContext: Sized { "names from parent modules are not accessible without an explicit import", ); } - BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => { + BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths( + span_def, + ) => { db.span_note(span_def, "the macro is defined here"); } BuiltinLintDiagnostics::ElidedLifetimesInPaths( @@ -585,7 +588,7 @@ pub trait LintContext: Sized { &self, lint: &'static Lint, span: S, - decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>) + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), ) { self.lookup(lint, Some(span), decorate); } diff --git a/src/librustc_lint/internal.rs b/src/librustc_lint/internal.rs index 19778a044a498..79a06e81410d0 100644 --- a/src/librustc_lint/internal.rs +++ b/src/librustc_lint/internal.rs @@ -47,7 +47,10 @@ impl EarlyLintPass for DefaultHashTypes { replace.to_string(), Applicability::MaybeIncorrect, // FxHashMap, ... needs another import ) - .note(&format!("a `use rustc_data_structures::fx::{}` may be necessary", replace)) + .note(&format!( + "a `use rustc_data_structures::fx::{}` may be necessary", + replace + )) .emit(); }); } @@ -90,13 +93,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { if lint_ty_kind_usage(cx, last) { cx.struct_span_lint(USAGE_OF_TY_TYKIND, span, |lint| { lint.build("usage of `ty::TyKind::`") - .span_suggestion( - span, - "try using ty:: directly", - "ty".to_string(), - Applicability::MaybeIncorrect, // ty maybe needs an import - ) - .emit(); + .span_suggestion( + span, + "try using ty:: directly", + "ty".to_string(), + Applicability::MaybeIncorrect, // ty maybe needs an import + ) + .emit(); }) } } @@ -108,36 +111,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { if let QPath::Resolved(_, path) = qpath { if let Some(last) = path.segments.iter().last() { if lint_ty_kind_usage(cx, last) { - cx.struct_span_lint( - USAGE_OF_TY_TYKIND, - path.span, - |lint| { - lint.build("usage of `ty::TyKind`") - .help("try using `Ty` instead") - .emit(); - }, - ) + cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| { + lint.build("usage of `ty::TyKind`") + .help("try using `Ty` instead") + .emit(); + }) } else { if ty.span.from_expansion() { return; } if let Some(t) = is_ty_or_ty_ctxt(cx, ty) { if path.segments.len() > 1 { - cx.struct_span_lint( - USAGE_OF_QUALIFIED_TY, - path.span, - |lint| { - lint.build(&format!("usage of qualified `ty::{}`", t)) - .span_suggestion( - path.span, - "try using it unqualified", - t, - // The import probably needs to be changed - Applicability::MaybeIncorrect, - ) - .emit(); - }, - ) + cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| { + lint.build(&format!("usage of qualified `ty::{}`", t)) + .span_suggestion( + path.span, + "try using it unqualified", + t, + // The import probably needs to be changed + Applicability::MaybeIncorrect, + ) + .emit(); + }) } } } @@ -151,11 +146,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { } } if let Some(t) = is_ty_or_ty_ctxt(cx, &inner_ty) { - cx.struct_span_lint( - TY_PASS_BY_REFERENCE, - ty.span, - |lint| { - lint.build(&format!("passing `{}` by reference", t)) + cx.struct_span_lint(TY_PASS_BY_REFERENCE, ty.span, |lint| { + lint.build(&format!("passing `{}` by reference", t)) .span_suggestion( ty.span, "try passing by value", @@ -164,8 +156,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { Applicability::MaybeIncorrect, ) .emit(); - }, - ) + }) } } _ => {} diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs index 6dd899d146182..b58acac316ef2 100644 --- a/src/librustc_lint/levels.rs +++ b/src/librustc_lint/levels.rs @@ -1,13 +1,13 @@ use crate::context::{CheckLintNameResult, LintStore}; use crate::late::unerased_lint_store; use rustc::hir::map::Map; +use rustc::lint::LintDiagnosticBuilder; use rustc::lint::{struct_lint_level, LintLevelMap, LintLevelSets, LintSet, LintSource}; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{struct_span_err, Applicability}; -use rustc::lint::LintDiagnosticBuilder; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::{intravisit, HirId}; @@ -248,13 +248,13 @@ impl<'s> LintLevelsBuilder<'s> { Some(li.span().into()), |lint| { lint.build(&msg) - .span_suggestion( - li.span(), - "change it to", - new_lint_name.to_string(), - Applicability::MachineApplicable, - ) - .emit(); + .span_suggestion( + li.span(), + "change it to", + new_lint_name.to_string(), + Applicability::MachineApplicable, + ) + .emit(); }, ); @@ -326,7 +326,6 @@ impl<'s> LintLevelsBuilder<'s> { db.emit(); }, ); - } } } diff --git a/src/librustc_lint/non_ascii_idents.rs b/src/librustc_lint/non_ascii_idents.rs index df91df8f8b594..a0ca7ad1860e8 100644 --- a/src/librustc_lint/non_ascii_idents.rs +++ b/src/librustc_lint/non_ascii_idents.rs @@ -22,17 +22,13 @@ impl EarlyLintPass for NonAsciiIdents { if name_str.is_ascii() { return; } - cx.struct_span_lint( - NON_ASCII_IDENTS, - ident.span, - |lint| lint.build("identifier contains non-ASCII characters").emit(), - ); + cx.struct_span_lint(NON_ASCII_IDENTS, ident.span, |lint| { + lint.build("identifier contains non-ASCII characters").emit() + }); if !name_str.chars().all(GeneralSecurityProfile::identifier_allowed) { - cx.struct_span_lint( - UNCOMMON_CODEPOINTS, - ident.span, - |lint| lint.build("identifier contains uncommon Unicode codepoints").emit(), - ) + cx.struct_span_lint(UNCOMMON_CODEPOINTS, ident.span, |lint| { + lint.build("identifier contains uncommon Unicode codepoints").emit() + }) } } } diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 9e291d2cb74e7..52f29b30f3be9 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -109,12 +109,14 @@ impl NonCamelCaseTypes { if !is_camel_case(name) { let msg = format!("{} `{}` should have an upper camel case name", sort, name); cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, |lint| { - lint.build(&msg).span_suggestion( - ident.span, - "convert the identifier to upper camel case", - to_camel_case(name), - Applicability::MaybeIncorrect, - ).emit() + lint.build(&msg) + .span_suggestion( + ident.span, + "convert the identifier to upper camel case", + to_camel_case(name), + Applicability::MaybeIncorrect, + ) + .emit() }) } } @@ -243,7 +245,6 @@ impl NonSnakeCase { err.emit(); }); - } } } @@ -394,13 +395,13 @@ impl NonUpperCaseGlobals { cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| { lint.build(&format!("{} `{}` should have an upper case name", sort, name)) - .span_suggestion( - ident.span, - "convert the identifier to upper case", - uc, - Applicability::MaybeIncorrect, - ) - .emit(); + .span_suggestion( + ident.span, + "convert the identifier to upper case", + uc, + Applicability::MaybeIncorrect, + ) + .emit(); }) } } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 30a903a2a30d2..71a86592396c9 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -76,33 +76,29 @@ fn lint_overflowing_range_endpoint<'a, 'tcx>( // (`..=`) instead only if it is the `end` that is // overflowing and only by 1. if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max { - cx.struct_span_lint( - OVERFLOWING_LITERALS, - parent_expr.span, - |lint| { - let mut err = lint.build(&format!("range endpoint is out of range for `{}`", ty)); - if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) { - use ast::{LitIntType, LitKind}; - // We need to preserve the literal's suffix, - // as it may determine typing information. - let suffix = match lit.node { - LitKind::Int(_, LitIntType::Signed(s)) => format!("{}", s.name_str()), - LitKind::Int(_, LitIntType::Unsigned(s)) => format!("{}", s.name_str()), - LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(), - _ => bug!(), - }; - let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix); - err.span_suggestion( - parent_expr.span, - &"use an inclusive range instead", - suggestion, - Applicability::MachineApplicable, - ); - err.emit(); - overwritten = true; - } - }, - ); + cx.struct_span_lint(OVERFLOWING_LITERALS, parent_expr.span, |lint| { + let mut err = lint.build(&format!("range endpoint is out of range for `{}`", ty)); + if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) { + use ast::{LitIntType, LitKind}; + // We need to preserve the literal's suffix, + // as it may determine typing information. + let suffix = match lit.node { + LitKind::Int(_, LitIntType::Signed(s)) => format!("{}", s.name_str()), + LitKind::Int(_, LitIntType::Unsigned(s)) => format!("{}", s.name_str()), + LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(), + _ => bug!(), + }; + let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix); + err.span_suggestion( + parent_expr.span, + &"use an inclusive range instead", + suggestion, + Applicability::MachineApplicable, + ); + err.emit(); + overwritten = true; + } + }); } } overwritten @@ -165,32 +161,29 @@ fn report_bin_hex_error( (t.name_str(), actually.to_string()) } }; - cx.struct_span_lint( - OVERFLOWING_LITERALS, - expr.span, - |lint| { - let mut err = lint.build(&format!("literal out of range for {}", t)); - err.note(&format!( - "the literal `{}` (decimal `{}`) does not fit into \ + cx.struct_span_lint(OVERFLOWING_LITERALS, expr.span, |lint| { + let mut err = lint.build(&format!("literal out of range for {}", t)); + err.note(&format!( + "the literal `{}` (decimal `{}`) does not fit into \ an `{}` and will become `{}{}`", - repr_str, val, t, actually, t - )); - if let Some(sugg_ty) = get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative) { - if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { - let (sans_suffix, _) = repr_str.split_at(pos); - err.span_suggestion( - expr.span, - &format!("consider using `{}` instead", sugg_ty), - format!("{}{}", sans_suffix, sugg_ty), - Applicability::MachineApplicable, - ); - } else { - err.help(&format!("consider using `{}` instead", sugg_ty)); - } + repr_str, val, t, actually, t + )); + if let Some(sugg_ty) = get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative) + { + if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { + let (sans_suffix, _) = repr_str.split_at(pos); + err.span_suggestion( + expr.span, + &format!("consider using `{}` instead", sugg_ty), + format!("{}{}", sans_suffix, sugg_ty), + Applicability::MachineApplicable, + ); + } else { + err.help(&format!("consider using `{}` instead", sugg_ty)); } - err.emit(); - }, - ); + } + err.emit(); + }); } // This function finds the next fitting type and generates a suggestion string. diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 25f1a495ad3e4..4dae7fbe9413d 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -379,12 +379,8 @@ fn do_mir_borrowck<'a, 'tcx>( } let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); - tcx.struct_span_lint_hir( - UNUSED_MUT, - lint_root, - span, - |lint| { - lint.build("variable does not need to be mutable") + tcx.struct_span_lint_hir(UNUSED_MUT, lint_root, span, |lint| { + lint.build("variable does not need to be mutable") .span_suggestion_short( mut_span, "remove this `mut`", @@ -392,8 +388,7 @@ fn do_mir_borrowck<'a, 'tcx>( Applicability::MachineApplicable, ) .emit(); - }, - ) + }) } // Buffer any move errors that we collected and de-duplicated. diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 99d3b281945eb..2e8e4dac237bc 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -213,9 +213,7 @@ fn validate_and_turn_into_const<'tcx>( diag.note(note_on_undefined_behavior_error()); diag.emit(); }) { - Ok(_) => { - ErrorHandled::Reported - } + Ok(_) => ErrorHandled::Reported, Err(err) => err, } }) diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index c019fa57fb783..08ef60aa58ea5 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -624,15 +624,13 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) { lint_hir_id, source_info.span, |lint| { - lint.build( - &format!( - "{} is unsafe and requires unsafe function or block (error E0133)", - description - ) - ) + lint.build(&format!( + "{} is unsafe and requires unsafe function or block (error E0133)", + description + )) .note(&details.as_str()) .emit() - } + }, ) } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index aeeca52ba3ba2..9a2e2c56f1426 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -923,17 +923,24 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { | PanicInfo::DivisionByZero | PanicInfo::RemainderByZero => msg.description().to_owned(), PanicInfo::BoundsCheck { ref len, ref index } => { - let len = - self.eval_operand(len, source_info).expect("len must be const"); + let len = self + .eval_operand(len, source_info) + .expect("len must be const"); let len = match self.ecx.read_scalar(len) { - Ok(ScalarMaybeUndef::Scalar(Scalar::Raw { data, .. })) => data, + Ok(ScalarMaybeUndef::Scalar(Scalar::Raw { + data, + .. + })) => data, other => bug!("const len not primitive: {:?}", other), }; let index = self .eval_operand(index, source_info) .expect("index must be const"); let index = match self.ecx.read_scalar(index) { - Ok(ScalarMaybeUndef::Scalar(Scalar::Raw { data, .. })) => data, + Ok(ScalarMaybeUndef::Scalar(Scalar::Raw { + data, + .. + })) => data, other => bug!("const index not primitive: {:?}", other), }; format!( diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index 421f7958e5f49..acb9829ce5f37 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -287,30 +287,26 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa }) { let ty_path = cx.tcx.def_path_str(edef.did); - cx.tcx - .struct_span_lint_hir( - BINDINGS_WITH_VARIANT_NAME, - p.hir_id, - p.span, - |lint| { - lint - .build( - &format!( - "pattern binding `{}` is named the same as one \ + cx.tcx.struct_span_lint_hir( + BINDINGS_WITH_VARIANT_NAME, + p.hir_id, + p.span, + |lint| { + lint.build(&format!( + "pattern binding `{}` is named the same as one \ of the variants of the type `{}`", - ident, ty_path - ) - ) - .code(error_code!(E0170)) - .span_suggestion( - p.span, - "to match on the variant, qualify the path", - format!("{}::{}", ty_path, ident), - Applicability::MachineApplicable, - ) - .emit(); - }, - ) + ident, ty_path + )) + .code(error_code!(E0170)) + .span_suggestion( + p.span, + "to match on the variant, qualify the path", + format!("{}::{}", ty_path, ident), + Applicability::MachineApplicable, + ) + .emit(); + }, + ) } } } diff --git a/src/librustc_mir_build/lints.rs b/src/librustc_mir_build/lints.rs index 4704f8d034dca..0017f800de702 100644 --- a/src/librustc_mir_build/lints.rs +++ b/src/librustc_mir_build/lints.rs @@ -124,20 +124,15 @@ fn check_fn_for_unconditional_recursion<'tcx>( if !reached_exit_without_self_call && !self_call_locations.is_empty() { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); let sp = tcx.sess.source_map().def_span(tcx.hir().span(hir_id)); - tcx.struct_span_lint_hir( - UNCONDITIONAL_RECURSION, - hir_id, - sp, - |lint| { - let mut db = lint.build("function cannot return without recursing"); - db.span_label(sp, "cannot return without recursing"); - // offer some help to the programmer. - for location in &self_call_locations { - db.span_label(location.span, "recursive call site"); - } - db.help("a `loop` may express intention better if this is on purpose"); - db.emit(); - }, - ); + tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION, hir_id, sp, |lint| { + let mut db = lint.build("function cannot return without recursing"); + db.span_label(sp, "cannot return without recursing"); + // offer some help to the programmer. + for location in &self_call_locations { + db.span_label(location.span, "recursive call site"); + } + db.help("a `loop` may express intention better if this is on purpose"); + db.emit(); + }); } } diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index cd935a37f7dda..8dec64c579e88 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -317,9 +317,9 @@ impl<'a> StripUnconfigured<'a> { Ok(r) => return Some(r), Err(mut e) => { e.help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP)) - .note(CFG_ATTR_NOTE_REF) - .emit(); - }, + .note(CFG_ATTR_NOTE_REF) + .emit(); + } } } _ => self.error_malformed_cfg_attr_missing(attr.span), diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index ba97f3feb8021..21a738c7f7b18 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -1407,6 +1407,8 @@ pub fn emit_unclosed_delims(unclosed_delims: &mut Vec, sess: &Pa *sess.reached_eof.borrow_mut() |= unclosed_delims.iter().any(|unmatched_delim| unmatched_delim.found_delim.is_none()); for unmatched in unclosed_delims.drain(..) { - make_unclosed_delims_error(unmatched, sess).map(|mut e| { e.emit(); }); + make_unclosed_delims_error(unmatched, sess).map(|mut e| { + e.emit(); + }); } } diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs index f6d5da68be3b6..f5e47608d589d 100644 --- a/src/librustc_parse/validate_attr.rs +++ b/src/librustc_parse/validate_attr.rs @@ -27,7 +27,11 @@ pub fn check_meta(sess: &ParseSess, attr: &Attribute) { _ => { if let MacArgs::Eq(..) = attr.get_normal_item().args { // All key-value attributes are restricted to meta-item syntax. - parse_meta(sess, attr).map_err(|mut err| { err.emit(); }).ok(); + parse_meta(sess, attr) + .map_err(|mut err| { + err.emit(); + }) + .ok(); } } } @@ -152,6 +156,8 @@ pub fn check_builtin_attribute( } } } - Err(mut err) => { err.emit(); }, + Err(mut err) => { + err.emit(); + } } } diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs index 6bae61d787b9b..fac90525e3234 100644 --- a/src/librustc_passes/check_attr.rs +++ b/src/librustc_passes/check_attr.rs @@ -92,13 +92,9 @@ impl CheckAttrVisitor<'tcx> { | Target::Method(MethodKind::Trait { body: true }) | Target::Method(MethodKind::Inherent) => true, Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => { - self.tcx - .struct_span_lint_hir( - UNUSED_ATTRIBUTES, - hir_id, - attr.span, - |lint| lint.build("`#[inline]` is ignored on function prototypes").emit(), - ); + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build("`#[inline]` is ignored on function prototypes").emit() + }); true } // FIXME(#65833): We permit associated consts to have an `#[inline]` attribute with @@ -331,17 +327,16 @@ impl CheckAttrVisitor<'tcx> { || (is_simd && is_c) || (int_reprs == 1 && is_c && item.map_or(false, |item| is_c_like_enum(item))) { - self.tcx - .struct_span_lint_hir( - CONFLICTING_REPR_HINTS, - hir_id, - hint_spans.collect::>(), - |lint| { - lint.build("conflicting representation hints") - .code(rustc_errors::error_code!(E0566)) - .emit(); - } - ); + self.tcx.struct_span_lint_hir( + CONFLICTING_REPR_HINTS, + hir_id, + hint_spans.collect::>(), + |lint| { + lint.build("conflicting representation hints") + .code(rustc_errors::error_code!(E0566)) + .emit(); + }, + ); } } diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index 27ad953e4fa6b..709068d218937 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -1521,18 +1521,16 @@ impl<'tcx> Liveness<'_, 'tcx> { if ln == self.s.exit_ln { false } else { self.assigned_on_exit(ln, var).is_some() }; if is_assigned { - self.ir - .tcx - .struct_span_lint_hir( - lint::builtin::UNUSED_VARIABLES, - hir_id, - spans, - |lint| { - lint.build(&format!("variable `{}` is assigned to, but never used", name)) - .note(&format!("consider using `_{}` instead", name)) - .emit(); - }, - ) + self.ir.tcx.struct_span_lint_hir( + lint::builtin::UNUSED_VARIABLES, + hir_id, + spans, + |lint| { + lint.build(&format!("variable `{}` is assigned to, but never used", name)) + .note(&format!("consider using `_{}` instead", name)) + .emit(); + }, + ) } else { self.ir.tcx.struct_span_lint_hir( lint::builtin::UNUSED_VARIABLES, @@ -1543,8 +1541,10 @@ impl<'tcx> Liveness<'_, 'tcx> { if self.ir.variable_is_shorthand(var) { if let Node::Binding(pat) = self.ir.tcx.hir().get(hir_id) { // Handle `ref` and `ref mut`. - let spans = - spans.iter().map(|_span| (pat.span, format!("{}: _", name))).collect(); + let spans = spans + .iter() + .map(|_span| (pat.span, format!("{}: _", name))) + .collect(); err.multipart_suggestion( "try ignoring the field", @@ -1575,31 +1575,27 @@ impl<'tcx> Liveness<'_, 'tcx> { fn report_dead_assign(&self, hir_id: HirId, spans: Vec, var: Variable, is_param: bool) { if let Some(name) = self.should_warn(var) { if is_param { - self.ir - .tcx - .struct_span_lint_hir( - lint::builtin::UNUSED_ASSIGNMENTS, - hir_id, - spans, - |lint| { - lint.build(&format!("value passed to `{}` is never read", name)) - .help("maybe it is overwritten before being read?") - .emit(); - }, - ) + self.ir.tcx.struct_span_lint_hir( + lint::builtin::UNUSED_ASSIGNMENTS, + hir_id, + spans, + |lint| { + lint.build(&format!("value passed to `{}` is never read", name)) + .help("maybe it is overwritten before being read?") + .emit(); + }, + ) } else { - self.ir - .tcx - .struct_span_lint_hir( - lint::builtin::UNUSED_ASSIGNMENTS, - hir_id, - spans, - |lint| { - lint.build(&format!("value assigned to `{}` is never read", name)) - .help("maybe it is overwritten before being read?") - .emit(); - }, - ) + self.ir.tcx.struct_span_lint_hir( + lint::builtin::UNUSED_ASSIGNMENTS, + hir_id, + spans, + |lint| { + lint.build(&format!("value assigned to `{}` is never read", name)) + .help("maybe it is overwritten before being read?") + .emit(); + }, + ) } } } diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 374b7d1cf7a15..4e2085d07a39a 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -608,10 +608,10 @@ fn unnecessary_stable_feature_lint(tcx: TyCtxt<'_>, span: Span, feature: Symbol, lint.build(&format!( "the feature `{}` has been stable since {} and no longer requires \ an attribute to enable", - feature, since - )).emit(); - } - ); + feature, since + )) + .emit(); + }); } fn duplicate_feature_err(sess: &Session, span: Span, feature: Symbol) { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 43f92ae69c46b..7f51bc25642b5 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1786,15 +1786,14 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { self.item_id, self.span, |lint| { - lint.build( - &format!( - "{} `{}` from private dependency '{}' in public \ + lint.build(&format!( + "{} `{}` from private dependency '{}' in public \ interface", - kind, - descr, - self.tcx.crate_name(def_id.krate) - ) - ).emit() + kind, + descr, + self.tcx.crate_name(def_id.krate) + )) + .emit() }, ); } @@ -1818,9 +1817,12 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { err.emit(); } else { let err_code = if kind == "trait" { "E0445" } else { "E0446" }; - self.tcx.struct_span_lint_hir(lint::builtin::PRIVATE_IN_PUBLIC, hir_id, self.span, |lint| { - lint.build(&format!("{} (error {})", msg, err_code)).emit() - }); + self.tcx.struct_span_lint_hir( + lint::builtin::PRIVATE_IN_PUBLIC, + hir_id, + self.span, + |lint| lint.build(&format!("{} (error {})", msg, err_code)).emit(), + ); } } diff --git a/src/librustc_resolve/lifetimes.rs b/src/librustc_resolve/lifetimes.rs index cef5e025741d7..fd4d2c718c094 100644 --- a/src/librustc_resolve/lifetimes.rs +++ b/src/librustc_resolve/lifetimes.rs @@ -1580,7 +1580,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { id, span, |lint| { - let mut err = lint.build(&format!("lifetime parameter `{}` only used once", name)); + let mut err = lint.build(&format!( + "lifetime parameter `{}` only used once", + name + )); if span == lifetime.span { // spans are the same for in-band lifetime declarations err.span_label(span, "this lifetime is only used here"); @@ -1588,7 +1591,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { err.span_label(span, "this lifetime..."); err.span_label(lifetime.span, "...is used only here"); } - self.suggest_eliding_single_use_lifetime(&mut err, def_id, lifetime); + self.suggest_eliding_single_use_lifetime( + &mut err, def_id, lifetime, + ); err.emit(); }, ); @@ -1616,10 +1621,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { id, span, |lint| { - let mut err = lint.build(&format!("lifetime parameter `{}` never used", name)); + let mut err = lint + .build(&format!("lifetime parameter `{}` never used", name)); if let Some(parent_def_id) = self.tcx.parent(def_id) { - if let Some(generics) = self.tcx.hir().get_generics(parent_def_id) { - let unused_lt_span = self.lifetime_deletion_span(name, generics); + if let Some(generics) = + self.tcx.hir().get_generics(parent_def_id) + { + let unused_lt_span = + self.lifetime_deletion_span(name, generics); if let Some(span) = unused_lt_span { err.span_suggestion( span, diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 02da2766ec661..909f40ee98499 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -468,27 +468,20 @@ impl<'a, 'tcx> CastCheck<'tcx> { } else { ("", lint::builtin::TRIVIAL_CASTS) }; - fcx.tcx.struct_span_lint_hir( - lint, - self.expr.hir_id, - self.span, - |err| { - err.build( - &format!( - "trivial {}cast: `{}` as `{}`", - adjective, - fcx.ty_to_string(t_expr), - fcx.ty_to_string(t_cast) - ) - ) - .help(&format!( - "cast can be replaced by coercion; this might \ + fcx.tcx.struct_span_lint_hir(lint, self.expr.hir_id, self.span, |err| { + err.build(&format!( + "trivial {}cast: `{}` as `{}`", + adjective, + fcx.ty_to_string(t_expr), + fcx.ty_to_string(t_cast) + )) + .help(&format!( + "cast can be replaced by coercion; this might \ require {}a temporary variable", - type_asc_or - )) - .emit(); - }, - ); + type_asc_or + )) + .emit(); + }); } pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) { diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 599f7dfe2d41c..760b6487045d8 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1285,7 +1285,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.fcx.body_id, self.span, |lint| { - let mut diag = lint.build("a method with this name may be added to the standard library in the future"); + let mut diag = lint.build( + "a method with this name may be added to the standard library in the future", + ); // FIXME: This should be a `span_suggestion` instead of `help` // However `self.span` only // highlights the method name, so we can't use it. Also consider reusing the code from diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2fff5106dd1d2..be2052dce3c0b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2895,17 +2895,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind); - self.tcx() - .struct_span_lint_hir(lint::builtin::UNREACHABLE_CODE, id, span, |lint| { - let msg = format!("unreachable {}", kind); - lint.build(&msg) - .span_label(span, &msg) - .span_label( - orig_span, - custom_note.unwrap_or("any code following this expression is unreachable"), - ) - .emit(); - }) + self.tcx().struct_span_lint_hir(lint::builtin::UNREACHABLE_CODE, id, span, |lint| { + let msg = format!("unreachable {}", kind); + lint.build(&msg) + .span_label(span, &msg) + .span_label( + orig_span, + custom_note + .unwrap_or("any code following this expression is unreachable"), + ) + .emit(); + }) } } } diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 71ce5ce0f02ce..6471db3efce84 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -180,7 +180,6 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { }; let replacement = visibility_qualified(&item.vis, base_replacement); tcx.struct_span_lint_hir(lint, id, extern_crate.span, |lint| { - let msg = "`extern crate` is not idiomatic in the new edition"; let help = format!("convert it to a `{}`", visibility_qualified(&item.vis, "use")); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d26a4cdc5ca77..1b4f0ffce9c1e 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1157,9 +1157,10 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { param.span, |lint| { lint.build(&format!( - "defaults for type parameters are only allowed in \ + "defaults for type parameters are only allowed in \ `struct`, `enum`, `type`, or `trait` definitions." - )).emit(); + )) + .emit(); }, ); } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index dfb75c5a98e73..79bcfe7aee744 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -676,7 +676,8 @@ fn build_diagnostic( |lint| { let mut diag = lint.build(&format!("`[{}]` {}", path_str, err_msg)); if let Some(link_range) = link_range { - if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) { + if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) + { diag.set_span(sp); diag.span_label(sp, short_err_msg); } else { @@ -684,7 +685,8 @@ fn build_diagnostic( // ^ ~~~~ // | link_range // last_new_line_offset - let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1); + let last_new_line_offset = + dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1); let line = dox[last_new_line_offset..].lines().next().unwrap_or(""); // Print the line containing the `link_range` and manually mark it with '^'s. @@ -804,7 +806,8 @@ fn ambiguity_error( let mut diag = lint.build(&msg); if let Some(link_range) = link_range { - if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) { + if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) + { diag.set_span(sp); diag.span_label(sp, "ambiguous link"); @@ -851,7 +854,8 @@ fn ambiguity_error( // ^ ~~~~ // | link_range // last_new_line_offset - let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1); + let last_new_line_offset = + dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1); let line = dox[last_new_line_offset..].lines().next().unwrap_or(""); // Print the line containing the `link_range` and manually mark it with '^'s. @@ -868,7 +872,6 @@ fn ambiguity_error( diag.emit(); }, ); - } /// Given an enum variant's res, return the res of its enum and the associated fragment. diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index a5213fe8635fd..9e48904a47d33 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -342,12 +342,9 @@ pub fn look_for_tests<'tcx>( if check_missing_code == true && tests.found_tests == 0 { let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span()); - cx.tcx.struct_span_lint_hir( - lint::builtin::MISSING_DOC_CODE_EXAMPLES, - hir_id, - sp, - |lint| lint.build("missing code example in this documentation").emit(), - ); + cx.tcx.struct_span_lint_hir(lint::builtin::MISSING_DOC_CODE_EXAMPLES, hir_id, sp, |lint| { + lint.build("missing code example in this documentation").emit() + }); } else if check_missing_code == false && tests.found_tests > 0 && !cx.renderinfo.borrow().access_levels.is_public(item.def_id) From b2e78faa15263011dad1e9579fc59610d5b75579 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Sun, 2 Feb 2020 11:11:33 +1000 Subject: [PATCH 05/11] Move more work into `decorate` functions. --- src/librustc_lint/nonstandard_style.rs | 8 +++---- src/librustc_lint/types.rs | 20 ++++++++-------- src/librustc_typeck/check_unused.rs | 32 ++++++++++++-------------- 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 52f29b30f3be9..d45ea10dfbf58 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -107,8 +107,8 @@ impl NonCamelCaseTypes { let name = &ident.name.as_str(); if !is_camel_case(name) { - let msg = format!("{} `{}` should have an upper camel case name", sort, name); cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, |lint| { + let msg = format!("{} `{}` should have an upper camel case name", sort, name); lint.build(&msg) .span_suggestion( ident.span, @@ -227,8 +227,8 @@ impl NonSnakeCase { if !is_snake_case(name) { let sc = NonSnakeCase::to_snake_case(name); - let msg = format!("{} `{}` should have a snake case name", sort, name); cx.struct_span_lint(NON_SNAKE_CASE, ident.span, |lint| { + let msg = format!("{} `{}` should have a snake case name", sort, name); let mut err = lint.build(&msg); // We have a valid span in almost all cases, but we don't have one when linting a crate // name provided via the command line. @@ -389,11 +389,9 @@ declare_lint_pass!(NonUpperCaseGlobals => [NON_UPPER_CASE_GLOBALS]); impl NonUpperCaseGlobals { fn check_upper_case(cx: &LateContext<'_, '_>, sort: &str, ident: &Ident) { let name = &ident.name.as_str(); - if name.chars().any(|c| c.is_lowercase()) { - let uc = NonSnakeCase::to_snake_case(&name).to_uppercase(); - cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| { + let uc = NonSnakeCase::to_snake_case(&name).to_uppercase(); lint.build(&format!("{} `{}` should have an upper case name", sort, name)) .span_suggestion( ident.span, diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 71a86592396c9..d1982e9162e59 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -151,17 +151,17 @@ fn report_bin_hex_error( negative: bool, ) { let size = layout::Integer::from_attr(&cx.tcx, ty).size(); - let (t, actually) = match ty { - attr::IntType::SignedInt(t) => { - let actually = sign_extend(val, size) as i128; - (t.name_str(), actually.to_string()) - } - attr::IntType::UnsignedInt(t) => { - let actually = truncate(val, size); - (t.name_str(), actually.to_string()) - } - }; cx.struct_span_lint(OVERFLOWING_LITERALS, expr.span, |lint| { + let (t, actually) = match ty { + attr::IntType::SignedInt(t) => { + let actually = sign_extend(val, size) as i128; + (t.name_str(), actually.to_string()) + } + attr::IntType::UnsignedInt(t) => { + let actually = truncate(val, size); + (t.name_str(), actually.to_string()) + } + }; let mut err = lint.build(&format!("literal out of range for {}", t)); err.note(&format!( "the literal `{}` (decimal `{}`) does not fit into \ diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 6471db3efce84..dd833d9751cb9 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -123,17 +123,15 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { // We do this in any edition. if extern_crate.warn_if_unused { if let Some(&span) = unused_extern_crates.get(&extern_crate.def_id) { - let msg = "unused extern crate"; - - // Removal suggestion span needs to include attributes (Issue #54400) - let span_with_attrs = tcx - .get_attrs(extern_crate.def_id) - .iter() - .map(|attr| attr.span) - .fold(span, |acc, attr_span| acc.to(attr_span)); - tcx.struct_span_lint_hir(lint, id, span, |lint| { - lint.build(msg) + // Removal suggestion span needs to include attributes (Issue #54400) + let span_with_attrs = tcx + .get_attrs(extern_crate.def_id) + .iter() + .map(|attr| attr.span) + .fold(span, |acc, attr_span| acc.to(attr_span)); + + lint.build("unused extern crate") .span_suggestion_short( span_with_attrs, "remove it", @@ -172,14 +170,14 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { if !tcx.get_attrs(extern_crate.def_id).is_empty() { continue; } - - // Otherwise, we can convert it into a `use` of some kind. - let base_replacement = match extern_crate.orig_name { - Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name), - None => format!("use {};", item.ident.name), - }; - let replacement = visibility_qualified(&item.vis, base_replacement); tcx.struct_span_lint_hir(lint, id, extern_crate.span, |lint| { + // Otherwise, we can convert it into a `use` of some kind. + let base_replacement = match extern_crate.orig_name { + Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name), + None => format!("use {};", item.ident.name), + }; + + let replacement = visibility_qualified(&item.vis, base_replacement); let msg = "`extern crate` is not idiomatic in the new edition"; let help = format!("convert it to a `{}`", visibility_qualified(&item.vis, "use")); From 2f0430a163bb2f4fe6545064391606bb736e9e51 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Sun, 2 Feb 2020 19:41:14 +1000 Subject: [PATCH 06/11] Make cx.span_lint methods lazy - Make report_unsafe take decorate function - Remove span_lint, replacing calls with struct_span_lint, as caller is now responsible for emitting. - Remove lookup_and_emit, replacing with just lookup which takes a decorate function. - Remove span_lint_note, span_lint_help. These methods aren't easily made lazy as standalone methods, private, and unused. If this functionality is needed, to be lazy, they can easily be made into Fn(&mut DiagnosticBuilder) that are meant to be called _within_ the decorate function. - Rename lookup_and_emit_with_diagnostics to lookup_with_diagnostics to better reflect the fact that it doesn't emit for you. --- src/librustc_lint/builtin.rs | 50 ++++++++++++++--------------- src/librustc_lint/context.rs | 57 ++++++---------------------------- src/librustc_lint/early.rs | 9 +++--- src/librustc_lint/types.rs | 22 ++++++------- src/librustc_lint/unused.rs | 53 +++++++++++++++++-------------- src/librustc_typeck/collect.rs | 8 +++-- 6 files changed, 85 insertions(+), 114 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 9fc81a4a1fdaf..7ebedd29cc420 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -28,6 +28,7 @@ use rustc::ty::{self, layout::VariantIdx, Ty, TyCtxt}; use rustc_ast_pretty::pprust::{self, expr_to_string}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc::lint::LintDiagnosticBuilder; use rustc_feature::Stability; use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, AttributeType}; use rustc_hir as hir; @@ -106,8 +107,7 @@ impl BoxPointers { fn check_heap_type(&self, cx: &LateContext<'_, '_>, span: Span, ty: Ty<'_>) { for leaf_ty in ty.walk() { if leaf_ty.is_box() { - let m = format!("type uses owned (Box type) pointers: {}", ty); - cx.span_lint(BOX_POINTERS, span, &m); + cx.struct_span_lint(BOX_POINTERS, span, |lint| lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit()); } } } @@ -214,13 +214,13 @@ declare_lint! { declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]); impl UnsafeCode { - fn report_unsafe(&self, cx: &EarlyContext<'_>, span: Span, desc: &'static str) { + fn report_unsafe(&self, cx: &EarlyContext<'_>, span: Span, decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) { // This comes from a macro that has `#[allow_internal_unsafe]`. if span.allows_unsafe() { return; } - cx.span_lint(UNSAFE_CODE, span, desc); + cx.struct_span_lint(UNSAFE_CODE, span, decorate); } } @@ -230,9 +230,9 @@ impl EarlyLintPass for UnsafeCode { self.report_unsafe( cx, attr.span, - "`allow_internal_unsafe` allows defining \ + |lint| lint.build("`allow_internal_unsafe` allows defining \ macros using unsafe without triggering \ - the `unsafe_code` lint at their call site", + the `unsafe_code` lint at their call site").emit(), ); } } @@ -241,7 +241,7 @@ impl EarlyLintPass for UnsafeCode { if let ast::ExprKind::Block(ref blk, _) = e.kind { // Don't warn about generated blocks; that'll just pollute the output. if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) { - self.report_unsafe(cx, blk.span, "usage of an `unsafe` block"); + self.report_unsafe(cx, blk.span, |lint| lint.build("usage of an `unsafe` block").emit()); } } } @@ -249,11 +249,11 @@ impl EarlyLintPass for UnsafeCode { fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { match it.kind { ast::ItemKind::Trait(_, ast::Unsafety::Unsafe, ..) => { - self.report_unsafe(cx, it.span, "declaration of an `unsafe` trait") + self.report_unsafe(cx, it.span, |lint| lint.build("declaration of an `unsafe` trait").emit()) } ast::ItemKind::Impl { unsafety: ast::Unsafety::Unsafe, .. } => { - self.report_unsafe(cx, it.span, "implementation of an `unsafe` trait") + self.report_unsafe(cx, it.span, |lint| lint.build("implementation of an `unsafe` trait").emit()) } _ => return, @@ -275,7 +275,7 @@ impl EarlyLintPass for UnsafeCode { FnCtxt::Assoc(_) if body.is_none() => "declaration of an `unsafe` method", FnCtxt::Assoc(_) => "implementation of an `unsafe` method", }; - self.report_unsafe(cx, span, msg); + self.report_unsafe(cx, span, |lint| lint.build(msg).emit()); } } } @@ -360,10 +360,10 @@ impl MissingDoc { let has_doc = attrs.iter().any(|a| has_doc(a)); if !has_doc { - cx.span_lint( + cx.struct_span_lint( MISSING_DOCS, cx.tcx.sess.source_map().def_span(sp), - &format!("missing documentation for {}", desc), + |lint| lint.build(&format!("missing documentation for {}", desc)).emit(), ); } } @@ -392,10 +392,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { for macro_def in krate.exported_macros { let has_doc = macro_def.attrs.iter().any(|a| has_doc(a)); if !has_doc { - cx.span_lint( + cx.struct_span_lint( MISSING_DOCS, cx.tcx.sess.source_map().def_span(macro_def.span), - "missing documentation for macro", + |lint| lint.build("missing documentation for macro").emit(), ); } } @@ -543,11 +543,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations { return; } if can_type_implement_copy(cx.tcx, param_env, ty).is_ok() { - cx.span_lint( + cx.struct_span_lint( MISSING_COPY_IMPLEMENTATIONS, item.span, - "type could implement `Copy`; consider adding `impl \ - Copy`", + |lint| lint.build("type could implement `Copy`; consider adding `impl \ + Copy`").emit(), ) } } @@ -597,14 +597,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations { } if !self.impling_types.as_ref().unwrap().contains(&item.hir_id) { - cx.span_lint( + cx.struct_span_lint( MISSING_DEBUG_IMPLEMENTATIONS, item.span, - &format!( + |lint| lint.build(&format!( "type does not implement `{}`; consider adding `#[derive(Debug)]` \ or a manual implementation", cx.tcx.def_path_str(debug) - ), + )).emit(), ); } } @@ -903,7 +903,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { match get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.kind, &ty2.kind)) { Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => { if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not { - cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg); + cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| lint.build(msg).emit()); } } _ => (), @@ -953,7 +953,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures { if attr.check_name(sym::feature) { if let Some(items) = attr.meta_item_list() { for item in items { - ctx.span_lint(UNSTABLE_FEATURES, item.span(), "unstable feature"); + ctx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| lint.build("unstable feature").emit()); } } } @@ -1235,14 +1235,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints { ConstEvaluatable(..) => continue, }; if predicate.is_global() { - cx.span_lint( + cx.struct_span_lint( TRIVIAL_BOUNDS, span, - &format!( + |lint| lint.build(&format!( "{} bound {} does not depend on any type \ or lifetime parameters", predicate_kind_name, predicate - ), + )).emit(), ); } } diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs index d9ad97654e04b..232b56c88f2b0 100644 --- a/src/librustc_lint/context.rs +++ b/src/librustc_lint/context.rs @@ -474,19 +474,18 @@ pub trait LintContext: Sized { fn sess(&self) -> &Session; fn lints(&self) -> &LintStore; - fn lookup_and_emit>(&self, lint: &'static Lint, span: Option, msg: &str) { - self.lookup(lint, span, |lint| lint.build(msg).emit()); - } - - fn lookup_and_emit_with_diagnostics>( + fn lookup_with_diagnostics>( &self, lint: &'static Lint, span: Option, - msg: &str, + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), diagnostic: BuiltinLintDiagnostics, ) { self.lookup(lint, span, |lint| { - let mut db = lint.build(msg); + // We first generate a blank diagnostic. + let mut db = lint.build(""); + + // Now, set up surrounding context. let sess = self.sess(); match diagnostic { BuiltinLintDiagnostics::Normal => (), @@ -567,8 +566,8 @@ pub trait LintContext: Sized { stability::deprecation_suggestion(&mut db, suggestion, span) } } - - db.emit(); + // Rewrap `db`, and pass control to the user. + decorate(LintDiagnosticBuilder::new(db)); }); } @@ -579,11 +578,6 @@ pub trait LintContext: Sized { decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), ); - /// Emit a lint at the appropriate level, for a particular span. - fn span_lint>(&self, lint: &'static Lint, span: S, msg: &str) { - self.lookup_and_emit(lint, Some(span), msg); - } - fn struct_span_lint>( &self, lint: &'static Lint, @@ -592,40 +586,9 @@ pub trait LintContext: Sized { ) { self.lookup(lint, Some(span), decorate); } - - /// Emit a lint and note at the appropriate level, for a particular span. - fn span_lint_note( - &self, - lint: &'static Lint, - span: Span, - msg: &str, - note_span: Span, - note: &str, - ) { - self.lookup(lint, Some(span), |lint| { - let mut err = lint.build(msg); - if note_span == span { - err.note(note); - } else { - err.span_note(note_span, note); - } - err.emit(); - }); - } - - /// Emit a lint and help at the appropriate level, for a particular span. - fn span_lint_help(&self, lint: &'static Lint, span: Span, msg: &str, help: &str) { - self.lookup(lint, Some(span), |err| { - let mut err = err.build(msg); - self.span_lint(lint, span, msg); - err.span_help(span, help); - err.emit(); - }); - } - /// Emit a lint at the appropriate level, with no associated span. - fn lint(&self, lint: &'static Lint, msg: &str) { - self.lookup_and_emit(lint, None as Option, msg); + fn lint(&self, lint: &'static Lint, decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) { + self.lookup(lint, None as Option, decorate); } } diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs index 27781eb41d28d..4f337cd18aaa0 100644 --- a/src/librustc_lint/early.rs +++ b/src/librustc_lint/early.rs @@ -37,11 +37,12 @@ struct EarlyContextAndPass<'a, T: EarlyLintPass> { impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { fn check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { - self.context.lookup_and_emit_with_diagnostics( + let rustc_session::lint::BufferedEarlyLint { span, msg, node_id: _, lint_id: _, diagnostic } = early_lint; + self.context.lookup_with_diagnostics( early_lint.lint_id.lint, - Some(early_lint.span.clone()), - &early_lint.msg, - early_lint.diagnostic, + Some(span), + |lint| lint.build(&msg).emit(), + diagnostic, ); } } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index d1982e9162e59..f6404fb63d409 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -266,10 +266,10 @@ fn lint_int_literal<'a, 'tcx>( } } - cx.span_lint( + cx.struct_span_lint( OVERFLOWING_LITERALS, e.span, - &format!("literal out of range for `{}`", t.name_str()), + |lint| lint.build(&format!("literal out of range for `{}`", t.name_str())).emit(), ); } } @@ -321,10 +321,10 @@ fn lint_uint_literal<'a, 'tcx>( report_bin_hex_error(cx, e, attr::IntType::UnsignedInt(t), repr_str, lit_val, false); return; } - cx.span_lint( + cx.struct_span_lint( OVERFLOWING_LITERALS, e.span, - &format!("literal out of range for `{}`", t.name_str()), + |lint| lint.build(&format!("literal out of range for `{}`", t.name_str())).emit(), ); } } @@ -355,10 +355,10 @@ fn lint_literal<'a, 'tcx>( _ => bug!(), }; if is_infinite == Ok(true) { - cx.span_lint( + cx.struct_span_lint( OVERFLOWING_LITERALS, e.span, - &format!("literal out of range for `{}`", t.name_str()), + |lint| lint.build(&format!("literal out of range for `{}`", t.name_str())).emit(), ); } } @@ -377,10 +377,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } hir::ExprKind::Binary(binop, ref l, ref r) => { if is_comparison(binop) && !check_limits(cx, binop, &l, &r) { - cx.span_lint( + cx.struct_span_lint( UNUSED_COMPARISONS, e.span, - "comparison is useless due to type limits", + |lint| lint.build("comparison is useless due to type limits").emit(), ); } } @@ -1055,14 +1055,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { // We only warn if the largest variant is at least thrice as large as // the second-largest. if largest > slargest * 3 && slargest > 0 { - cx.span_lint( + cx.struct_span_lint( VARIANT_SIZE_DIFFERENCES, enum_definition.variants[largest_index].span, - &format!( + |lint| lint.build(&format!( "enum variant is more than three times \ larger ({} bytes) than the next largest", largest - ), + )).emit(), ); } } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 2f4a9572a8349..faa0b019311eb 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -104,16 +104,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { }; if let Some(must_use_op) = must_use_op { - cx.span_lint( + cx.struct_span_lint( UNUSED_MUST_USE, expr.span, - &format!("unused {} that must be used", must_use_op), + |lint| lint.build(&format!("unused {} that must be used", must_use_op)).emit(), ); op_warned = true; } if !(type_permits_lack_of_use || fn_warned || op_warned) { - cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); + cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| lint.build("unused result").emit()); } // Returns whether an error has been emitted (and thus another does not need to be later). @@ -247,7 +247,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathStatements { fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt<'_>) { if let hir::StmtKind::Semi(ref expr) = s.kind { if let hir::ExprKind::Path(_) = expr.kind { - cx.span_lint(PATH_STATEMENTS, s.span, "path statement with no effect"); + cx.struct_span_lint(PATH_STATEMENTS, s.span, |lint| lint.build("path statement with no effect").emit()); } } } @@ -288,17 +288,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { if !attr::is_used(attr) { debug!("emitting warning for: {:?}", attr); - cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute"); + cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| lint.build("unused attribute").emit()); // Is it a builtin attribute that must be used at the crate level? if attr_info.map_or(false, |(_, ty, ..)| ty == &AttributeType::CrateLevel) { - let msg = match attr.style { - ast::AttrStyle::Outer => { - "crate-level attribute should be an inner attribute: add an exclamation \ - mark: `#![foo]`" - } - ast::AttrStyle::Inner => "crate-level attribute should be in the root module", - }; - cx.span_lint(UNUSED_ATTRIBUTES, attr.span, msg); + cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| { + let msg = match attr.style { + ast::AttrStyle::Outer => { + "crate-level attribute should be an inner attribute: add an exclamation \ + mark: `#![foo]`" + } + ast::AttrStyle::Inner => "crate-level attribute should be in the root module", + }; + lint.build(msg).emit() + }); } } else { debug!("Attr was used: {:?}", attr); @@ -635,8 +637,9 @@ impl UnusedImportBraces { ast::UseTreeKind::Nested(_) => return, }; - let msg = format!("braces around {} is unnecessary", node_name); - cx.span_lint(UNUSED_IMPORT_BRACES, item.span, &msg); + cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| + lint.build(&format!("braces around {} is unnecessary", node_name)).emit() + ); } } } @@ -666,15 +669,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation { for adj in cx.tables.expr_adjustments(e) { if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind { - let msg = match m { - adjustment::AutoBorrowMutability::Not => { - "unnecessary allocation, use `&` instead" - } - adjustment::AutoBorrowMutability::Mut { .. } => { - "unnecessary allocation, use `&mut` instead" - } - }; - cx.span_lint(UNUSED_ALLOCATION, e.span, msg); + cx.struct_span_lint(UNUSED_ALLOCATION, e.span, |lint| { + let msg = match m { + adjustment::AutoBorrowMutability::Not => { + "unnecessary allocation, use `&` instead" + } + adjustment::AutoBorrowMutability::Mut { .. } => { + "unnecessary allocation, use `&mut` instead" + } + }; + lint.build(msg).emit() + }); } } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1b4f0ffce9c1e..b661006d1ddd0 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2959,10 +2959,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { lint::builtin::INLINE_NO_SANITIZE, hir_id, no_sanitize_span, - "`no_sanitize` will have no effect after inlining", + |lint| { + lint.build("`no_sanitize` will have no effect after inlining") + .span_note(inline_span, "inlining requested here") + .emit(); + }, ) - .span_note(inline_span, "inlining requested here") - .emit(); } } } From aa3c458c067b399e1f115281f77b7f33513d5920 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Mon, 3 Feb 2020 19:57:45 +1000 Subject: [PATCH 07/11] Run RustFmt --- src/librustc_lint/builtin.rs | 89 ++++++++++++++++++------------- src/librustc_lint/early.rs | 8 ++- src/librustc_lint/types.rs | 43 +++++++-------- src/librustc_lint/unused.rs | 22 ++++---- src/librustc_passes/check_attr.rs | 25 ++++----- 5 files changed, 100 insertions(+), 87 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 7ebedd29cc420..23bbcb40c9434 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -23,12 +23,12 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc::hir::map::Map; +use rustc::lint::LintDiagnosticBuilder; use rustc::traits::misc::can_type_implement_copy; use rustc::ty::{self, layout::VariantIdx, Ty, TyCtxt}; use rustc_ast_pretty::pprust::{self, expr_to_string}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder}; -use rustc::lint::LintDiagnosticBuilder; use rustc_feature::Stability; use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, AttributeType}; use rustc_hir as hir; @@ -107,7 +107,9 @@ impl BoxPointers { fn check_heap_type(&self, cx: &LateContext<'_, '_>, span: Span, ty: Ty<'_>) { for leaf_ty in ty.walk() { if leaf_ty.is_box() { - cx.struct_span_lint(BOX_POINTERS, span, |lint| lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit()); + cx.struct_span_lint(BOX_POINTERS, span, |lint| { + lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit() + }); } } } @@ -214,7 +216,12 @@ declare_lint! { declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]); impl UnsafeCode { - fn report_unsafe(&self, cx: &EarlyContext<'_>, span: Span, decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) { + fn report_unsafe( + &self, + cx: &EarlyContext<'_>, + span: Span, + decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), + ) { // This comes from a macro that has `#[allow_internal_unsafe]`. if span.allows_unsafe() { return; @@ -227,13 +234,14 @@ impl UnsafeCode { impl EarlyLintPass for UnsafeCode { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { if attr.check_name(sym::allow_internal_unsafe) { - self.report_unsafe( - cx, - attr.span, - |lint| lint.build("`allow_internal_unsafe` allows defining \ + self.report_unsafe(cx, attr.span, |lint| { + lint.build( + "`allow_internal_unsafe` allows defining \ macros using unsafe without triggering \ - the `unsafe_code` lint at their call site").emit(), - ); + the `unsafe_code` lint at their call site", + ) + .emit() + }); } } @@ -241,7 +249,9 @@ impl EarlyLintPass for UnsafeCode { if let ast::ExprKind::Block(ref blk, _) = e.kind { // Don't warn about generated blocks; that'll just pollute the output. if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) { - self.report_unsafe(cx, blk.span, |lint| lint.build("usage of an `unsafe` block").emit()); + self.report_unsafe(cx, blk.span, |lint| { + lint.build("usage of an `unsafe` block").emit() + }); } } } @@ -249,11 +259,15 @@ impl EarlyLintPass for UnsafeCode { fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { match it.kind { ast::ItemKind::Trait(_, ast::Unsafety::Unsafe, ..) => { - self.report_unsafe(cx, it.span, |lint| lint.build("declaration of an `unsafe` trait").emit()) + self.report_unsafe(cx, it.span, |lint| { + lint.build("declaration of an `unsafe` trait").emit() + }) } ast::ItemKind::Impl { unsafety: ast::Unsafety::Unsafe, .. } => { - self.report_unsafe(cx, it.span, |lint| lint.build("implementation of an `unsafe` trait").emit()) + self.report_unsafe(cx, it.span, |lint| { + lint.build("implementation of an `unsafe` trait").emit() + }) } _ => return, @@ -360,11 +374,9 @@ impl MissingDoc { let has_doc = attrs.iter().any(|a| has_doc(a)); if !has_doc { - cx.struct_span_lint( - MISSING_DOCS, - cx.tcx.sess.source_map().def_span(sp), - |lint| lint.build(&format!("missing documentation for {}", desc)).emit(), - ); + cx.struct_span_lint(MISSING_DOCS, cx.tcx.sess.source_map().def_span(sp), |lint| { + lint.build(&format!("missing documentation for {}", desc)).emit() + }); } } } @@ -543,12 +555,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations { return; } if can_type_implement_copy(cx.tcx, param_env, ty).is_ok() { - cx.struct_span_lint( - MISSING_COPY_IMPLEMENTATIONS, - item.span, - |lint| lint.build("type could implement `Copy`; consider adding `impl \ - Copy`").emit(), - ) + cx.struct_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, |lint| { + lint.build( + "type could implement `Copy`; consider adding `impl \ + Copy`", + ) + .emit() + }) } } } @@ -597,15 +610,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations { } if !self.impling_types.as_ref().unwrap().contains(&item.hir_id) { - cx.struct_span_lint( - MISSING_DEBUG_IMPLEMENTATIONS, - item.span, - |lint| lint.build(&format!( + cx.struct_span_lint(MISSING_DEBUG_IMPLEMENTATIONS, item.span, |lint| { + lint.build(&format!( "type does not implement `{}`; consider adding `#[derive(Debug)]` \ or a manual implementation", cx.tcx.def_path_str(debug) - )).emit(), - ); + )) + .emit() + }); } } } @@ -903,7 +915,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { match get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.kind, &ty2.kind)) { Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => { if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not { - cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| lint.build(msg).emit()); + cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| { + lint.build(msg).emit() + }); } } _ => (), @@ -953,7 +967,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures { if attr.check_name(sym::feature) { if let Some(items) = attr.meta_item_list() { for item in items { - ctx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| lint.build("unstable feature").emit()); + ctx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| { + lint.build("unstable feature").emit() + }); } } } @@ -1235,15 +1251,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints { ConstEvaluatable(..) => continue, }; if predicate.is_global() { - cx.struct_span_lint( - TRIVIAL_BOUNDS, - span, - |lint| lint.build(&format!( + cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| { + lint.build(&format!( "{} bound {} does not depend on any type \ or lifetime parameters", predicate_kind_name, predicate - )).emit(), - ); + )) + .emit() + }); } } } diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs index 4f337cd18aaa0..a636e7540fb0d 100644 --- a/src/librustc_lint/early.rs +++ b/src/librustc_lint/early.rs @@ -37,7 +37,13 @@ struct EarlyContextAndPass<'a, T: EarlyLintPass> { impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { fn check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { - let rustc_session::lint::BufferedEarlyLint { span, msg, node_id: _, lint_id: _, diagnostic } = early_lint; + let rustc_session::lint::BufferedEarlyLint { + span, + msg, + node_id: _, + lint_id: _, + diagnostic, + } = early_lint; self.context.lookup_with_diagnostics( early_lint.lint_id.lint, Some(span), diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index f6404fb63d409..5ffa9c1747fa9 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -266,11 +266,9 @@ fn lint_int_literal<'a, 'tcx>( } } - cx.struct_span_lint( - OVERFLOWING_LITERALS, - e.span, - |lint| lint.build(&format!("literal out of range for `{}`", t.name_str())).emit(), - ); + cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { + lint.build(&format!("literal out of range for `{}`", t.name_str())).emit() + }); } } @@ -321,11 +319,9 @@ fn lint_uint_literal<'a, 'tcx>( report_bin_hex_error(cx, e, attr::IntType::UnsignedInt(t), repr_str, lit_val, false); return; } - cx.struct_span_lint( - OVERFLOWING_LITERALS, - e.span, - |lint| lint.build(&format!("literal out of range for `{}`", t.name_str())).emit(), - ); + cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { + lint.build(&format!("literal out of range for `{}`", t.name_str())).emit() + }); } } @@ -355,11 +351,9 @@ fn lint_literal<'a, 'tcx>( _ => bug!(), }; if is_infinite == Ok(true) { - cx.struct_span_lint( - OVERFLOWING_LITERALS, - e.span, - |lint| lint.build(&format!("literal out of range for `{}`", t.name_str())).emit(), - ); + cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { + lint.build(&format!("literal out of range for `{}`", t.name_str())).emit() + }); } } _ => {} @@ -377,11 +371,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } hir::ExprKind::Binary(binop, ref l, ref r) => { if is_comparison(binop) && !check_limits(cx, binop, &l, &r) { - cx.struct_span_lint( - UNUSED_COMPARISONS, - e.span, - |lint| lint.build("comparison is useless due to type limits").emit(), - ); + cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| { + lint.build("comparison is useless due to type limits").emit() + }); } } hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit), @@ -1058,11 +1050,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { cx.struct_span_lint( VARIANT_SIZE_DIFFERENCES, enum_definition.variants[largest_index].span, - |lint| lint.build(&format!( - "enum variant is more than three times \ + |lint| { + lint.build(&format!( + "enum variant is more than three times \ larger ({} bytes) than the next largest", - largest - )).emit(), + largest + )) + .emit() + }, ); } } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index faa0b019311eb..9cf5ff42c5771 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -104,11 +104,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { }; if let Some(must_use_op) = must_use_op { - cx.struct_span_lint( - UNUSED_MUST_USE, - expr.span, - |lint| lint.build(&format!("unused {} that must be used", must_use_op)).emit(), - ); + cx.struct_span_lint(UNUSED_MUST_USE, expr.span, |lint| { + lint.build(&format!("unused {} that must be used", must_use_op)).emit() + }); op_warned = true; } @@ -247,7 +245,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathStatements { fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt<'_>) { if let hir::StmtKind::Semi(ref expr) = s.kind { if let hir::ExprKind::Path(_) = expr.kind { - cx.struct_span_lint(PATH_STATEMENTS, s.span, |lint| lint.build("path statement with no effect").emit()); + cx.struct_span_lint(PATH_STATEMENTS, s.span, |lint| { + lint.build("path statement with no effect").emit() + }); } } } @@ -288,7 +288,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { if !attr::is_used(attr) { debug!("emitting warning for: {:?}", attr); - cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| lint.build("unused attribute").emit()); + cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| { + lint.build("unused attribute").emit() + }); // Is it a builtin attribute that must be used at the crate level? if attr_info.map_or(false, |(_, ty, ..)| ty == &AttributeType::CrateLevel) { cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| { @@ -637,9 +639,9 @@ impl UnusedImportBraces { ast::UseTreeKind::Nested(_) => return, }; - cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| - lint.build(&format!("braces around {} is unnecessary", node_name)).emit() - ); + cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| { + lint.build(&format!("braces around {} is unnecessary", node_name)).emit() + }); } } } diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs index fac90525e3234..ecffd615e71c0 100644 --- a/src/librustc_passes/check_attr.rs +++ b/src/librustc_passes/check_attr.rs @@ -102,24 +102,19 @@ impl CheckAttrVisitor<'tcx> { // accidentally, to to be compatible with crates depending on them, we can't throw an // error here. Target::AssocConst => { - self.tcx - .struct_span_lint_hir( - UNUSED_ATTRIBUTES, - hir_id, - attr.span, - |lint| { - lint.build("`#[inline]` is ignored on constants") - .warn( - "this was previously accepted by the compiler but is \ + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build("`#[inline]` is ignored on constants") + .warn( + "this was previously accepted by the compiler but is \ being phased out; it will become a hard error in \ a future release!", - ) - .note( - "see issue #65833 \ + ) + .note( + "see issue #65833 \ for more information", - ) - .emit(); - }); + ) + .emit(); + }); true } _ => { From 0b2436f3a466ff077861665197cf35059c811f48 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 6 Feb 2020 01:27:46 +1000 Subject: [PATCH 08/11] Move more into decorate functions. --- src/librustc_lint/builtin.rs | 30 +++++++++---------- src/librustc_lint/internal.rs | 4 +-- src/librustc_lint/levels.rs | 15 +++++----- src/librustc_lint/unused.rs | 4 +++ src/librustc_mir/borrow_check/mod.rs | 2 +- src/librustc_mir/transform/check_unsafety.rs | 24 +++++++-------- src/librustc_mir/transform/const_prop.rs | 6 ++-- .../hair/pattern/check_match.rs | 16 +++++----- src/librustc_privacy/lib.rs | 8 ++--- 9 files changed, 58 insertions(+), 51 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 23bbcb40c9434..9cc3e39726bd9 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -645,15 +645,15 @@ impl EarlyLintPass for AnonymousParameters { match arg.pat.kind { ast::PatKind::Ident(_, ident, None) => { if ident.name == kw::Invalid { - let ty_snip = cx.sess.source_map().span_to_snippet(arg.ty.span); + cx.struct_span_lint(ANONYMOUS_PARAMETERS, arg.pat.span, |lint| { + let ty_snip = cx.sess.source_map().span_to_snippet(arg.ty.span); - let (ty_snip, appl) = if let Ok(snip) = ty_snip { - (snip, Applicability::MachineApplicable) - } else { - ("".to_owned(), Applicability::HasPlaceholders) - }; + let (ty_snip, appl) = if let Ok(snip) = ty_snip { + (snip, Applicability::MachineApplicable) + } else { + ("".to_owned(), Applicability::HasPlaceholders) + }; - cx.struct_span_lint(ANONYMOUS_PARAMETERS, arg.pat.span, |lint| { lint.build( "anonymous parameters are deprecated and will be \ removed in the next edition.", @@ -869,8 +869,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { if attr::contains_name(&it.attrs, sym::no_mangle) { // Const items do not refer to a particular location in memory, and therefore // don't have anything to attach a symbol to - let msg = "const items should never be `#[no_mangle]`"; cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, |lint| { + let msg = "const items should never be `#[no_mangle]`"; let mut err = lint.build(msg); // account for "pub const" (#45562) @@ -910,11 +910,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) { use rustc_target::spec::abi::Abi::RustIntrinsic; - let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \ - consider instead using an UnsafeCell"; match get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.kind, &ty2.kind)) { Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => { if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not { + let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \ + consider instead using an UnsafeCell"; cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| { lint.build(msg).emit() }); @@ -1335,12 +1335,12 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { let suggestion = "use `..=` for an inclusive range"; if parenthesise { self.node_id = Some(pat.id); - let end = expr_to_string(&end); - let replace = match start { - Some(start) => format!("&({}..={})", expr_to_string(&start), end), - None => format!("&(..={})", end), - }; cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, |lint| { + let end = expr_to_string(&end); + let replace = match start { + Some(start) => format!("&({}..={})", expr_to_string(&start), end), + None => format!("&(..={})", end), + }; lint.build(msg) .span_suggestion( pat.span, diff --git a/src/librustc_lint/internal.rs b/src/librustc_lint/internal.rs index 79a06e81410d0..7875261911201 100644 --- a/src/librustc_lint/internal.rs +++ b/src/librustc_lint/internal.rs @@ -37,9 +37,9 @@ impl_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]); impl EarlyLintPass for DefaultHashTypes { fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { if let Some(replace) = self.map.get(&ident.name) { - // FIXME: We can avoid a copy here. Would require us to take String instead of &str. - let msg = format!("Prefer {} over {}, it has better performance", replace, ident); cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, |lint| { + // FIXME: We can avoid a copy here. Would require us to take String instead of &str. + let msg = format!("Prefer {} over {}, it has better performance", replace, ident); lint.build(&msg) .span_suggestion( ident.span, diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs index b58acac316ef2..da449ed42fd00 100644 --- a/src/librustc_lint/levels.rs +++ b/src/librustc_lint/levels.rs @@ -234,12 +234,6 @@ impl<'s> LintLevelsBuilder<'s> { let lint = builtin::RENAMED_AND_REMOVED_LINTS; let (lvl, src) = self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess); - let msg = format!( - "lint name `{}` is deprecated \ - and may not have an effect in the future. \ - Also `cfg_attr(cargo-clippy)` won't be necessary anymore", - name - ); struct_lint_level( self.sess, lint, @@ -247,6 +241,12 @@ impl<'s> LintLevelsBuilder<'s> { src, Some(li.span().into()), |lint| { + let msg = format!( + "lint name `{}` is deprecated \ + and may not have an effect in the future. \ + Also `cfg_attr(cargo-clippy)` won't be necessary anymore", + name + ); lint.build(&msg) .span_suggestion( li.span(), @@ -306,7 +306,6 @@ impl<'s> LintLevelsBuilder<'s> { let lint = builtin::UNKNOWN_LINTS; let (level, src) = self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess); - let msg = format!("unknown lint: `{}`", name); struct_lint_level( self.sess, lint, @@ -314,7 +313,7 @@ impl<'s> LintLevelsBuilder<'s> { src, Some(li.span().into()), |lint| { - let mut db = lint.build(&msg); + let mut db = lint.build(&format!("unknown lint: `{}`", name)); if let Some(suggestion) = suggestion { db.span_suggestion( li.span(), diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 9cf5ff42c5771..480df99a01eed 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -202,6 +202,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { } // Returns whether an error has been emitted (and thus another does not need to be later). + // FIXME: Args desc_{pre,post}_path could be made lazy by taking Fn() -> &str, but this + // would make calling it a big awkward. Could also take String (so args are moved), but + // this would still require a copy into the format string, which would only be executed + // when needed. fn check_must_use_def( cx: &LateContext<'_, '_>, def_id: DefId, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 4dae7fbe9413d..82a9c631b727e 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -378,8 +378,8 @@ fn do_mir_borrowck<'a, 'tcx>( continue; } - let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); tcx.struct_span_lint_hir(UNUSED_MUT, lint_root, span, |lint| { + let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); lint.build("variable does not need to be mutable") .span_suggestion_short( mut_span, diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 08ef60aa58ea5..6e80338c975ed 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -516,18 +516,18 @@ fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: DefId) { .as_local_hir_id(def_id) .unwrap_or_else(|| bug!("checking unsafety for non-local def id {:?}", def_id)); - // FIXME: when we make this a hard error, this should have its - // own error code. - let message = if tcx.generics_of(def_id).own_requires_monomorphization() { - "`#[derive]` can't be used on a `#[repr(packed)]` struct with \ - type or const parameters (error E0133)" - .to_string() - } else { - "`#[derive]` can't be used on a `#[repr(packed)]` struct that \ - does not derive Copy (error E0133)" - .to_string() - }; tcx.struct_span_lint_hir(SAFE_PACKED_BORROWS, lint_hir_id, tcx.def_span(def_id), |lint| { + // FIXME: when we make this a hard error, this should have its + // own error code. + let message = if tcx.generics_of(def_id).own_requires_monomorphization() { + "`#[derive]` can't be used on a `#[repr(packed)]` struct with \ + type or const parameters (error E0133)" + .to_string() + } else { + "`#[derive]` can't be used on a `#[repr(packed)]` struct that \ + does not derive Copy (error E0133)" + .to_string() + }; lint.build(&message).emit() }); } @@ -560,8 +560,8 @@ fn is_enclosed( fn report_unused_unsafe(tcx: TyCtxt<'_>, used_unsafe: &FxHashSet, id: hir::HirId) { let span = tcx.sess.source_map().def_span(tcx.hir().span(id)); - let msg = "unnecessary `unsafe` block"; tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, |lint| { + let msg = "unnecessary `unsafe` block"; let mut db = lint.build(msg); db.span_label(span, msg); if let Some((kind, id)) = is_enclosed(tcx, used_unsafe, id) { diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 9a2e2c56f1426..14c0db2def285 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -556,12 +556,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); if r_bits.map_or(false, |b| b >= left_bits as u128) { let lint_root = self.lint_root(source_info)?; - let dir = if op == BinOp::Shr { "right" } else { "left" }; self.tcx.struct_span_lint_hir( ::rustc::lint::builtin::EXCEEDING_BITSHIFTS, lint_root, source_info.span, - |lint| lint.build(&format!("attempt to shift {} with overflow", dir)).emit(), + |lint| { + let dir = if op == BinOp::Shr { "right" } else { "left" }; + lint.build(&format!("attempt to shift {} with overflow", dir)).emit() + }, ); return None; } diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index acb9829ce5f37..651f2f70d9bfb 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -286,12 +286,12 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa variant.ident == ident && variant.ctor_kind == CtorKind::Const }) { - let ty_path = cx.tcx.def_path_str(edef.did); cx.tcx.struct_span_lint_hir( BINDINGS_WITH_VARIANT_NAME, p.hir_id, p.span, |lint| { + let ty_path = cx.tcx.def_path_str(edef.did); lint.build(&format!( "pattern binding `{}` is named the same as one \ of the variants of the type `{}`", @@ -338,12 +338,14 @@ fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option< } fn irrefutable_let_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, source: hir::MatchSource) { - let msg = match source { - hir::MatchSource::IfLetDesugar { .. } => "irrefutable if-let pattern", - hir::MatchSource::WhileLetDesugar => "irrefutable while-let pattern", - _ => bug!(), - }; - tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| lint.build(msg).emit()); + tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| { + let msg = match source { + hir::MatchSource::IfLetDesugar { .. } => "irrefutable if-let pattern", + hir::MatchSource::WhileLetDesugar => "irrefutable while-let pattern", + _ => bug!(), + }; + lint.build(msg).emit() + }); } /// Check for unreachable patterns. diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 7f51bc25642b5..ef1e99c5a64be 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1805,12 +1805,12 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { let (vis, vis_span, vis_descr) = def_id_visibility(self.tcx, def_id); if !vis.is_at_least(self.required_visibility, self.tcx) { - let msg = format!("{} {} `{}` in public interface", vis_descr, kind, descr); + let make_msg = || format!("{} {} `{}` in public interface", vis_descr, kind, descr); if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty { let mut err = if kind == "trait" { - struct_span_err!(self.tcx.sess, self.span, E0445, "{}", msg) + struct_span_err!(self.tcx.sess, self.span, E0445, "{}", make_msg()) } else { - struct_span_err!(self.tcx.sess, self.span, E0446, "{}", msg) + struct_span_err!(self.tcx.sess, self.span, E0446, "{}", make_msg()) }; err.span_label(self.span, format!("can't leak {} {}", vis_descr, kind)); err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr)); @@ -1821,7 +1821,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { lint::builtin::PRIVATE_IN_PUBLIC, hir_id, self.span, - |lint| lint.build(&format!("{} (error {})", msg, err_code)).emit(), + |lint| lint.build(&format!("{} (error {})", make_msg(), err_code)).emit(), ); } } From 284982df6047ad8a259a3cb0698706ccdfd20946 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 6 Feb 2020 01:28:23 +1000 Subject: [PATCH 09/11] Address review nitpicks. --- src/librustc_lint/context.rs | 4 ++-- src/librustc_lint/early.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs index 232b56c88f2b0..f3cbd3f1c9ef9 100644 --- a/src/librustc_lint/context.rs +++ b/src/librustc_lint/context.rs @@ -474,10 +474,10 @@ pub trait LintContext: Sized { fn sess(&self) -> &Session; fn lints(&self) -> &LintStore; - fn lookup_with_diagnostics>( + fn lookup_with_diagnostics( &self, lint: &'static Lint, - span: Option, + span: Option>, decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>), diagnostic: BuiltinLintDiagnostics, ) { diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs index a636e7540fb0d..c351159067387 100644 --- a/src/librustc_lint/early.rs +++ b/src/librustc_lint/early.rs @@ -41,11 +41,11 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { span, msg, node_id: _, - lint_id: _, + lint_id, diagnostic, } = early_lint; self.context.lookup_with_diagnostics( - early_lint.lint_id.lint, + lint_id.lint, Some(span), |lint| lint.build(&msg).emit(), diagnostic, From e45099619334bbf4413b40ff07a100ce72ace96a Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 6 Feb 2020 03:18:40 +1000 Subject: [PATCH 10/11] Avoid allocs in a few places. - AnonymousParameters::check_trait_item - TypeAliasBounds::check_item - NonSnakeCase::check_snake_case --- src/librustc_lint/builtin.rs | 22 +++++++++++----------- src/librustc_lint/context.rs | 2 ++ src/librustc_lint/nonstandard_style.rs | 3 +-- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 9cc3e39726bd9..c827a7f3d5283 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -648,10 +648,10 @@ impl EarlyLintPass for AnonymousParameters { cx.struct_span_lint(ANONYMOUS_PARAMETERS, arg.pat.span, |lint| { let ty_snip = cx.sess.source_map().span_to_snippet(arg.ty.span); - let (ty_snip, appl) = if let Ok(snip) = ty_snip { - (snip, Applicability::MachineApplicable) + let (ty_snip, appl) = if let Ok(ref snip) = ty_snip { + (snip.as_str(), Applicability::MachineApplicable) } else { - ("".to_owned(), Applicability::HasPlaceholders) + ("", Applicability::HasPlaceholders) }; lint.build( @@ -1132,17 +1132,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { let mut suggested_changing_assoc_types = false; // There must not be a where clause if !type_alias_generics.where_clause.predicates.is_empty() { - let spans: Vec<_> = type_alias_generics - .where_clause - .predicates - .iter() - .map(|pred| pred.span()) - .collect(); - cx.struct_span_lint( + cx.lint( TYPE_ALIAS_BOUNDS, - spans, |lint| { let mut err = lint.build("where clauses are not enforced in type aliases"); + let spans: Vec<_> = type_alias_generics + .where_clause + .predicates + .iter() + .map(|pred| pred.span()) + .collect(); + err.set_span(spans); err.span_suggestion( type_alias_generics.where_clause.span_for_predicates_or_empty_place(), "the clause will not be checked when the type alias is used, and should be removed", diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs index f3cbd3f1c9ef9..8e8beefa72f13 100644 --- a/src/librustc_lint/context.rs +++ b/src/librustc_lint/context.rs @@ -571,6 +571,8 @@ pub trait LintContext: Sized { }); } + // FIXME: These methods should not take an Into -- instead, callers should need to + // set the span in their `decorate` function (preferably using set_span). fn lookup>( &self, lint: &'static Lint, diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index d45ea10dfbf58..8c58f2ba4c07a 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -225,9 +225,8 @@ impl NonSnakeCase { let name = &ident.name.as_str(); if !is_snake_case(name) { - let sc = NonSnakeCase::to_snake_case(name); - cx.struct_span_lint(NON_SNAKE_CASE, ident.span, |lint| { + let sc = NonSnakeCase::to_snake_case(name); let msg = format!("{} `{}` should have a snake case name", sort, name); let mut err = lint.build(&msg); // We have a valid span in almost all cases, but we don't have one when linting a crate From b959da2f4cd2cf8f4b170369355fe7329cf5a9c9 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 6 Feb 2020 20:22:25 +1000 Subject: [PATCH 11/11] Fix stage2 test failures from call to span_lint. span_lint was removed. Callers should use the `lint` method now, and call `set_span` within the closure passed to this method. --- .../auxiliary/issue-40001-plugin.rs | 34 +++++++++++-------- .../auxiliary/lint-for-crate-rpass.rs | 14 +++++--- .../ui-fulldeps/auxiliary/lint-for-crate.rs | 15 +++++--- .../auxiliary/lint-group-plugin-test.rs | 24 +++++++++---- .../ui-fulldeps/auxiliary/lint-plugin-test.rs | 12 ++++--- .../ui-fulldeps/auxiliary/lint-tool-test.rs | 24 +++++++++---- 6 files changed, 80 insertions(+), 43 deletions(-) diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs index fbdad29d6494f..91b3372e8f415 100644 --- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -4,17 +4,19 @@ extern crate rustc_ast_pretty; extern crate rustc_driver; extern crate rustc_hir; -#[macro_use] extern crate rustc_lint; -#[macro_use] extern crate rustc_session; +#[macro_use] +extern crate rustc_lint; +#[macro_use] +extern crate rustc_session; extern crate rustc_span; extern crate syntax; use rustc_ast_pretty::pprust; -use rustc_hir::intravisit; +use rustc_driver::plugin::Registry; use rustc_hir as hir; +use rustc_hir::intravisit; use rustc_hir::Node; -use rustc_lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext}; -use rustc_driver::plugin::Registry; +use rustc_lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc_span::source_map; #[plugin_registrar] @@ -32,14 +34,15 @@ declare_lint! { declare_lint_pass!(MissingWhitelistedAttrPass => [MISSING_WHITELISTED_ATTR]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingWhitelistedAttrPass { - fn check_fn(&mut self, - cx: &LateContext<'a, 'tcx>, - _: intravisit::FnKind<'tcx>, - _: &'tcx hir::FnDecl, - _: &'tcx hir::Body, - span: source_map::Span, - id: hir::HirId) { - + fn check_fn( + &mut self, + cx: &LateContext<'a, 'tcx>, + _: intravisit::FnKind<'tcx>, + _: &'tcx hir::FnDecl, + _: &'tcx hir::Body, + span: source_map::Span, + id: hir::HirId, + ) { let item = match cx.tcx.hir().get(id) { Node::Item(item) => item, _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id)), @@ -47,8 +50,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingWhitelistedAttrPass { let whitelisted = |attr| pprust::attribute_to_string(attr).contains("whitelisted_attr"); if !item.attrs.iter().any(whitelisted) { - cx.span_lint(MISSING_WHITELISTED_ATTR, span, - "Missing 'whitelisted_attr' attribute"); + cx.lint(MISSING_WHITELISTED_ATTR, |lint| { + lint.build("Missing 'whitelisted_attr' attribute").set_span(span).emit() + }); } } } diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs index 98963a180c850..eb251a0a3adb8 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs @@ -5,12 +5,14 @@ extern crate rustc_driver; extern crate rustc_hir; extern crate rustc_span; -#[macro_use] extern crate rustc_lint; -#[macro_use] extern crate rustc_session; +#[macro_use] +extern crate rustc_lint; +#[macro_use] +extern crate rustc_session; extern crate syntax; -use rustc_lint::{LateContext, LintContext, LintPass, LateLintPass}; use rustc_driver::plugin::Registry; +use rustc_lint::{LateContext, LateLintPass, LintContext, LintPass}; use rustc_span::symbol::Symbol; use syntax::attr; @@ -28,8 +30,10 @@ macro_rules! fake_lint_pass { fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) { $( if !attr::contains_name(&krate.attrs, $attr) { - cx.span_lint(CRATE_NOT_OKAY, krate.span, - &format!("crate is not marked with #![{}]", $attr)); + cx.lint(CRATE_NOT_OKAY, |lint| { + let msg = format!("crate is not marked with #![{}]", $attr); + lint.build(&msg).set_span(krate.span).emit() + }); } )* } diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs index 589477da62527..e5f4bf88d57aa 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -5,13 +5,15 @@ extern crate rustc_driver; extern crate rustc_hir; -#[macro_use] extern crate rustc_lint; -#[macro_use] extern crate rustc_session; +#[macro_use] +extern crate rustc_lint; +#[macro_use] +extern crate rustc_session; extern crate rustc_span; extern crate syntax; -use rustc_lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray}; use rustc_driver::plugin::Registry; +use rustc_lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc_span::symbol::Symbol; use syntax::attr; @@ -26,8 +28,11 @@ declare_lint_pass!(Pass => [CRATE_NOT_OKAY]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) { if !attr::contains_name(&krate.attrs, Symbol::intern("crate_okay")) { - cx.span_lint(CRATE_NOT_OKAY, krate.span, - "crate is not marked with #![crate_okay]"); + cx.lint(CRATE_NOT_OKAY, |lint| { + lint.build("crate is not marked with #![crate_okay]") + .set_span(krate.span) + .emit() + }); } } } diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs index 2cc288c21e697..5a8eaa63db2f8 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs @@ -6,11 +6,13 @@ // Load rustc as a plugin to get macros. extern crate rustc_driver; extern crate rustc_hir; -#[macro_use] extern crate rustc_lint; -#[macro_use] extern crate rustc_session; +#[macro_use] +extern crate rustc_lint; +#[macro_use] +extern crate rustc_session; -use rustc_lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray, LintId}; use rustc_driver::plugin::Registry; +use rustc_lint::{LateContext, LateLintPass, LintArray, LintContext, LintId, LintPass}; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); @@ -21,8 +23,12 @@ declare_lint_pass!(Pass => [TEST_LINT, PLEASE_LINT]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_item(&mut self, cx: &LateContext, it: &rustc_hir::Item) { match &*it.ident.as_str() { - "lintme" => cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"), - "pleaselintme" => cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'"), + "lintme" => cx.lint(TEST_LINT, |lint| { + lint.build("item is named 'lintme'").set_span(it.span).emit() + }), + "pleaselintme" => cx.lint(PLEASE_LINT, |lint| { + lint.build("item is named 'pleaselintme'").set_span(it.span).emit() + }), _ => {} } } @@ -32,6 +38,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { pub fn plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&TEST_LINT, &PLEASE_LINT]); reg.lint_store.register_late_pass(|| box Pass); - reg.lint_store.register_group(true, "lint_me", None, - vec![LintId::of(&TEST_LINT), LintId::of(&PLEASE_LINT)]); + reg.lint_store.register_group( + true, + "lint_me", + None, + vec![LintId::of(&TEST_LINT), LintId::of(&PLEASE_LINT)], + ); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs index c704701cc480b..ad5f882c43434 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs @@ -7,11 +7,13 @@ extern crate syntax; // Load rustc as a plugin to get macros extern crate rustc_driver; -#[macro_use] extern crate rustc_lint; -#[macro_use] extern crate rustc_session; +#[macro_use] +extern crate rustc_lint; +#[macro_use] +extern crate rustc_session; -use rustc_lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, LintArray}; use rustc_driver::plugin::Registry; +use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use syntax::ast; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); @@ -20,7 +22,9 @@ declare_lint_pass!(Pass => [TEST_LINT]); impl EarlyLintPass for Pass { fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { if it.ident.name.as_str() == "lintme" { - cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); + cx.lint(TEST_LINT, |lint| { + lint.build("item is named 'lintme'").set_span(it.span).emit() + }); } } } diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs index fa545ddc2bc6b..b14dbdf8f938b 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs @@ -5,11 +5,13 @@ extern crate syntax; // Load rustc as a plugin to get macros extern crate rustc_driver; -#[macro_use] extern crate rustc_lint; -#[macro_use] extern crate rustc_session; +#[macro_use] +extern crate rustc_lint; +#[macro_use] +extern crate rustc_session; -use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass, LintId}; use rustc_driver::plugin::Registry; +use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintId, LintPass}; use syntax::ast; declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff"); declare_tool_lint!( @@ -30,10 +32,14 @@ declare_lint_pass!(Pass => [TEST_LINT, TEST_GROUP, TEST_RUSTC_TOOL_LINT]); impl EarlyLintPass for Pass { fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { if it.ident.name.as_str() == "lintme" { - cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); + cx.lint(TEST_LINT, |lint| { + lint.build("item is named 'lintme'").set_span(it.span).emit() + }); } if it.ident.name.as_str() == "lintmetoo" { - cx.span_lint(TEST_GROUP, it.span, "item is named 'lintmetoo'"); + cx.lint(TEST_GROUP, |lint| { + lint.build("item is named 'lintmetoo'").set_span(it.span).emit() + }); } } } @@ -42,6 +48,10 @@ impl EarlyLintPass for Pass { pub fn plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&TEST_RUSTC_TOOL_LINT, &TEST_LINT, &TEST_GROUP]); reg.lint_store.register_early_pass(|| box Pass); - reg.lint_store.register_group(true, "clippy::group", Some("clippy_group"), - vec![LintId::of(&TEST_LINT), LintId::of(&TEST_GROUP)]); + reg.lint_store.register_group( + true, + "clippy::group", + Some("clippy_group"), + vec![LintId::of(&TEST_LINT), LintId::of(&TEST_GROUP)], + ); }