Auto merge of #119146 - nnethercote:rm-DiagCtxt-api-duplication, r=compiler-errors
Remove `DiagCtxt` API duplication `DiagCtxt` defines the internal API for creating and emitting diagnostics: methods like `struct_err`, `struct_span_warn`, `note`, `create_fatal`, `emit_bug`. There are over 50 methods. Some of these methods are then duplicated across several other types: `Session`, `ParseSess`, `Parser`, `ExtCtxt`, and `MirBorrowckCtxt`. `Session` duplicates the most, though half the ones it does are unused. Each duplicated method just calls forward to the corresponding method in `DiagCtxt`. So this duplication exists to (in the best case) shorten chains like `ecx.tcx.sess.parse_sess.dcx.emit_err()` to `ecx.emit_err()`. This API duplication is ugly and has been bugging me for a while. And it's inconsistent: there's no real logic about which methods are duplicated, and the use of `#[rustc_lint_diagnostic]` and `#[track_caller]` attributes vary across the duplicates. This PR removes the duplicated API methods and makes all diagnostic creation and emission go through `DiagCtxt`. It also adds `dcx` getter methods to several types to shorten chains. This approach scales *much* better than API duplication; indeed, the PR adds `dcx()` to numerous types that didn't have API duplication: `TyCtxt`, `LoweringCtxt`, `ConstCx`, `FnCtxt`, `TypeErrCtxt`, `InferCtxt`, `CrateLoader`, `CheckAttrVisitor`, and `Resolver`. These result in a lot of changes from `foo.tcx.sess.emit_err()` to `foo.dcx().emit_err()`. (You could do this with more types, but it gets into diminishing returns territory for types that don't emit many diagnostics.) After all these changes, some call sites are more verbose, some are less verbose, and many are the same. The total number of lines is reduced, mostly because of the removed API duplication. And consistency is increased, because calls to `emit_err` and friends are always preceded with `.dcx()` or `.dcx`. r? `@compiler-errors`
This commit is contained in:
commit
2271c26e4a
347 changed files with 2334 additions and 2696 deletions
|
@ -4,10 +4,10 @@
|
|||
///
|
||||
/// If you have a span available, you should use [`span_bug`] instead.
|
||||
///
|
||||
/// If the bug should only be emitted when compilation didn't fail, [`Session::span_delayed_bug`]
|
||||
/// If the bug should only be emitted when compilation didn't fail, [`DiagCtxt::span_delayed_bug`]
|
||||
/// may be useful.
|
||||
///
|
||||
/// [`Session::span_delayed_bug`]: rustc_session::Session::span_delayed_bug
|
||||
/// [`DiagCtxt::span_delayed_bug`]: rustc_errors::DiagCtxt::span_delayed_bug
|
||||
/// [`span_bug`]: crate::span_bug
|
||||
#[macro_export]
|
||||
macro_rules! bug {
|
||||
|
@ -24,10 +24,10 @@ macro_rules! bug {
|
|||
/// at the code the compiler was compiling when it ICEd. This is the preferred way to trigger
|
||||
/// ICEs.
|
||||
///
|
||||
/// If the bug should only be emitted when compilation didn't fail, [`Session::span_delayed_bug`]
|
||||
/// If the bug should only be emitted when compilation didn't fail, [`DiagCtxt::span_delayed_bug`]
|
||||
/// may be useful.
|
||||
///
|
||||
/// [`Session::span_delayed_bug`]: rustc_session::Session::span_delayed_bug
|
||||
/// [`DiagCtxt::span_delayed_bug`]: rustc_errors::DiagCtxt::span_delayed_bug
|
||||
#[macro_export]
|
||||
macro_rules! span_bug {
|
||||
($span:expr, $msg:expr) => ({ $crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg)) });
|
||||
|
|
|
@ -19,7 +19,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// If not found, fatally aborts compilation.
|
||||
pub fn require_lang_item(self, lang_item: LangItem, span: Option<Span>) -> DefId {
|
||||
self.lang_items().get(lang_item).unwrap_or_else(|| {
|
||||
self.sess.emit_fatal(crate::error::RequiresLangItem { span, name: lang_item.name() });
|
||||
self.dcx().emit_fatal(crate::error::RequiresLangItem { span, name: lang_item.name() });
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: u
|
|||
IntErrorKind::Zero => bug!("zero is a valid `limit`"),
|
||||
kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
|
||||
};
|
||||
sess.emit_err(LimitInvalid { span: attr.span, value_span, error_str });
|
||||
sess.dcx().emit_err(LimitInvalid { span: attr.span, value_span, error_str });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -565,7 +565,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|span, def_id| {
|
||||
// The API could be uncallable for other reasons, for example when a private module
|
||||
// was referenced.
|
||||
self.sess.span_delayed_bug(span, format!("encountered unmarked API: {def_id:?}"));
|
||||
self.dcx().span_delayed_bug(span, format!("encountered unmarked API: {def_id:?}"));
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -315,7 +315,7 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
|
|||
pub fn try_uninit<'tcx>(size: Size, align: Align) -> InterpResult<'tcx, Self> {
|
||||
Self::uninit_inner(size, align, || {
|
||||
ty::tls::with(|tcx| {
|
||||
tcx.sess.span_delayed_bug(DUMMY_SP, "exhausted memory during interpretation")
|
||||
tcx.dcx().span_delayed_bug(DUMMY_SP, "exhausted memory during interpretation")
|
||||
});
|
||||
InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted).into()
|
||||
})
|
||||
|
|
|
@ -47,7 +47,7 @@ impl ErrorHandled {
|
|||
match self {
|
||||
&ErrorHandled::Reported(err, span) => {
|
||||
if !err.is_tainted_by_errors && !span.is_dummy() {
|
||||
tcx.sess.emit_note(error::ErroneousConstant { span });
|
||||
tcx.dcx().emit_note(error::ErroneousConstant { span });
|
||||
}
|
||||
}
|
||||
&ErrorHandled::TooGeneric(_) => {}
|
||||
|
@ -91,7 +91,7 @@ pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
|
|||
pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, ErrorHandled>;
|
||||
|
||||
pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'tcx> {
|
||||
struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
|
||||
struct_span_err!(tcx.dcx(), tcx.span, E0080, "{}", msg)
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
|
|
|
@ -551,7 +551,7 @@ macro_rules! define_feedable {
|
|||
// We have an inconsistency. This can happen if one of the two
|
||||
// results is tainted by errors. In this case, delay a bug to
|
||||
// ensure compilation is doomed, and keep the `old` value.
|
||||
tcx.sess.span_delayed_bug(DUMMY_SP, format!(
|
||||
tcx.dcx().span_delayed_bug(DUMMY_SP, format!(
|
||||
"Trying to feed an already recorded value for query {} key={key:?}:\n\
|
||||
old value: {old:?}\nnew value: {value:?}",
|
||||
stringify!($name),
|
||||
|
|
|
@ -105,7 +105,7 @@ pub struct DropckOutlivesResult<'tcx> {
|
|||
impl<'tcx> DropckOutlivesResult<'tcx> {
|
||||
pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
|
||||
if let Some(overflow_ty) = self.overflows.get(0) {
|
||||
tcx.sess.emit_err(DropCheckOverflow { span, ty, overflow_ty: *overflow_ty });
|
||||
tcx.dcx().emit_err(DropCheckOverflow { span, ty, overflow_ty: *overflow_ty });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ impl OverlapMode {
|
|||
})
|
||||
.find(|attr| attr.has_name(sym::rustc_strict_coherence))
|
||||
.map(|attr| attr.span);
|
||||
tcx.sess.emit_err(StrictCoherenceNeedsNegativeCoherence {
|
||||
tcx.dcx().emit_err(StrictCoherenceNeedsNegativeCoherence {
|
||||
span: tcx.def_span(trait_id),
|
||||
attr_span,
|
||||
});
|
||||
|
|
|
@ -470,7 +470,7 @@ impl<'tcx> AdtDef<'tcx> {
|
|||
Some(Discr { val: b, ty })
|
||||
} else {
|
||||
info!("invalid enum discriminant: {:#?}", val);
|
||||
tcx.sess.emit_err(crate::error::ConstEvalNonIntError {
|
||||
tcx.dcx().emit_err(crate::error::ConstEvalNonIntError {
|
||||
span: tcx.def_span(expr_did),
|
||||
});
|
||||
None
|
||||
|
@ -481,7 +481,7 @@ impl<'tcx> AdtDef<'tcx> {
|
|||
ErrorHandled::Reported(..) => "enum discriminant evaluation failed",
|
||||
ErrorHandled::TooGeneric(..) => "enum discriminant depends on generics",
|
||||
};
|
||||
tcx.sess.span_delayed_bug(tcx.def_span(expr_did), msg);
|
||||
tcx.dcx().span_delayed_bug(tcx.def_span(expr_did), msg);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ impl<'tcx> Const<'tcx> {
|
|||
span: S,
|
||||
msg: &'static str,
|
||||
) -> Const<'tcx> {
|
||||
let reported = tcx.sess.span_delayed_bug(span, msg);
|
||||
let reported = tcx.dcx().span_delayed_bug(span, msg);
|
||||
Const::new_error(tcx, reported, ty)
|
||||
}
|
||||
|
||||
|
@ -223,7 +223,7 @@ impl<'tcx> Const<'tcx> {
|
|||
match tcx.at(expr.span).lit_to_const(lit_input) {
|
||||
Ok(c) => return Some(c),
|
||||
Err(e) => {
|
||||
tcx.sess.span_delayed_bug(
|
||||
tcx.dcx().span_delayed_bug(
|
||||
expr.span,
|
||||
format!("Const::from_anon_const: couldn't lit_to_const {e:?}"),
|
||||
);
|
||||
|
@ -322,7 +322,7 @@ impl<'tcx> Const<'tcx> {
|
|||
let Some(c) = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)?
|
||||
else {
|
||||
// This can happen when we run on ill-typed code.
|
||||
let e = tcx.sess.span_delayed_bug(
|
||||
let e = tcx.dcx().span_delayed_bug(
|
||||
span.unwrap_or(DUMMY_SP),
|
||||
"`ty::Const::eval` called on a non-valtree-compatible type",
|
||||
);
|
||||
|
|
|
@ -44,7 +44,7 @@ use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, WorkerLocal};
|
|||
use rustc_data_structures::sync::{DynSend, DynSync};
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::{
|
||||
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
|
||||
DecorateLint, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
|
@ -747,7 +747,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
{
|
||||
Bound::Included(a)
|
||||
} else {
|
||||
self.sess.span_delayed_bug(
|
||||
self.dcx().span_delayed_bug(
|
||||
attr.span,
|
||||
"invalid rustc_layout_scalar_valid_range attribute",
|
||||
);
|
||||
|
@ -783,7 +783,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
hooks: crate::hooks::Providers,
|
||||
) -> GlobalCtxt<'tcx> {
|
||||
let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
|
||||
s.emit_fatal(err);
|
||||
s.dcx().emit_fatal(err);
|
||||
});
|
||||
let interners = CtxtInterners::new(arena);
|
||||
let common_types = CommonTypes::new(&interners, s, &untracked);
|
||||
|
@ -1018,6 +1018,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.def_path(def_id).to_string_no_crate_verbose()
|
||||
)
|
||||
}
|
||||
|
||||
pub fn dcx(self) -> &'tcx DiagCtxt {
|
||||
self.sess.dcx()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxtAt<'tcx> {
|
||||
|
|
|
@ -284,7 +284,7 @@ impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
type TargetDataLayoutRef = &'tcx TargetDataLayout;
|
||||
|
||||
fn delayed_bug(&self, txt: String) {
|
||||
self.tcx.sess.span_delayed_bug(DUMMY_SP, txt);
|
||||
self.tcx.dcx().span_delayed_bug(DUMMY_SP, txt);
|
||||
}
|
||||
|
||||
fn current_data_layout(&self) -> Self::TargetDataLayoutRef {
|
||||
|
|
|
@ -1495,7 +1495,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
|
|||
} else {
|
||||
TypeMismatchReason::PreviousUse { span: self.span }
|
||||
};
|
||||
tcx.sess.create_err(OpaqueHiddenTypeMismatch {
|
||||
tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
|
||||
self_ty: self.ty,
|
||||
other_ty: other.ty,
|
||||
other_span: other.span,
|
||||
|
|
|
@ -130,7 +130,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
|
|||
None => {
|
||||
let e = self
|
||||
.tcx
|
||||
.sess
|
||||
.dcx()
|
||||
.struct_span_err(self.span, "non-defining opaque type use in defining scope")
|
||||
.span_label(
|
||||
self.span,
|
||||
|
@ -174,7 +174,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
|
|||
debug!(?param, ?self.map);
|
||||
if !self.ignore_errors {
|
||||
self.tcx
|
||||
.sess
|
||||
.dcx()
|
||||
.struct_span_err(
|
||||
self.span,
|
||||
format!(
|
||||
|
@ -208,7 +208,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
|
|||
None => {
|
||||
let guar = self
|
||||
.tcx
|
||||
.sess
|
||||
.dcx()
|
||||
.create_err(ConstNotUsedTraitAlias {
|
||||
ct: ct.to_string(),
|
||||
span: self.span,
|
||||
|
|
|
@ -1557,7 +1557,7 @@ impl<'tcx> Region<'tcx> {
|
|||
span: S,
|
||||
msg: &'static str,
|
||||
) -> Region<'tcx> {
|
||||
let reported = tcx.sess.span_delayed_bug(span, msg);
|
||||
let reported = tcx.dcx().span_delayed_bug(span, msg);
|
||||
Region::new_error(tcx, reported)
|
||||
}
|
||||
|
||||
|
@ -2004,7 +2004,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
span: S,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> Ty<'tcx> {
|
||||
let reported = tcx.sess.span_delayed_bug(span, msg);
|
||||
let reported = tcx.dcx().span_delayed_bug(span, msg);
|
||||
Ty::new(tcx, Error(reported))
|
||||
}
|
||||
|
||||
|
|
|
@ -391,7 +391,7 @@ impl<'tcx> TypeckResults<'tcx> {
|
|||
|
||||
pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
|
||||
self.pat_binding_modes().get(id).copied().or_else(|| {
|
||||
s.span_delayed_bug(sp, "missing binding mode");
|
||||
s.dcx().span_delayed_bug(sp, "missing binding mode");
|
||||
None
|
||||
})
|
||||
}
|
||||
|
|
|
@ -223,8 +223,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
Limit(0) => Limit(2),
|
||||
limit => limit * 2,
|
||||
};
|
||||
let reported =
|
||||
self.sess.emit_err(crate::error::RecursionLimitReached { ty, suggested_limit });
|
||||
let reported = self
|
||||
.dcx()
|
||||
.emit_err(crate::error::RecursionLimitReached { ty, suggested_limit });
|
||||
return Ty::new_error(self, reported);
|
||||
}
|
||||
match *ty.kind() {
|
||||
|
@ -360,13 +361,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
|
||||
self.sess
|
||||
self.dcx()
|
||||
.span_delayed_bug(self.def_span(impl_did), "Drop impl without drop function");
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some((old_item_id, _)) = dtor_candidate {
|
||||
self.sess
|
||||
self.dcx()
|
||||
.struct_span_err(self.def_span(item_id), "multiple drop impls found")
|
||||
.span_note(self.def_span(old_item_id), "other impl here")
|
||||
.delay_as_bug();
|
||||
|
|
|
@ -55,7 +55,7 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
|
|||
}
|
||||
fn error_reported(&self) -> Result<(), ErrorGuaranteed> {
|
||||
if self.references_error() {
|
||||
if let Some(reported) = ty::tls::with(|tcx| tcx.sess.is_compilation_going_to_fail()) {
|
||||
if let Some(reported) = ty::tls::with(|tcx| tcx.dcx().is_compilation_going_to_fail()) {
|
||||
Err(reported)
|
||||
} else {
|
||||
bug!("expect tcx.sess.is_compilation_going_to_fail return `Some`");
|
||||
|
|
|
@ -31,8 +31,8 @@ fn opt_span_bug_fmt<S: Into<MultiSpan>>(
|
|||
tls::with_opt(move |tcx| {
|
||||
let msg = format!("{location}: {args}");
|
||||
match (tcx, span) {
|
||||
(Some(tcx), Some(span)) => tcx.sess.dcx().span_bug(span, msg),
|
||||
(Some(tcx), None) => tcx.sess.dcx().bug(msg),
|
||||
(Some(tcx), Some(span)) => tcx.dcx().span_bug(span, msg),
|
||||
(Some(tcx), None) => tcx.dcx().bug(msg),
|
||||
(None, _) => panic_any(msg),
|
||||
}
|
||||
})
|
||||
|
@ -42,7 +42,7 @@ fn opt_span_bug_fmt<S: Into<MultiSpan>>(
|
|||
/// `span_delayed_bug`, so what is the point of this? It exists to help us test `span_delayed_bug`'s
|
||||
/// interactions with the query system and incremental.
|
||||
pub fn trigger_span_delayed_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) {
|
||||
tcx.sess.span_delayed_bug(
|
||||
tcx.dcx().span_delayed_bug(
|
||||
tcx.def_span(key),
|
||||
"delayed span bug triggered by #[rustc_error(span_delayed_bug_from_inside_query)]",
|
||||
);
|
||||
|
|
|
@ -51,7 +51,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> {
|
|||
{
|
||||
sig.decl.inputs.len() + sig.decl.implicit_self.has_implicit_self() as usize
|
||||
} else {
|
||||
tcx.sess.abort_if_errors();
|
||||
tcx.dcx().abort_if_errors();
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
|
@ -191,7 +191,7 @@ pub fn recursive_type_error(
|
|||
s
|
||||
};
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
tcx.dcx(),
|
||||
err_span,
|
||||
E0072,
|
||||
"recursive type{} {} {} infinite size",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue