1
Fork 0

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:
bors 2023-12-26 02:24:39 +00:00
commit 2271c26e4a
347 changed files with 2334 additions and 2696 deletions

View file

@ -151,10 +151,10 @@ where
let (our_span, frames) = get_span_and_frames();
let span = span.unwrap_or(our_span);
let err = mk(span, frames);
let mut err = tcx.sess.create_err(err);
let mut err = tcx.dcx().create_err(err);
let msg = error.diagnostic_message();
error.add_args(tcx.sess.dcx(), &mut err);
error.add_args(tcx.dcx(), &mut err);
// Use *our* span to label the interp error
err.span_label(our_span, msg);

View file

@ -391,7 +391,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
if ecx.tcx.is_ctfe_mir_available(def) {
Ok(ecx.tcx.mir_for_ctfe(def))
} else if ecx.tcx.def_kind(def) == DefKind::AssocConst {
let guar = ecx.tcx.sess.span_delayed_bug(
let guar = ecx.tcx.dcx().span_delayed_bug(
rustc_span::DUMMY_SP,
"This is likely a const item that is missing from its impl",
);
@ -621,7 +621,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
if is_error {
let guard = ecx
.tcx
.sess
.dcx()
.span_delayed_bug(span, "The deny lint should have already errored");
throw_inval!(AlreadyReported(guard.into()));
}
@ -630,7 +630,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
// current number of evaluated terminators is a power of 2. The latter gives us a cheap
// way to implement exponential backoff.
let span = ecx.cur_span();
ecx.tcx.sess.emit_warning(LongRunningWarn { span, item_span: ecx.tcx.span });
ecx.tcx.dcx().emit_warning(LongRunningWarn { span, item_span: ecx.tcx.span });
}
}

View file

