Skip to content

Commit eaf8fa7

Browse files
committed
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.
1 parent a1e8d54 commit eaf8fa7

File tree

5 files changed

+82
-113
lines changed

5 files changed

+82
-113
lines changed

src/librustc_lint/builtin.rs

+27-27
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use rustc::ty::{self, layout::VariantIdx, Ty, TyCtxt};
2828
use rustc_ast_pretty::pprust::{self, expr_to_string};
2929
use rustc_data_structures::fx::FxHashSet;
3030
use rustc_errors::{Applicability, DiagnosticBuilder};
31+
use rustc::lint::LintDiagnosticBuilder;
3132
use rustc_feature::Stability;
3233
use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, AttributeType};
3334
use rustc_hir as hir;
@@ -106,8 +107,7 @@ impl BoxPointers {
106107
fn check_heap_type(&self, cx: &LateContext<'_, '_>, span: Span, ty: Ty<'_>) {
107108
for leaf_ty in ty.walk() {
108109
if leaf_ty.is_box() {
109-
let m = format!("type uses owned (Box type) pointers: {}", ty);
110-
cx.span_lint(BOX_POINTERS, span, &m);
110+
cx.struct_span_lint(BOX_POINTERS, span, |lint| lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit());
111111
}
112112
}
113113
}
@@ -214,13 +214,13 @@ declare_lint! {
214214
declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]);
215215

216216
impl UnsafeCode {
217-
fn report_unsafe(&self, cx: &EarlyContext<'_>, span: Span, desc: &'static str) {
217+
fn report_unsafe(&self, cx: &EarlyContext<'_>, span: Span, decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) {
218218
// This comes from a macro that has `#[allow_internal_unsafe]`.
219219
if span.allows_unsafe() {
220220
return;
221221
}
222222

223-
cx.span_lint(UNSAFE_CODE, span, desc);
223+
cx.struct_span_lint(UNSAFE_CODE, span, decorate);
224224
}
225225
}
226226

@@ -230,9 +230,9 @@ impl EarlyLintPass for UnsafeCode {
230230
self.report_unsafe(
231231
cx,
232232
attr.span,
233-
"`allow_internal_unsafe` allows defining \
233+
|lint| lint.build("`allow_internal_unsafe` allows defining \
234234
macros using unsafe without triggering \
235-
the `unsafe_code` lint at their call site",
235+
the `unsafe_code` lint at their call site").emit(),
236236
);
237237
}
238238
}
@@ -241,19 +241,19 @@ impl EarlyLintPass for UnsafeCode {
241241
if let ast::ExprKind::Block(ref blk, _) = e.kind {
242242
// Don't warn about generated blocks; that'll just pollute the output.
243243
if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
244-
self.report_unsafe(cx, blk.span, "usage of an `unsafe` block");
244+
self.report_unsafe(cx, blk.span, |lint| lint.build("usage of an `unsafe` block").emit());
245245
}
246246
}
247247
}
248248

