Skip to content

Commit

Permalink
Auto merge of rust-lang#125410 - fmease:adj-lint-diag-api, r=nnethercote
Browse files Browse the repository at this point in the history
[perf] Delay the construction of early lint diag structs

Attacks some of the perf regressions from rust-lang#124417 (comment).

See individual commits for details. The first three commits are not strictly necessary.
However, the 2nd one (06bc4fc, *Remove `LintDiagnostic::msg`*) makes the main change way nicer to implement.
It's also pretty sweet on its own if I may say so myself.
  • Loading branch information
bors committed May 27, 2024
2 parents fec98b3 + 37bf2d2 commit b582f80
Show file tree
Hide file tree
Showing 50 changed files with 600 additions and 751 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
lint::builtin::INLINE_NO_SANITIZE,
hir_id,
no_sanitize_span,
"`no_sanitize` will have no effect after inlining",
|lint| {
lint.primary_message("`no_sanitize` will have no effect after inlining");
lint.span_note(inline_span, "inlining requested here");
},
)
Expand Down
11 changes: 0 additions & 11 deletions compiler/rustc_error_messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,17 +364,6 @@ impl From<Cow<'static, str>> for DiagMessage {
}
}

/// A workaround for must_produce_diag ICEs when formatting types in disabled lints.
///
/// Delays formatting until `.into(): DiagMessage` is used.
pub struct DelayDm<F>(pub F);

impl<F: FnOnce() -> String> From<DelayDm<F>> for DiagMessage {
fn from(DelayDm(f): DelayDm<F>) -> Self {
DiagMessage::from(f())
}
}

/// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but
/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagMessage` and the
/// subdiagnostic derive refers to typed identifiers that are `DiagMessage`s, so need to be
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,6 @@ pub trait SubdiagMessageOp<G: EmissionGuarantee> =
pub trait LintDiagnostic<'a, G: EmissionGuarantee> {
/// Decorate and emit a lint.
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>);

fn msg(&self) -> DiagMessage;
}

#[derive(Clone, Debug, Encodable, Decodable)]
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub use diagnostic_impls::{
};
pub use emitter::ColorConfig;
pub use rustc_error_messages::{
fallback_fluent_bundle, fluent_bundle, DelayDm, DiagMessage, FluentBundle, LanguageIdentifier,
fallback_fluent_bundle, fluent_bundle, DiagMessage, FluentBundle, LanguageIdentifier,
LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage,
};
pub use rustc_lint_defs::{pluralize, Applicability};
Expand Down Expand Up @@ -572,8 +572,8 @@ impl Drop for DiagCtxtInner {
if let Some(backtrace) = &self.must_produce_diag {
panic!(
"must_produce_diag: `trimmed_def_paths` called but no diagnostics emitted; \
use `DelayDm` for lints or `with_no_trimmed_paths` for debugging. \
called at: {backtrace}"
`with_no_trimmed_paths` for debugging. \
called at: {backtrace}"
);
}
}
Expand Down
18 changes: 8 additions & 10 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,9 @@ pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
.emit();
}
None => {
tcx.node_span_lint(
UNSUPPORTED_CALLING_CONVENTIONS,
hir_id,
span,
"use of calling convention not supported on this target",
|_| {},
);
tcx.node_span_lint(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
lint.primary_message("use of calling convention not supported on this target");
});
}
}

Expand Down Expand Up @@ -243,8 +239,8 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
UNINHABITED_STATIC,
tcx.local_def_id_to_hir_id(def_id),
span,
"static of uninhabited type",
|lint| {
lint.primary_message("static of uninhabited type");
lint
.note("uninhabited statics cannot be initialized, and any access would be an immediate error");
},
Expand Down Expand Up @@ -1310,9 +1306,11 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
tcx.local_def_id_to_hir_id(adt.did().expect_local()),
span,
"zero-sized fields in `repr(transparent)` cannot \
contain external non-exhaustive types",
|lint| {
lint.primary_message(
"zero-sized fields in `repr(transparent)` cannot \
contain external non-exhaustive types",
);
let note = if non_exhaustive {
"is marked with `#[non_exhaustive]`"
} else {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
lint::builtin::ASM_SUB_REGISTER,
expr.hir_id,
spans,
"formatting may not be suitable for sub-register argument",
|lint| {
lint.primary_message("formatting may not be suitable for sub-register argument");
lint.span_label(expr.span, "for this argument");
lint.help(format!(
"use `{{{idx}:{suggested_modifier}}}` to have the register formatted as `{suggested_result}` (for {suggested_size}-bit values)",
Expand Down
13 changes: 7 additions & 6 deletions compiler/rustc_hir_analysis/src/check_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) {
continue;
}
let (path, _) = item.expect_use();
let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
format!("unused import: `{snippet}`")
} else {
"unused import".to_owned()
};
tcx.node_span_lint(lint::builtin::UNUSED_IMPORTS, item.hir_id(), path.span, msg, |_| {});
tcx.node_span_lint(lint::builtin::UNUSED_IMPORTS, item.hir_id(), path.span, |lint| {
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
lint.primary_message(format!("unused import: `{snippet}`"));
} else {
lint.primary_message("unused import");
}
});
}
}
5 changes: 3 additions & 2 deletions compiler/rustc_hir_analysis/src/collect/generics_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,9 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
param.hir_id,
param.span,
TYPE_DEFAULT_NOT_ALLOWED,
|_| {},
|lint| {
lint.primary_message(TYPE_DEFAULT_NOT_ALLOWED);
},
);
}
Defaults::Deny => {
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,8 +646,9 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
LATE_BOUND_LIFETIME_ARGUMENTS,
args.args[0].hir_id(),
multispan,
msg,
|_| {},
|lint| {
lint.primary_message(msg);
},
);
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag);
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
} else {
let msg = "trait objects without an explicit `dyn` are deprecated";
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| {
lint.primary_message("trait objects without an explicit `dyn` are deprecated");
if self_ty.span.can_be_used_for_suggestions() {
lint.multipart_suggestion_verbose(
"if this is an object-safe trait, use `dyn`",
Expand Down
45 changes: 20 additions & 25 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1165,33 +1165,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let ty = self.lower_assoc_ty(span, assoc_ty_did, assoc_segment, bound);

if let Some(variant_def_id) = variant_resolution {
tcx.node_span_lint(
AMBIGUOUS_ASSOCIATED_ITEMS,
hir_ref_id,
span,
"ambiguous associated item",
|lint| {
let mut could_refer_to = |kind: DefKind, def_id, also| {
let note_msg = format!(
"`{}` could{} refer to the {} defined here",
assoc_ident,
also,
tcx.def_kind_descr(kind, def_id)
);
lint.span_note(tcx.def_span(def_id), note_msg);
};
tcx.node_span_lint(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| {
lint.primary_message("ambiguous associated item");
let mut could_refer_to = |kind: DefKind, def_id, also| {
let note_msg = format!(
"`{}` could{} refer to the {} defined here",
assoc_ident,
also,
tcx.def_kind_descr(kind, def_id)
);
lint.span_note(tcx.def_span(def_id), note_msg);
};

could_refer_to(DefKind::Variant, variant_def_id, "");
could_refer_to(DefKind::AssocTy, assoc_ty_did, " also");
could_refer_to(DefKind::Variant, variant_def_id, "");
could_refer_to(DefKind::AssocTy, assoc_ty_did, " also");

lint.span_suggestion(
span,
"use fully-qualified syntax",
format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
Applicability::MachineApplicable,
);
},
);
lint.span_suggestion(
span,
"use fully-qualified syntax",
format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
Applicability::MachineApplicable,
);
});
}
Ok((ty, DefKind::AssocTy, assoc_ty_did))
}
Expand Down
20 changes: 7 additions & 13 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);

let msg = format!("unreachable {kind}");
self.tcx().node_span_lint(
lint::builtin::UNREACHABLE_CODE,
id,
span,
msg.clone(),
|lint| {
lint.span_label(span, msg).span_label(
orig_span,
custom_note
.unwrap_or("any code following this expression is unreachable"),
);
},
)
self.tcx().node_span_lint(lint::builtin::UNREACHABLE_CODE, id, span, |lint| {
lint.primary_message(msg.clone());
lint.span_label(span, msg).span_label(
orig_span,
custom_note.unwrap_or("any code following this expression is unreachable"),
);
})
}
}
}
Expand Down
Loading

0 comments on commit b582f80

Please sign in to comment.