@ -61,7 +61,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
match err {
ValTreeCreationError::NodesOverflow => {
let span = tcx.hir().span_if_local(did);
tcx.sess.emit_err(MaxNumNodesInConstErr { span, global_const_id });
tcx.dcx().emit_err(MaxNumNodesInConstErr { span, global_const_id });
Ok(None)
}

View file

@ -439,8 +439,8 @@ pub trait ReportErrorExt {
Self: Sized,
{
ty::tls::with(move |tcx| {
let mut builder = tcx.sess.struct_allow(DiagnosticMessage::Str(String::new().into()));
let dcx = tcx.sess.dcx();
let dcx = tcx.dcx();
let mut builder = dcx.struct_allow(DiagnosticMessage::Str(String::new().into()));
let message = self.diagnostic_message();
self.add_args(dcx, &mut builder);
let s = dcx.eagerly_translate_to_string(message, builder.args());

View file

@ -473,9 +473,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
backtrace.print_backtrace();
// FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the
// label and arguments from the InterpError.
let dcx = self.tcx.sess.dcx();
let dcx = self.tcx.dcx();
#[allow(rustc::untranslatable_diagnostic)]
let mut diag = self.tcx.sess.struct_allow("");
let mut diag = dcx.struct_allow("");
let msg = e.diagnostic_message();
e.add_args(dcx, &mut diag);
let s = dcx.eagerly_translate_to_string(msg, diag.args());

View file

@ -96,7 +96,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval:
// in the value the dangling reference lies.
// The `span_delayed_bug` ensures that we don't forget such a check in validation.
if tcx.try_get_global_alloc(alloc_id).is_none() {
tcx.sess.span_delayed_bug(ecx.tcx.span, "tried to intern dangling pointer");
tcx.dcx().span_delayed_bug(ecx.tcx.span, "tried to intern dangling pointer");
}
// treat dangling pointers like other statics
// just to stop trying to recurse into them
@ -185,7 +185,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
} else {
// Validation will error (with a better message) on an invalid vtable pointer.
// Let validation show the error message, but make sure it *does* error.
tcx.sess
tcx.dcx()
.span_delayed_bug(tcx.span, "vtables pointers cannot be integer pointers");
}
}
@ -375,7 +375,7 @@ pub fn intern_const_alloc_recursive<
match res {
Ok(()) => {}
Err(error) => {
ecx.tcx.sess.span_delayed_bug(
ecx.tcx.dcx().span_delayed_bug(
ecx.tcx.span,
format!(
"error during interning should later cause validation failure: {}",
@ -424,7 +424,7 @@ pub fn intern_const_alloc_recursive<
// something that cannot be promoted, which in constants means values that have
// drop glue, such as the example above.
InternKind::Constant => {
ecx.tcx.sess.emit_err(UnsupportedUntypedPointer { span: ecx.tcx.span });
ecx.tcx.dcx().emit_err(UnsupportedUntypedPointer { span: ecx.tcx.span });
// For better errors later, mark the allocation as immutable.
alloc.mutability = Mutability::Not;
}
@ -440,7 +440,7 @@ pub fn intern_const_alloc_recursive<
} else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
// Codegen does not like dangling pointers, and generally `tcx` assumes that
// all allocations referenced anywhere actually exist. So, make sure we error here.
let reported = ecx.tcx.sess.emit_err(DanglingPtrInFinal { span: ecx.tcx.span });
let reported = ecx.tcx.dcx().emit_err(DanglingPtrInFinal { span: ecx.tcx.span });
return Err(reported);
} else if ecx.tcx.try_get_global_alloc(alloc_id).is_none() {
// We have hit an `AllocId` that is neither in local or global memory and isn't

View file

@ -244,7 +244,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
// `async` functions cannot be `const fn`. This is checked during AST lowering, so there's
// no need to emit duplicate errors here.
if self.ccx.is_async() || body.coroutine.is_some() {
tcx.sess.span_delayed_bug(body.span, "`async` functions cannot be `const fn`");
tcx.dcx().span_delayed_bug(body.span, "`async` functions cannot be `const fn`");
return;
}
@ -276,10 +276,10 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
let secondary_errors = mem::take(&mut self.secondary_errors);
if self.error_emitted.is_none() {
for error in secondary_errors {
self.tcx.sess.dcx().emit_diagnostic(error);
self.tcx.dcx().emit_diagnostic(error);
}
} else {
assert!(self.tcx.sess.has_errors().is_some());
assert!(self.tcx.dcx().has_errors().is_some());
}
}
@ -354,7 +354,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
fn check_static(&mut self, def_id: DefId, span: Span) {
if self.tcx.is_thread_local_static(def_id) {
self.tcx
.sess
.dcx()
.span_delayed_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
}
self.check_op_spanned(ops::StaticAccess, span)
@ -994,5 +994,5 @@ fn is_int_bool_or_char(ty: Ty<'_>) -> bool {
fn emit_unstable_in_stable_error(ccx: &ConstCx<'_, '_>, span: Span, gate: Symbol) {
let attr_span = ccx.tcx.def_span(ccx.def_id()).shrink_to_lo();
ccx.tcx.sess.emit_err(UnstableInStable { gate: gate.to_string(), span, attr_span });
ccx.dcx().emit_err(UnstableInStable { gate: gate.to_string(), span, attr_span });
}

View file

@ -5,6 +5,7 @@
//! it finds operations that are invalid in a certain context.
use rustc_attr as attr;
use rustc_errors::DiagCtxt;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::mir;
@ -44,6 +45,10 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
ConstCx { body, tcx, param_env, const_kind }
}
pub(crate) fn dcx(&self) -> &'tcx DiagCtxt {
self.tcx.dcx()
}
pub fn def_id(&self) -> LocalDefId {
self.body.source.def_id().expect_local()
}
@ -112,7 +117,7 @@ pub fn is_const_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
None if is_parent_const_stable_trait(tcx, def_id) => {
// Remove this when `#![feature(const_trait_impl)]` is stabilized,
// returning `true` unconditionally.
tcx.sess.span_delayed_bug(
tcx.dcx().span_delayed_bug(
tcx.def_span(def_id),
"trait implementations cannot be const stable yet",
);

View file

@ -77,7 +77,7 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp {
pub struct FnCallIndirect;
impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
ccx.tcx.sess.create_err(errors::UnallowedFnPointerCall { span, kind: ccx.const_kind() })
ccx.dcx().create_err(errors::UnallowedFnPointerCall { span, kind: ccx.const_kind() })
}
}
@ -148,7 +148,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
CallKind::Normal { desugaring: Some((kind, self_ty)), .. } => {
macro_rules! error {
($err:ident) => {
tcx.sess.create_err(errors::$err {
tcx.dcx().create_err(errors::$err {
span,
ty: self_ty,
kind: ccx.const_kind(),
@ -192,7 +192,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
_ => None,
};
let mut err = tcx.sess.create_err(errors::NonConstClosure {
let mut err = tcx.dcx().create_err(errors::NonConstClosure {
span,
kind: ccx.const_kind(),
note,
@ -203,7 +203,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
}
CallKind::Operator { trait_id, self_ty, .. } => {
let mut err = if let CallSource::MatchCmp = call_source {
tcx.sess.create_err(errors::NonConstMatchEq {
tcx.dcx().create_err(errors::NonConstMatchEq {
span,
kind: ccx.const_kind(),
ty: self_ty,
@ -248,7 +248,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
_ => {}
}
}
tcx.sess.create_err(errors::NonConstOperator {
tcx.dcx().create_err(errors::NonConstOperator {
span,
kind: ccx.const_kind(),
sugg,
@ -266,7 +266,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
None
};
let mut err = tcx.sess.create_err(errors::NonConstDerefCoercion {
let mut err = tcx.dcx().create_err(errors::NonConstDerefCoercion {
span,
ty: self_ty,
kind: ccx.const_kind(),
@ -277,11 +277,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span)));
err
}
_ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentMethods) => ccx
.tcx
.sess
.create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }),
_ => ccx.tcx.sess.create_err(errors::NonConstFnCall {
_ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentMethods) => {
ccx.dcx().create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() })
}
_ => ccx.dcx().create_err(errors::NonConstFnCall {
span,
def_path_str: ccx.tcx.def_path_str_with_args(callee, args),
kind: ccx.const_kind(),
@ -319,8 +318,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
let FnCallUnstable(def_id, feature) = *self;
let mut err = ccx
.tcx
.sess
.dcx()
.create_err(errors::UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) });
if ccx.is_const_stable_const_fn() {
@ -362,7 +360,7 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine {
sym::const_async_blocks,
)
} else {
ccx.tcx.sess.create_err(errors::UnallowedOpInConstContext { span, msg })
ccx.dcx().create_err(errors::UnallowedOpInConstContext { span, msg })
}
}
}
@ -371,7 +369,7 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine {
pub struct HeapAllocation;
impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
ccx.tcx.sess.create_err(errors::UnallowedHeapAllocations {
ccx.dcx().create_err(errors::UnallowedHeapAllocations {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0010)).then_some(()),
@ -383,7 +381,7 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
pub struct InlineAsm;
impl<'tcx> NonConstOp<'tcx> for InlineAsm {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
ccx.tcx.sess.create_err(errors::UnallowedInlineAsm { span, kind: ccx.const_kind() })
ccx.dcx().create_err(errors::UnallowedInlineAsm { span, kind: ccx.const_kind() })
}
}
@ -394,7 +392,7 @@ pub struct LiveDrop<'tcx> {
}
impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
ccx.tcx.sess.create_err(errors::LiveDrop {
ccx.dcx().create_err(errors::LiveDrop {
span,
dropped_ty: self.dropped_ty,
kind: ccx.const_kind(),
@ -432,14 +430,14 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
// FIXME: Maybe a more elegant solution to this if else case
if let hir::ConstContext::Static(_) = ccx.const_kind() {
ccx.tcx.sess.create_err(errors::InteriorMutableDataRefer {
ccx.dcx().create_err(errors::InteriorMutableDataRefer {
span,
opt_help: Some(()),
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()),
})
} else {
ccx.tcx.sess.create_err(errors::InteriorMutableDataRefer {
ccx.dcx().create_err(errors::InteriorMutableDataRefer {
span,
opt_help: None,
kind: ccx.const_kind(),
@ -468,12 +466,12 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
match self.0 {
hir::BorrowKind::Raw => ccx.tcx.sess.create_err(errors::UnallowedMutableRefsRaw {
hir::BorrowKind::Raw => ccx.dcx().create_err(errors::UnallowedMutableRefsRaw {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
}),
hir::BorrowKind::Ref => ccx.tcx.sess.create_err(errors::UnallowedMutableRefs {
hir::BorrowKind::Ref => ccx.dcx().create_err(errors::UnallowedMutableRefs {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
@ -530,7 +528,7 @@ impl<'tcx> NonConstOp<'tcx> for MutDeref {
pub struct PanicNonStr;
impl<'tcx> NonConstOp<'tcx> for PanicNonStr {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
ccx.tcx.sess.create_err(errors::PanicNonStrErr { span })
ccx.dcx().create_err(errors::PanicNonStrErr { span })
}
}
@ -542,7 +540,7 @@ pub struct RawPtrComparison;
impl<'tcx> NonConstOp<'tcx> for RawPtrComparison {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
// FIXME(const_trait_impl): revert to span_bug?
ccx.tcx.sess.create_err(errors::RawPtrComparisonErr { span })
ccx.dcx().create_err(errors::RawPtrComparisonErr { span })
}
}
@ -570,7 +568,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref {
pub struct RawPtrToIntCast;
impl<'tcx> NonConstOp<'tcx> for RawPtrToIntCast {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
ccx.tcx.sess.create_err(errors::RawPtrToIntErr { span })
ccx.dcx().create_err(errors::RawPtrToIntErr { span })
}
}
@ -587,7 +585,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
}
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
ccx.tcx.sess.create_err(errors::StaticAccessErr {
ccx.dcx().create_err(errors::StaticAccessErr {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0013)).then_some(()),
@ -600,7 +598,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
pub struct ThreadLocalAccess;
impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
ccx.tcx.sess.create_err(errors::NonConstOpErr { span })
ccx.dcx().create_err(errors::NonConstOpErr { span })
}
}

View file

@ -119,7 +119,7 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
let span = self.body.source_info(location).span;
// We use `span_delayed_bug` as we might see broken MIR when other errors have already
// occurred.
self.tcx.sess.dcx().span_delayed_bug(
self.tcx.dcx().span_delayed_bug(
span,
format!(
"broken MIR in {:?} ({}) at {:?}:\n{}",
@ -527,7 +527,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
fn visit_source_scope(&mut self, scope: SourceScope) {
if self.body.source_scopes.get(scope).is_none() {
self.tcx.sess.dcx().span_delayed_bug(
self.tcx.dcx().span_delayed_bug(
self.body.span,
format!(
"broken MIR in {:?} ({}):\ninvalid source scope {:?}",