Skip to content

Commit a8f7e24

Browse files
committed
Refactor rustc lint API
1 parent 65445a5 commit a8f7e24

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1761
-1556
lines changed

compiler/rustc_const_eval/src/const_eval/error.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,10 @@ impl<'tcx> ConstEvalErr<'tcx> {
233233
rustc_session::lint::builtin::CONST_ERR,
234234
hir_id,
235235
tcx.span,
236+
message,
236237
|lint| {
237-
let mut lint = lint.build(message);
238-
finish(&mut lint, Some(err_msg));
239-
lint.emit();
238+
finish(lint, Some(err_msg));
239+
lint
240240
},
241241
);
242242
ErrorHandled::Linted

compiler/rustc_error_messages/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,17 @@ impl<S: Into<String>> From<S> for DiagnosticMessage {
357357
}
358358
}
359359

360+
/// A workaround for "good path" ICEs when formatting types in disables lints.
361+
///
362+
/// Delays formatting until `.into(): DiagnosticMessage` is used.
363+
pub struct DelayDm<F>(pub F);
364+
365+
impl<F: FnOnce() -> String> From<DelayDm<F>> for DiagnosticMessage {
366+
fn from(DelayDm(f): DelayDm<F>) -> Self {
367+
DiagnosticMessage::from(f())
368+
}
369+
}
370+
360371
/// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but
361372
/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagnosticMessage` and the
362373
/// subdiagnostic derive refers to typed identifiers that are `DiagnosticMessage`s, so need to be

compiler/rustc_errors/src/diagnostic.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::snippet::Style;
22
use crate::{
3-
CodeSuggestion, DiagnosticMessage, EmissionGuarantee, Level, LintDiagnosticBuilder, MultiSpan,
3+
CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level, MultiSpan,
44
SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
55
};
66
use rustc_ast as ast;
@@ -209,7 +209,12 @@ pub trait AddToDiagnostic {
209209
#[rustc_diagnostic_item = "DecorateLint"]
210210
pub trait DecorateLint<'a, G: EmissionGuarantee> {
211211
/// Decorate and emit a lint.
212-
fn decorate_lint(self, diag: LintDiagnosticBuilder<'a, G>);
212+
fn decorate_lint<'b>(
213+
self,
214+
diag: &'b mut DiagnosticBuilder<'a, G>,
215+
) -> &'b mut DiagnosticBuilder<'a, G>;
216+
217+
fn msg(&self) -> DiagnosticMessage;
213218
}
214219

215220
#[must_use]

compiler/rustc_errors/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use rustc_data_structures::stable_hasher::StableHasher;
3030
use rustc_data_structures::sync::{self, Lock, Lrc};
3131
use rustc_data_structures::AtomicRef;
3232
pub use rustc_error_messages::{
33-
fallback_fluent_bundle, fluent, fluent_bundle, DiagnosticMessage, FluentBundle,
33+
fallback_fluent_bundle, fluent, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle,
3434
LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage,
3535
DEFAULT_LOCALE_RESOURCES,
3636
};

compiler/rustc_hir_analysis/src/astconv/generics.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -649,9 +649,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
649649
LATE_BOUND_LIFETIME_ARGUMENTS,
650650
args.args[0].hir_id(),
651651
multispan,
652-
|lint| {
653-
lint.build(msg).emit();
654-
},
652+
msg,
653+
|lint| lint,
655654
);
656655
}
657656

compiler/rustc_hir_analysis/src/astconv/mod.rs

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,30 +2015,35 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
20152015
tcx.check_stability(item.def_id, Some(hir_ref_id), span, None);
20162016

20172017
if let Some(variant_def_id) = variant_resolution {
2018-
tcx.struct_span_lint_hir(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| {
2019-
let mut err = lint.build("ambiguous associated item");
2020-
let mut could_refer_to = |kind: DefKind, def_id, also| {
2021-
let note_msg = format!(
2022-
"`{}` could{} refer to the {} defined here",
2023-
assoc_ident,
2024-
also,
2025-
kind.descr(def_id)
2026-
);
2027-
err.span_note(tcx.def_span(def_id), &note_msg);
2028-
};
2018+
tcx.struct_span_lint_hir(
2019+
AMBIGUOUS_ASSOCIATED_ITEMS,
2020+
hir_ref_id,
2021+
span,
2022+
"ambiguous associated item",
2023+
|lint| {
2024+
let mut could_refer_to = |kind: DefKind, def_id, also| {
2025+
let note_msg = format!(
2026+
"`{}` could{} refer to the {} defined here",
2027+
assoc_ident,
2028+
also,
2029+
kind.descr(def_id)
2030+
);
2031+
lint.span_note(tcx.def_span(def_id), &note_msg);
2032+
};
20292033

2030-
could_refer_to(DefKind::Variant, variant_def_id, "");
2031-
could_refer_to(kind, item.def_id, " also");
2034+
could_refer_to(DefKind::Variant, variant_def_id, "");
2035+
could_refer_to(kind, item.def_id, " also");
20322036

2033-
err.span_suggestion(
2034-
span,
2035-
"use fully-qualified syntax",
2036-
format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
2037-
Applicability::MachineApplicable,
2038-
);
2037+
lint.span_suggestion(
2038+
span,
2039+
"use fully-qualified syntax",
2040+
format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
2041+
Applicability::MachineApplicable,
2042+
);
20392043

2040-
err.emit();
2041-
});
2044+
lint
2045+
},
2046+
);
20422047
}
20432048
Ok((ty, kind, item.def_id))
20442049
}
@@ -3084,15 +3089,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
30843089
BARE_TRAIT_OBJECTS,
30853090
self_ty.hir_id,
30863091
self_ty.span,
3092+
msg,
30873093
|lint| {
3088-
let mut diag = lint.build(msg);
3089-
diag.multipart_suggestion_verbose(
3094+
lint.multipart_suggestion_verbose(
30903095
"use `dyn`",
30913096
sugg,
30923097
Applicability::MachineApplicable,
30933098
);
3094-
self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
3095-
diag.emit();
3099+
self.maybe_lint_blanket_trait_impl(&self_ty, lint);
3100+
lint
30963101
},
30973102
);
30983103
}

compiler/rustc_hir_analysis/src/check/cast.rs

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use super::FnCtxt;
3333
use crate::hir::def_id::DefId;
3434
use crate::type_error_struct;
3535
use hir::def_id::LOCAL_CRATE;
36-
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
36+
use rustc_errors::{struct_span_err, Applicability, DelayDm, DiagnosticBuilder, ErrorGuaranteed};
3737
use rustc_hir as hir;
3838
use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode};
3939
use rustc_middle::mir::Mutability;
@@ -754,19 +754,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
754754
} else {
755755
("", lint::builtin::TRIVIAL_CASTS)
756756
};
757-
fcx.tcx.struct_span_lint_hir(lint, self.expr.hir_id, self.span, |err| {
758-
err.build(&format!(
759-
"trivial {}cast: `{}` as `{}`",
760-
adjective,
761-
fcx.ty_to_string(t_expr),
762-
fcx.ty_to_string(t_cast)
763-
))
764-
.help(&format!(
765-
"cast can be replaced by coercion; this might \
766-
require {type_asc_or}a temporary variable"
767-
))
768-
.emit();
769-
});
757+
fcx.tcx.struct_span_lint_hir(
758+
lint,
759+
self.expr.hir_id,
760+
self.span,
761+
DelayDm(|| {
762+
format!(
763+
"trivial {}cast: `{}` as `{}`",
764+
adjective,
765+
fcx.ty_to_string(t_expr),
766+
fcx.ty_to_string(t_cast)
767+
)
768+
}),
769+
|lint| {
770+
lint.help(format!(
771+
"cast can be replaced by coercion; this might \
772+
require {type_asc_or}a temporary variable"
773+
))
774+
},
775+
);
770776
}
771777

772778
#[instrument(skip(fcx), level = "debug")]
@@ -1074,12 +1080,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
10741080
lint::builtin::CENUM_IMPL_DROP_CAST,
10751081
self.expr.hir_id,
10761082
self.span,
1077-
|err| {
1078-
err.build(&format!(
1079-
"cannot cast enum `{}` into integer `{}` because it implements `Drop`",
1080-
self.expr_ty, self.cast_ty
1081-
))
1082-
.emit();
1083+
DelayDm(|| format!(
1084+
"cannot cast enum `{}` into integer `{}` because it implements `Drop`",
1085+
self.expr_ty, self.cast_ty
1086+
)),
1087+
|lint| {
1088+
lint
10831089
},
10841090
);
10851091
}
@@ -1090,12 +1096,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
10901096
lint::builtin::LOSSY_PROVENANCE_CASTS,
10911097
self.expr.hir_id,
10921098
self.span,
1093-
|err| {
1094-
let mut err = err.build(&format!(
1099+
DelayDm(|| format!(
10951100
"under strict provenance it is considered bad style to cast pointer `{}` to integer `{}`",
10961101
self.expr_ty, self.cast_ty
1097-
));
1098-
1102+
)),
1103+
|lint| {
10991104
let msg = "use `.addr()` to obtain the address of a pointer";
11001105

11011106
let expr_prec = self.expr.precedence().order();
@@ -1114,22 +1119,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
11141119
(cast_span, format!(").addr(){scalar_cast}")),
11151120
];
11161121

1117-
err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
1122+
lint.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
11181123
} else {
1119-
err.span_suggestion(
1124+
lint.span_suggestion(
11201125
cast_span,
11211126
msg,
11221127
format!(".addr(){scalar_cast}"),
11231128
Applicability::MaybeIncorrect,
11241129
);
11251130
}
11261131

1127-
err.help(
1132+
lint.help(
11281133
"if you can't comply with strict provenance and need to expose the pointer \
11291134
provenance you can use `.expose_addr()` instead"
11301135
);
11311136

1132-
err.emit();
1137+
lint
11331138
},
11341139
);
11351140
}
@@ -1139,24 +1144,24 @@ impl<'a, 'tcx> CastCheck<'tcx> {
11391144
lint::builtin::FUZZY_PROVENANCE_CASTS,
11401145
self.expr.hir_id,
11411146
self.span,
1142-
|err| {
1143-
let mut err = err.build(&format!(
1144-
"strict provenance disallows casting integer `{}` to pointer `{}`",
1145-
self.expr_ty, self.cast_ty
1146-
));
1147+
DelayDm(|| format!(
1148+
"strict provenance disallows casting integer `{}` to pointer `{}`",
1149+
self.expr_ty, self.cast_ty
1150+
)),
1151+
|lint| {
11471152
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
11481153
let suggestions = vec![
11491154
(self.expr_span.shrink_to_lo(), String::from("(...).with_addr(")),
11501155
(self.expr_span.shrink_to_hi().to(self.cast_span), String::from(")")),
11511156
];
11521157

1153-
err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
1154-
err.help(
1158+
lint.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
1159+
lint.help(
11551160
"if you can't comply with strict provenance and don't have a pointer with \
11561161
the correct provenance you can use `std::ptr::from_exposed_addr()` instead"
11571162
);
11581163

1159-
err.emit();
1164+
lint
11601165
},
11611166
);
11621167
}

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,13 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab
4848
.emit();
4949
}
5050
None => {
51-
tcx.struct_span_lint_hir(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
52-
lint.build("use of calling convention not supported on this target").emit();
53-
});
51+
tcx.struct_span_lint_hir(
52+
UNSUPPORTED_CALLING_CONVENTIONS,
53+
hir_id,
54+
span,
55+
"use of calling convention not supported on this target",
56+
|lint| lint,
57+
);
5458
}
5559
}
5660

@@ -510,10 +514,10 @@ fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
510514
UNINHABITED_STATIC,
511515
tcx.hir().local_def_id_to_hir_id(def_id),
512516
span,
517+
"static of uninhabited type",
513518
|lint| {
514-
lint.build("static of uninhabited type")
519+
lint
515520
.note("uninhabited statics cannot be initialized, and any access would be an immediate error")
516-
.emit();
517521
},
518522
);
519523
}
@@ -1434,17 +1438,17 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
14341438
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
14351439
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
14361440
span,
1441+
"zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types",
14371442
|lint| {
14381443
let note = if non_exhaustive {
14391444
"is marked with `#[non_exhaustive]`"
14401445
} else {
14411446
"contains private fields"
14421447
};
14431448
let field_ty = tcx.def_path_str_with_substs(def_id, substs);
1444-
lint.build("zero-sized fields in repr(transparent) cannot contain external non-exhaustive types")
1449+
lint
14451450
.note(format!("this {descr} contains `{field_ty}`, which {note}, \
14461451
and makes it not a breaking change to become non-zero-sized in the future."))
1447-
.emit();
14481452
},
14491453
)
14501454
}

compiler/rustc_hir_analysis/src/check/fn_ctxt/_impl.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5858

5959
debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
6060

61-
self.tcx().struct_span_lint_hir(lint::builtin::UNREACHABLE_CODE, id, span, |lint| {
62-
let msg = format!("unreachable {}", kind);
63-
lint.build(&msg)
64-
.span_label(span, &msg)
65-
.span_label(
61+
let msg = format!("unreachable {}", kind);
62+
self.tcx().struct_span_lint_hir(
63+
lint::builtin::UNREACHABLE_CODE,
64+
id,
65+
span,
66+
&msg,
67+
|lint| {
68+
lint.span_label(span, &msg).span_label(
6669
orig_span,
6770
custom_note
6871
.unwrap_or("any code following this expression is unreachable"),
6972
)
70-
.emit();
71-
})
73+
},
74+
)
7275
}
7376
}
7477
}

0 commit comments

Comments
 (0)