249249
fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
250250
match it.kind {
251251
ast::ItemKind::Trait(_, ast::Unsafety::Unsafe, ..) => {
252-
self.report_unsafe(cx, it.span, "declaration of an `unsafe` trait")
252+
self.report_unsafe(cx, it.span, |lint| lint.build("declaration of an `unsafe` trait").emit())
253253
}
254254

255255
ast::ItemKind::Impl { unsafety: ast::Unsafety::Unsafe, .. } => {
256-
self.report_unsafe(cx, it.span, "implementation of an `unsafe` trait")
256+
self.report_unsafe(cx, it.span, |lint| lint.build("implementation of an `unsafe` trait").emit())
257257
}
258258

259259
_ => return,
@@ -270,12 +270,12 @@ impl EarlyLintPass for UnsafeCode {
270270
) {
271271
match fk {
272272
FnKind::ItemFn(_, ast::FnHeader { unsafety: ast::Unsafety::Unsafe, .. }, ..) => {
273-
self.report_unsafe(cx, span, "declaration of an `unsafe` function")
273+
self.report_unsafe(cx, span, |lint| lint.build("declaration of an `unsafe` function").emit())
274274
}
275275

276276
FnKind::Method(_, sig, ..) => {
277277
if sig.header.unsafety == ast::Unsafety::Unsafe {
278-
self.report_unsafe(cx, span, "implementation of an `unsafe` method")
278+
self.report_unsafe(cx, span, |lint| lint.build("implementation of an `unsafe` method").emit())
279279
}
280280
}
281281

@@ -286,7 +286,7 @@ impl EarlyLintPass for UnsafeCode {
286286
fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &ast::AssocItem) {
287287
if let ast::AssocItemKind::Fn(ref sig, None) = item.kind {
288288
if sig.header.unsafety == ast::Unsafety::Unsafe {
289-
self.report_unsafe(cx, item.span, "declaration of an `unsafe` method")
289+
self.report_unsafe(cx, item.span, |lint| lint.build("declaration of an `unsafe` method").emit())
290290
}
291291
}
292292
}
@@ -372,10 +372,10 @@ impl MissingDoc {
372372

373373
let has_doc = attrs.iter().any(|a| has_doc(a));
374374
if !has_doc {
375-
cx.span_lint(
375+
cx.struct_span_lint(
376376
MISSING_DOCS,
377377
cx.tcx.sess.source_map().def_span(sp),
378-
&format!("missing documentation for {}", desc),
378+
|lint| lint.build(&format!("missing documentation for {}", desc)).emit(),
379379
);
380380
}
381381
}
@@ -404,10 +404,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
404404
for macro_def in krate.exported_macros {
405405
let has_doc = macro_def.attrs.iter().any(|a| has_doc(a));
406406
if !has_doc {
407-
cx.span_lint(
407+
cx.struct_span_lint(
408408
MISSING_DOCS,
409409
cx.tcx.sess.source_map().def_span(macro_def.span),
410-
"missing documentation for macro",
410+
|lint| lint.build("missing documentation for macro").emit(),
411411
);
412412
}
413413
}
@@ -555,11 +555,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations {
555555
return;
556556
}
557557
if can_type_implement_copy(cx.tcx, param_env, ty).is_ok() {
558-
cx.span_lint(
558+
cx.struct_span_lint(
559559
MISSING_COPY_IMPLEMENTATIONS,
560560
item.span,
561-
"type could implement `Copy`; consider adding `impl \
562-
Copy`",
561+
|lint| lint.build("type could implement `Copy`; consider adding `impl \
562+
Copy`").emit(),
563563
)
564564
}
565565
}
@@ -609,11 +609,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
609609
}
610610

611611
if !self.impling_types.as_ref().unwrap().contains(&item.hir_id) {
612-
cx.span_lint(
612+
cx.struct_span_lint(
613613
MISSING_DEBUG_IMPLEMENTATIONS,
614614
item.span,
615-
"type does not implement `fmt::Debug`; consider adding `#[derive(Debug)]` \
616-
or a manual implementation",
615+
|lint| lint.build("type does not implement `fmt::Debug`; consider adding `#[derive(Debug)]` \
616+
or a manual implementation").emit(),
617617
)
618618
}
619619
}
@@ -912,7 +912,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
912912
match get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.kind, &ty2.kind)) {
913913
Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => {
914914
if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
915-
cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg);
915+
cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| lint.build(msg).emit());
916916
}
917917
}
918918
_ => (),
@@ -962,7 +962,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures {
962962
if attr.check_name(sym::feature) {
963963
if let Some(items) = attr.meta_item_list() {
964964
for item in items {
965-
ctx.span_lint(UNSTABLE_FEATURES, item.span(), "unstable feature");
965+
ctx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| lint.build("unstable feature").emit());
966966
}
967967
}
968968
}
@@ -1244,14 +1244,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
12441244
ConstEvaluatable(..) => continue,
12451245
};
12461246
if predicate.is_global() {
1247-
cx.span_lint(
1247+
cx.struct_span_lint(
12481248
TRIVIAL_BOUNDS,
12491249
span,
1250-
&format!(
1250+
|lint| lint.build(&format!(
12511251
"{} bound {} does not depend on any type \
12521252
or lifetime parameters",
12531253
predicate_kind_name, predicate
1254-
),
1254+
)).emit(),
12551255
);
12561256
}
12571257
}

src/librustc_lint/context.rs

+10-47
Original file line numberDiff line numberDiff line change
@@ -474,19 +474,18 @@ pub trait LintContext: Sized {
474474
fn sess(&self) -> &Session;
475475
fn lints(&self) -> &LintStore;
476476

477-
fn lookup_and_emit<S: Into<MultiSpan>>(&self, lint: &'static Lint, span: Option<S>, msg: &str) {
478-
self.lookup(lint, span, |lint| lint.build(msg).emit());
479-
}
480-
481-
fn lookup_and_emit_with_diagnostics<S: Into<MultiSpan>>(
477+
fn lookup_with_diagnostics<S: Into<MultiSpan>>(
482478
&self,
483479
lint: &'static Lint,
484480
span: Option<S>,
485-
msg: &str,
481+
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
486482
diagnostic: BuiltinLintDiagnostics,
487483
) {
488484
self.lookup(lint, span, |lint| {
489-
let mut db = lint.build(msg);
485+
// We first generate a blank diagnostic.
486+
let mut db = lint.build("");
487+
488+
// Now, set up surrounding context.
490489
let sess = self.sess();
491490
match diagnostic {
492491
BuiltinLintDiagnostics::Normal => (),
@@ -567,8 +566,8 @@ pub trait LintContext: Sized {
567566
stability::deprecation_suggestion(&mut db, suggestion, span)
568567
}
569568
}
570-
571-
db.emit();
569+
// Rewrap `db`, and pass control to the user.
570+
decorate(LintDiagnosticBuilder::new(db));
572571
});
573572
}
574573

@@ -579,11 +578,6 @@ pub trait LintContext: Sized {
579578
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
580579
);
581580

582-
/// Emit a lint at the appropriate level, for a particular span.
583-
fn span_lint<S: Into<MultiSpan>>(&self, lint: &'static Lint, span: S, msg: &str) {
584-
self.lookup_and_emit(lint, Some(span), msg);
585-
}
586-
587581
fn struct_span_lint<S: Into<MultiSpan>>(
588582
&self,
589583
lint: &'static Lint,
@@ -592,40 +586,9 @@ pub trait LintContext: Sized {
592586
) {
593587
self.lookup(lint, Some(span), decorate);
594588
}
595-
596-
/// Emit a lint and note at the appropriate level, for a particular span.
597-
fn span_lint_note(
598-
&self,
599-
lint: &'static Lint,
600-
span: Span,
601-
msg: &str,
602-
note_span: Span,
603-
note: &str,
604-
) {
605-
self.lookup(lint, Some(span), |lint| {
606-
let mut err = lint.build(msg);
607-
if note_span == span {
608-
err.note(note);
609-
} else {
610-
err.span_note(note_span, note);
611-
}
612-
err.emit();
613-
});
614-
}
615-
616-
/// Emit a lint and help at the appropriate level, for a particular span.
617-
fn span_lint_help(&self, lint: &'static Lint, span: Span, msg: &str, help: &str) {
618-
self.lookup(lint, Some(span), |err| {
619-
let mut err = err.build(msg);
620-
self.span_lint(lint, span, msg);
621-
err.span_help(span, help);
622-
err.emit();
623-
});
624-
}
625-
626589
/// Emit a lint at the appropriate level, with no associated span.
627-
fn lint(&self, lint: &'static Lint, msg: &str) {
628-
self.lookup_and_emit(lint, None as Option<Span>, msg);
590+
fn lint(&self, lint: &'static Lint, decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) {
591+
self.lookup(lint, None as Option<Span>, decorate);
629592
}
630593
}
631594

src/librustc_lint/early.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ struct EarlyContextAndPass<'a, T: EarlyLintPass> {
3737
impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
3838
fn check_id(&mut self, id: ast::NodeId) {
3939
for early_lint in self.context.buffered.take(id) {
40-
self.context.lookup_and_emit_with_diagnostics(
40+
let rustc_session::lint::BufferedEarlyLint { span, msg, node_id: _, lint_id: _, diagnostic } = early_lint;
41+
self.context.lookup_with_diagnostics(
4142
early_lint.lint_id.lint,
42-
Some(early_lint.span.clone()),
43-
&early_lint.msg,
44-
early_lint.diagnostic,
43+
Some(span),
44+
|lint| lint.build(&msg).emit(),
45+
diagnostic,
4546
);
4647
}
4748
}

src/librustc_lint/types.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,10 @@ fn lint_int_literal<'a, 'tcx>(
266266
}
267267
}
268268

269-
cx.span_lint(
269+
cx.struct_span_lint(
270270
OVERFLOWING_LITERALS,
271271
e.span,
272-
&format!("literal out of range for `{}`", t.name_str()),
272+
|lint| lint.build(&format!("literal out of range for `{}`", t.name_str())).emit(),
273273
);
274274
}
275275
}
@@ -321,10 +321,10 @@ fn lint_uint_literal<'a, 'tcx>(
321321
report_bin_hex_error(cx, e, attr::IntType::UnsignedInt(t), repr_str, lit_val, false);
322322
return;
323323
}
324-
cx.span_lint(
324+
cx.struct_span_lint(
325325
OVERFLOWING_LITERALS,
326326
e.span,
327-
&format!("literal out of range for `{}`", t.name_str()),
327+
|lint| lint.build(&format!("literal out of range for `{}`", t.name_str())).emit(),
328328
);
329329
}
330330
}
@@ -355,10 +355,10 @@ fn lint_literal<'a, 'tcx>(
355355
_ => bug!(),
356356
};
357357
if is_infinite == Ok(true) {
358-
cx.span_lint(
358+
cx.struct_span_lint(
359359
OVERFLOWING_LITERALS,
360360
e.span,
361-
&format!("literal out of range for `{}`", t.name_str()),
361+
|lint| lint.build(&format!("literal out of range for `{}`", t.name_str())).emit(),
362362
);
363363
}
364364
}
@@ -377,10 +377,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
377377
}
378378
hir::ExprKind::Binary(binop, ref l, ref r) => {
379379
if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
380-
cx.span_lint(
380+
cx.struct_span_lint(
381381
UNUSED_COMPARISONS,
382382
e.span,
383-
"comparison is useless due to type limits",
383+
|lint| lint.build("comparison is useless due to type limits").emit(),
384384
);
385385
}
386386
}
@@ -1055,14 +1055,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
10551055
// We only warn if the largest variant is at least thrice as large as
10561056
// the second-largest.
10571057
if largest > slargest * 3 && slargest > 0 {
1058-
cx.span_lint(
1058+
cx.struct_span_lint(
10591059
VARIANT_SIZE_DIFFERENCES,
10601060
enum_definition.variants[largest_index].span,
1061-
&format!(
1061+
|lint| lint.build(&format!(
10621062
"enum variant is more than three times \
10631063
larger ({} bytes) than the next largest",
10641064
largest
1065-
),
1065+
)).emit(),
10661066
);
10671067
}
10681068
}

0 commit comments

Comments
 (0)