diff options
| author | jumbatm <jumbatm@gmail.com> | 2020-02-02 19:41:14 +1000 |
|---|---|---|
| committer | jumbatm <jumbatm@gmail.com> | 2020-02-11 19:49:01 +1000 |
| commit | 2f0430a163bb2f4fe6545064391606bb736e9e51 (patch) | |
| tree | f31051b5d0d597131a62d983abfa00348ccb14e7 | |
| parent | b2e78faa15263011dad1e9579fc59610d5b75579 (diff) | |
| download | rust-2f0430a163bb2f4fe6545064391606bb736e9e51.tar.gz rust-2f0430a163bb2f4fe6545064391606bb736e9e51.zip | |
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.
| -rw-r--r-- | src/librustc_lint/builtin.rs | 50 | ||||
| -rw-r--r-- | src/librustc_lint/context.rs | 57 | ||||
| -rw-r--r-- | src/librustc_lint/early.rs | 9 | ||||
| -rw-r--r-- | src/librustc_lint/types.rs | 22 | ||||
| -rw-r--r-- | src/librustc_lint/unused.rs | 53 | ||||
| -rw-r--r-- | 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 9fc81a4a1fd..7ebedd29cc4 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 d9ad97654e0..232b56c88f2 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<S: Into<MultiSpan>>(&self, lint: &'static Lint, span: Option<S>, msg: &str) { - self.lookup(lint, span, |lint| lint.build(msg).emit()); - } - - fn lookup_and_emit_with_diagnostics<S: Into<MultiSpan>>( + fn lookup_with_diagnostics<S: Into<MultiSpan>>( &self, lint: &'static Lint, span: Option<S>, - 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<S: Into<MultiSpan>>(&self, lint: &'static Lint, span: S, msg: &str) { - self.lookup_and_emit(lint, Some(span), msg); - } - fn struct_span_lint<S: Into<MultiSpan>>( &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<Span>, msg); + fn lint(&self, lint: &'static Lint, decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) { + self.lookup(lint, None as Option<Span>, decorate); } } diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs index 27781eb41d2..4f337cd18aa 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 d1982e9162e..f6404fb63d4 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 2f4a9572a83..faa0b019311 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 1b4f0ffce9c..b661006d1dd 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(); } } } |
