Skip to content

Commit 744e397

Browse files
committed
Auto merge of #101986 - WaffleLapkin:move_lint_note_to_the_bottom, r=estebank
Move lint level source explanation to the bottom So, uhhhhh r? `@estebank` ## User-facing change "note: `#[warn(...)]` on by default" and such are moved to the bottom of the diagnostic: ```diff - = note: `#[warn(unsupported_calling_conventions)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 <#87678> + = note: `#[warn(unsupported_calling_conventions)]` on by default ``` Why warning is enabled is the least important thing, so it shouldn't be the first note the user reads, IMO. ## Developer-facing change `struct_span_lint` and similar methods have a different signature. Before: `..., impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>)` After: `..., impl Into<DiagnosticMessage>, impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>) -> &'b mut DiagnosticBuilder<'a, ()>` The reason for this is that `struct_span_lint` needs to edit the diagnostic _after_ `decorate` closure is called. This also makes lint code a little bit nicer in my opinion. Another option is to use `impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>) -> DiagnosticBuilder<'a, ()>` altough I don't _really_ see reasons to do `let lint = lint.build(message)` everywhere. ## Subtle problem By moving the message outside of the closure (that may not be called if the lint is disabled) `format!(...)` is executed earlier, possibly formatting `Ty` which may call a query that trims paths that crashes the compiler if there were no warnings... I don't think it's that big of a deal, considering that we move from `format!(...)` to `fluent` (which is lazy by-default) anyway, however this required adding a workaround which is unfortunate. ## P.S. I'm sorry, I do not how to make this PR smaller/easier to review. Changes to the lint API affect SO MUCH 😢
2 parents 277bb66 + b5b3ffe commit 744e397

File tree

827 files changed

+3369
-3209
lines changed

Some content is hidden

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

827 files changed

+3369
-3209
lines changed

compiler/rustc_const_eval/src/const_eval/error.rs

+3-3
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

+11
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,17 @@ impl<S: Into<String>> From<S> for DiagnosticMessage {
358358
}
359359
}
360360

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

compiler/rustc_errors/src/diagnostic.rs

+7-2
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/diagnostic_builder.rs

-24
Original file line numberDiff line numberDiff line change
@@ -642,27 +642,3 @@ macro_rules! struct_span_err {
642642
macro_rules! error_code {
643643
($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }};
644644
}
645-
646-
/// Wrapper around a `DiagnosticBuilder` for creating lints.
647-
pub struct LintDiagnosticBuilder<'a, G: EmissionGuarantee>(DiagnosticBuilder<'a, G>);
648-
649-
impl<'a, G: EmissionGuarantee> LintDiagnosticBuilder<'a, G> {
650-
#[rustc_lint_diagnostics]
651-
/// Return the inner `DiagnosticBuilder`, first setting the primary message to `msg`.
652-
pub fn build(mut self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'a, G> {
653-
self.0.set_primary_message(msg);
654-
self.0.set_is_lint();
655-
self.0
656-
}
657-
658-
/// Create a `LintDiagnosticBuilder` from some existing `DiagnosticBuilder`.
659-
pub fn new(err: DiagnosticBuilder<'a, G>) -> LintDiagnosticBuilder<'a, G> {
660-
LintDiagnosticBuilder(err)
661-
}
662-
}
663-
664-
impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> {
665-
pub fn forget_guarantee(self) -> LintDiagnosticBuilder<'a, ()> {
666-
LintDiagnosticBuilder(self.0.forget_guarantee())
667-
}
668-
}

compiler/rustc_errors/src/lib.rs

+2-2
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
};
@@ -374,7 +374,7 @@ pub use diagnostic::{
374374
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgFromDisplay,
375375
DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
376376
};
377-
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, LintDiagnosticBuilder};
377+
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee};
378378
use std::backtrace::Backtrace;
379379

380380
/// A handler deals with errors and other compiler output.

compiler/rustc_hir_analysis/src/astconv/generics.rs

+2-3
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

+30-25
Original file line numberDiff line numberDiff line change
@@ -2010,30 +2010,35 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
20102010
tcx.check_stability(item.def_id, Some(hir_ref_id), span, None);
20112011

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

2025-
could_refer_to(DefKind::Variant, variant_def_id, "");
2026-
could_refer_to(kind, item.def_id, " also");
2029+
could_refer_to(DefKind::Variant, variant_def_id, "");
2030+
could_refer_to(kind, item.def_id, " also");
20272031

2028-
err.span_suggestion(
2029-
span,
2030-
"use fully-qualified syntax",
2031-
format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
2032-
Applicability::MachineApplicable,
2033-
);
2032+
lint.span_suggestion(
2033+
span,
2034+
"use fully-qualified syntax",
2035+
format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
2036+
Applicability::MachineApplicable,
2037+
);
20342038

2035-
err.emit();
2036-
});
2039+
lint
2040+
},
2041+
);
20372042
}
20382043
Ok((ty, kind, item.def_id))
20392044
}
@@ -3079,15 +3084,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
30793084
BARE_TRAIT_OBJECTS,
30803085
self_ty.hir_id,
30813086
self_ty.span,
3087+
msg,
30823088
|lint| {
3083-
let mut diag = lint.build(msg);
3084-
diag.multipart_suggestion_verbose(
3089+
lint.multipart_suggestion_verbose(
30853090
"use `dyn`",
30863091
sugg,
30873092
Applicability::MachineApplicable,
30883093
);
3089-
self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
3090-
diag.emit();
3094+
self.maybe_lint_blanket_trait_impl(&self_ty, lint);
3095+
lint
30913096
},
30923097
);
30933098
}

compiler/rustc_hir_analysis/src/check/cast.rs

+41-36
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

+11-7
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
}
@@ -1437,17 +1441,17 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
14371441
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
14381442
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
14391443
span,
1444+
"zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types",
14401445
|lint| {
14411446
let note = if non_exhaustive {
14421447
"is marked with `#[non_exhaustive]`"
14431448
} else {
14441449
"contains private fields"
14451450
};
14461451
let field_ty = tcx.def_path_str_with_substs(def_id, substs);
1447-
lint.build("zero-sized fields in repr(transparent) cannot contain external non-exhaustive types")
1452+
lint
14481453
.note(format!("this {descr} contains `{field_ty}`, which {note}, \
14491454
and makes it not a breaking change to become non-zero-sized in the future."))
1450-
.emit();
14511455
},
14521456
)
14531457
}

0 commit comments

Comments
 (0)