Use a dedicated type instead of a reference for the diagnostic context
This paves the way for tracking more state (e.g. error tainting) in the diagnostic context handle
This commit is contained in:
parent
c91edc3888
commit
7ba82d61eb
77 changed files with 363 additions and 328 deletions
|
@ -414,6 +414,19 @@ pub struct DiagCtxt {
|
|||
inner: Lock<DiagCtxtInner>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct DiagCtxtHandle<'a> {
|
||||
dcx: &'a DiagCtxt,
|
||||
}
|
||||
|
||||
impl<'a> std::ops::Deref for DiagCtxtHandle<'a> {
|
||||
type Target = &'a DiagCtxt;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.dcx
|
||||
}
|
||||
}
|
||||
|
||||
/// This inner struct exists to keep it all behind a single lock;
|
||||
/// this is done to prevent possible deadlocks in a multi-threaded compiler,
|
||||
/// as well as inconsistent state observation.
|
||||
|
@ -608,7 +621,7 @@ impl DiagCtxt {
|
|||
}
|
||||
|
||||
pub fn make_silent(
|
||||
&mut self,
|
||||
&self,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
fatal_note: Option<String>,
|
||||
emit_fatal_diagnostic: bool,
|
||||
|
@ -623,7 +636,7 @@ impl DiagCtxt {
|
|||
});
|
||||
}
|
||||
|
||||
fn wrap_emitter<F>(&mut self, f: F)
|
||||
fn wrap_emitter<F>(&self, f: F)
|
||||
where
|
||||
F: FnOnce(DiagCtxtInner) -> Box<DynEmitter>,
|
||||
{
|
||||
|
@ -738,6 +751,12 @@ impl DiagCtxt {
|
|||
*fulfilled_expectations = Default::default();
|
||||
}
|
||||
|
||||
pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> {
|
||||
DiagCtxtHandle { dcx: self }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DiagCtxtHandle<'a> {
|
||||
/// Stashes a diagnostic for possible later improvement in a different,
|
||||
/// later stage of the compiler. Possible actions depend on the diagnostic
|
||||
/// level:
|
||||
|
@ -745,8 +764,8 @@ impl DiagCtxt {
|
|||
/// - Level::Error: immediately counted as an error that has occurred, because it
|
||||
/// is guaranteed to be emitted eventually. Can be later accessed with the
|
||||
/// provided `span` and `key` through
|
||||
/// [`DiagCtxt::try_steal_modify_and_emit_err`] or
|
||||
/// [`DiagCtxt::try_steal_replace_and_emit_err`]. These do not allow
|
||||
/// [`DiagCtxtHandle::try_steal_modify_and_emit_err`] or
|
||||
/// [`DiagCtxtHandle::try_steal_replace_and_emit_err`]. These do not allow
|
||||
/// cancellation or downgrading of the error. Returns
|
||||
/// `Some(ErrorGuaranteed)`.
|
||||
/// - Level::DelayedBug: this does happen occasionally with errors that are
|
||||
|
@ -757,7 +776,7 @@ impl DiagCtxt {
|
|||
/// user-facing error. Returns `Some(ErrorGuaranteed)` as is normal for
|
||||
/// delayed bugs.
|
||||
/// - Level::Warning and lower (i.e. !is_error()): can be accessed with the
|
||||
/// provided `span` and `key` through [`DiagCtxt::steal_non_err()`]. This
|
||||
/// provided `span` and `key` through [`DiagCtxtHandle::steal_non_err()`]. This
|
||||
/// allows cancelling and downgrading of the diagnostic. Returns `None`.
|
||||
pub fn stash_diagnostic(
|
||||
&self,
|
||||
|
@ -793,7 +812,7 @@ impl DiagCtxt {
|
|||
/// Steal a previously stashed non-error diagnostic with the given `Span`
|
||||
/// and [`StashKey`] as the key. Panics if the found diagnostic is an
|
||||
/// error.
|
||||
pub fn steal_non_err(&self, span: Span, key: StashKey) -> Option<Diag<'_, ()>> {
|
||||
pub fn steal_non_err(self, span: Span, key: StashKey) -> Option<Diag<'a, ()>> {
|
||||
let key = (span.with_parent(None), key);
|
||||
// FIXME(#120456) - is `swap_remove` correct?
|
||||
let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key)?;
|
||||
|
@ -807,7 +826,7 @@ impl DiagCtxt {
|
|||
/// no matching diagnostic is found. Panics if the found diagnostic's level
|
||||
/// isn't `Level::Error`.
|
||||
pub fn try_steal_modify_and_emit_err<F>(
|
||||
&self,
|
||||
self,
|
||||
span: Span,
|
||||
key: StashKey,
|
||||
mut modify_err: F,
|
||||
|
@ -833,7 +852,7 @@ impl DiagCtxt {
|
|||
/// [`StashKey`] as the key, cancels it if found, and emits `new_err`.
|
||||
/// Panics if the found diagnostic's level isn't `Level::Error`.
|
||||
pub fn try_steal_replace_and_emit_err(
|
||||
&self,
|
||||
self,
|
||||
span: Span,
|
||||
key: StashKey,
|
||||
new_err: Diag<'_>,
|
||||
|
@ -1106,18 +1125,18 @@ impl DiagCtxt {
|
|||
//
|
||||
// Functions beginning with `struct_`/`create_` create a diagnostic. Other
|
||||
// functions create and emit a diagnostic all in one go.
|
||||
impl DiagCtxt {
|
||||
impl<'a> DiagCtxtHandle<'a> {
|
||||
// No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
|
||||
// user-facing.
|
||||
#[track_caller]
|
||||
pub fn struct_bug(&self, msg: impl Into<Cow<'static, str>>) -> Diag<'_, BugAbort> {
|
||||
pub fn struct_bug(self, msg: impl Into<Cow<'static, str>>) -> Diag<'a, BugAbort> {
|
||||
Diag::new(self, Bug, msg.into())
|
||||
}
|
||||
|
||||
// No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
|
||||
// user-facing.
|
||||
#[track_caller]
|
||||
pub fn bug(&self, msg: impl Into<Cow<'static, str>>) -> ! {
|
||||
pub fn bug(self, msg: impl Into<Cow<'static, str>>) -> ! {
|
||||
self.struct_bug(msg).emit()
|
||||
}
|
||||
|
||||
|
@ -1125,111 +1144,108 @@ impl DiagCtxt {
|
|||
// user-facing.
|
||||
#[track_caller]
|
||||
pub fn struct_span_bug(
|
||||
&self,
|
||||
self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<Cow<'static, str>>,
|
||||
) -> Diag<'_, BugAbort> {
|
||||
) -> Diag<'a, BugAbort> {
|
||||
self.struct_bug(msg).with_span(span)
|
||||
}
|
||||
|
||||
// No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
|
||||
// user-facing.
|
||||
#[track_caller]
|
||||
pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! {
|
||||
pub fn span_bug(self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! {
|
||||
self.struct_span_bug(span, msg.into()).emit()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn create_bug<'a>(&'a self, bug: impl Diagnostic<'a, BugAbort>) -> Diag<'a, BugAbort> {
|
||||
pub fn create_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> Diag<'a, BugAbort> {
|
||||
bug.into_diag(self, Bug)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn emit_bug<'a>(&'a self, bug: impl Diagnostic<'a, BugAbort>) -> ! {
|
||||
pub fn emit_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> ! {
|
||||
self.create_bug(bug).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_fatal(&self, msg: impl Into<DiagMessage>) -> Diag<'_, FatalAbort> {
|
||||
pub fn struct_fatal(self, msg: impl Into<DiagMessage>) -> Diag<'a, FatalAbort> {
|
||||
Diag::new(self, Fatal, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn fatal(&self, msg: impl Into<DiagMessage>) -> ! {
|
||||
pub fn fatal(self, msg: impl Into<DiagMessage>) -> ! {
|
||||
self.struct_fatal(msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_fatal(
|
||||
&self,
|
||||
self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagMessage>,
|
||||
) -> Diag<'_, FatalAbort> {
|
||||
) -> Diag<'a, FatalAbort> {
|
||||
self.struct_fatal(msg).with_span(span)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) -> ! {
|
||||
pub fn span_fatal(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) -> ! {
|
||||
self.struct_span_fatal(span, msg).emit()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn create_fatal<'a>(
|
||||
&'a self,
|
||||
fatal: impl Diagnostic<'a, FatalAbort>,
|
||||
) -> Diag<'a, FatalAbort> {
|
||||
pub fn create_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> Diag<'a, FatalAbort> {
|
||||
fatal.into_diag(self, Fatal)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn emit_fatal<'a>(&'a self, fatal: impl Diagnostic<'a, FatalAbort>) -> ! {
|
||||
pub fn emit_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> ! {
|
||||
self.create_fatal(fatal).emit()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn create_almost_fatal<'a>(
|
||||
&'a self,
|
||||
pub fn create_almost_fatal(
|
||||
self,
|
||||
fatal: impl Diagnostic<'a, FatalError>,
|
||||
) -> Diag<'a, FatalError> {
|
||||
fatal.into_diag(self, Fatal)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn emit_almost_fatal<'a>(&'a self, fatal: impl Diagnostic<'a, FatalError>) -> FatalError {
|
||||
pub fn emit_almost_fatal(self, fatal: impl Diagnostic<'a, FatalError>) -> FatalError {
|
||||
self.create_almost_fatal(fatal).emit()
|
||||
}
|
||||
|
||||
// FIXME: This method should be removed (every error should have an associated error code).
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_err(&self, msg: impl Into<DiagMessage>) -> Diag<'_> {
|
||||
pub fn struct_err(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
|
||||
Diag::new(self, Error, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn err(&self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed {
|
||||
pub fn err(self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed {
|
||||
self.struct_err(msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_err(
|
||||
&self,
|
||||
self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagMessage>,
|
||||
) -> Diag<'_> {
|
||||
) -> Diag<'a> {
|
||||
self.struct_err(msg).with_span(span)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_err(
|
||||
&self,
|
||||
self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagMessage>,
|
||||
) -> ErrorGuaranteed {
|
||||
|
@ -1237,12 +1253,12 @@ impl DiagCtxt {
|
|||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn create_err<'a>(&'a self, err: impl Diagnostic<'a>) -> Diag<'a> {
|
||||
pub fn create_err(self, err: impl Diagnostic<'a>) -> Diag<'a> {
|
||||
err.into_diag(self, Error)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn emit_err<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
|
||||
pub fn emit_err(self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
|
||||
self.create_err(err).emit()
|
||||
}
|
||||
|
||||
|
@ -1251,7 +1267,7 @@ impl DiagCtxt {
|
|||
// No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
|
||||
// user-facing.
|
||||
#[track_caller]
|
||||
pub fn delayed_bug(&self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed {
|
||||
pub fn delayed_bug(self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed {
|
||||
Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).emit()
|
||||
}
|
||||
|
||||
|
@ -1264,7 +1280,7 @@ impl DiagCtxt {
|
|||
// user-facing.
|
||||
#[track_caller]
|
||||
pub fn span_delayed_bug(
|
||||
&self,
|
||||
self,
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<Cow<'static, str>>,
|
||||
) -> ErrorGuaranteed {
|
||||
|
@ -1273,45 +1289,45 @@ impl DiagCtxt {
|
|||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_warn(&self, msg: impl Into<DiagMessage>) -> Diag<'_, ()> {
|
||||
pub fn struct_warn(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
|
||||
Diag::new(self, Warning, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn warn(&self, msg: impl Into<DiagMessage>) {
|
||||
pub fn warn(self, msg: impl Into<DiagMessage>) {
|
||||
self.struct_warn(msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_warn(
|
||||
&self,
|
||||
self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagMessage>,
|
||||
) -> Diag<'_, ()> {
|
||||
) -> Diag<'a, ()> {
|
||||
self.struct_warn(msg).with_span(span)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
|
||||
pub fn span_warn(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
|
||||
self.struct_span_warn(span, msg).emit()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn create_warn<'a>(&'a self, warning: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
|
||||
pub fn create_warn(self, warning: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
|
||||
warning.into_diag(self, Warning)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn emit_warn<'a>(&'a self, warning: impl Diagnostic<'a, ()>) {
|
||||
pub fn emit_warn(self, warning: impl Diagnostic<'a, ()>) {
|
||||
self.create_warn(warning).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_note(&self, msg: impl Into<DiagMessage>) -> Diag<'_, ()> {
|
||||
pub fn struct_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
|
||||
Diag::new(self, Note, msg)
|
||||
}
|
||||
|
||||
|
@ -1324,54 +1340,50 @@ impl DiagCtxt {
|
|||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_note(
|
||||
&self,
|
||||
self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagMessage>,
|
||||
) -> Diag<'_, ()> {
|
||||
) -> Diag<'a, ()> {
|
||||
self.struct_note(msg).with_span(span)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_note(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
|
||||
pub fn span_note(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
|
||||
self.struct_span_note(span, msg).emit()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn create_note<'a>(&'a self, note: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
|
||||
pub fn create_note(self, note: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
|
||||
note.into_diag(self, Note)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn emit_note<'a>(&'a self, note: impl Diagnostic<'a, ()>) {
|
||||
pub fn emit_note(self, note: impl Diagnostic<'a, ()>) {
|
||||
self.create_note(note).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_help(&self, msg: impl Into<DiagMessage>) -> Diag<'_, ()> {
|
||||
pub fn struct_help(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
|
||||
Diag::new(self, Help, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_failure_note(&self, msg: impl Into<DiagMessage>) -> Diag<'_, ()> {
|
||||
pub fn struct_failure_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
|
||||
Diag::new(self, FailureNote, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_allow(&self, msg: impl Into<DiagMessage>) -> Diag<'_, ()> {
|
||||
pub fn struct_allow(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
|
||||
Diag::new(self, Allow, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_expect(
|
||||
&self,
|
||||
msg: impl Into<DiagMessage>,
|
||||
id: LintExpectationId,
|
||||
) -> Diag<'_, ()> {
|
||||
pub fn struct_expect(self, msg: impl Into<DiagMessage>, id: LintExpectationId) -> Diag<'a, ()> {
|
||||
Diag::new(self, Expect(id), msg)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue