Skip to content

Commit 2f0430a

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 b2e78fa commit 2f0430a

File tree

6 files changed

+85
-114
lines changed

6 files changed

+85
-114
lines changed

src/librustc_lint/builtin.rs

+25-25
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,
@@ -275,7 +275,7 @@ impl EarlyLintPass for UnsafeCode {
275275
FnCtxt::Assoc(_) if body.is_none() => "declaration of an `unsafe` method",
276276
FnCtxt::Assoc(_) => "implementation of an `unsafe` method",
277277
};
278-
self.report_unsafe(cx, span, msg);
278+
self.report_unsafe(cx, span, |lint| lint.build(msg).emit());
279279
}
280280
}
281281
}
@@ -360,10 +360,10 @@ impl MissingDoc {
360360

361361
let has_doc = attrs.iter().any(|a| has_doc(a));
362362
if !has_doc {
363-
cx.span_lint(
363+
cx.struct_span_lint(
364364
MISSING_DOCS,
365365
cx.tcx.sess.source_map().def_span(sp),
366-
&format!("missing documentation for {}", desc),
366+
|lint| lint.build(&format!("missing documentation for {}", desc)).emit(),
367367
);
368368
}
369369
}
@@ -392,10 +392,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
392392
for macro_def in krate.exported_macros {
393393
let has_doc = macro_def.attrs.iter().any(|a| has_doc(a));
394394
if !has_doc {
395-
cx.span_lint(
395+
cx.struct_span_lint(
396396
MISSING_DOCS,
397397
cx.tcx.sess.source_map().def_span(macro_def.span),
398-
"missing documentation for macro",
398+
|lint| lint.build("missing documentation for macro").emit(),
399399
);
400400
}
401401
}
@@ -543,11 +543,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations {
543543
return;
544544
}
545545
if can_type_implement_copy(cx.tcx, param_env, ty).is_ok() {
546-
cx.span_lint(
546+
cx.struct_span_lint(
547547
MISSING_COPY_IMPLEMENTATIONS,
548548
item.span,
549-
"type could implement `Copy`; consider adding `impl \
550-
Copy`",
549+
|lint| lint.build("type could implement `Copy`; consider adding `impl \
550+
Copy`").emit(),
551551
)
552552
}
553553
}
@@ -597,14 +597,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
597597
}
598598

599599
if !self.impling_types.as_ref().unwrap().contains(&item.hir_id) {
600-
cx.span_lint(
600+
cx.struct_span_lint(
601601
MISSING_DEBUG_IMPLEMENTATIONS,
602602
item.span,
603-
&format!(
603+
|lint| lint.build(&format!(
604604
"type does not implement `{}`; consider adding `#[derive(Debug)]` \
605605
or a manual implementation",
606606
cx.tcx.def_path_str(debug)
607-
),
607+
)).emit(),
608608
);
609609
}
610610
}
@@ -903,7 +903,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
903903
match get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.kind, &ty2.kind)) {
904904
Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => {
905905
if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
906-
cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg);
906+
cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| lint.build(msg).emit());
907907
}
908908
}
909909
_ => (),
@@ -953,7 +953,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures {
953953
if attr.check_name(sym::feature) {
954954
if let Some(items) = attr.meta_item_list() {
955955
for item in items {
956-
ctx.span_lint(UNSTABLE_FEATURES, item.span(), "unstable feature");
956+
ctx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| lint.build("unstable feature").emit());
957957
}
958958
}
959959
}
@@ -1235,14 +1235,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
12351235
ConstEvaluatable(..) => continue,
12361236
};
12371237
if predicate.is_global() {
1238-
cx.span_lint(
1238+
cx.struct_span_lint(
12391239
TRIVIAL_BOUNDS,
12401240
span,
1241-
&format!(
1241+
|lint| lint.build(&format!(
12421242
"{} bound {} does not depend on any type \
12431243
or lifetime parameters",
12441244
predicate_kind_name, predicate
1245-
),
1245+
)).emit(),
12461246
);
12471247
}
12481248
}

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)