From b1b9278851a9512a0c934c12f9c1800169c336f7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Jan 2024 12:17:35 +1100 Subject: Make `DiagnosticBuilder::emit` consuming. This works for most of its call sites. This is nice, because `emit` very much makes sense as a consuming operation -- indeed, `DiagnosticBuilderState` exists to ensure no diagnostic is emitted twice, but it uses runtime checks. For the small number of call sites where a consuming emit doesn't work, the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will be removed in subsequent commits.) Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes consuming, while `delay_as_bug_without_consuming` is added (which will also be removed in subsequent commits.) All this requires significant changes to `DiagnosticBuilder`'s chaining methods. Currently `DiagnosticBuilder` method chaining uses a non-consuming `&mut self -> &mut Self` style, which allows chaining to be used when the chain ends in `emit()`, like so: ``` struct_err(msg).span(span).emit(); ``` But it doesn't work when producing a `DiagnosticBuilder` value, requiring this: ``` let mut err = self.struct_err(msg); err.span(span); err ``` This style of chaining won't work with consuming `emit` though. For that, we need to use to a `self -> Self` style. That also would allow `DiagnosticBuilder` production to be chained, e.g.: ``` self.struct_err(msg).span(span) ``` However, removing the `&mut self -> &mut Self` style would require that individual modifications of a `DiagnosticBuilder` go from this: ``` err.span(span); ``` to this: ``` err = err.span(span); ``` There are *many* such places. I have a high tolerance for tedious refactorings, but even I gave up after a long time trying to convert them all. Instead, this commit has it both ways: the existing `&mut self -> Self` chaining methods are kept, and new `self -> Self` chaining methods are added, all of which have a `_mv` suffix (short for "move"). Changes to the existing `forward!` macro lets this happen with very little additional boilerplate code. I chose to add the suffix to the new chaining methods rather than the existing ones, because the number of changes required is much smaller that way. This doubled chainging is a bit clumsy, but I think it is worthwhile because it allows a *lot* of good things to subsequently happen. In this commit, there are many `mut` qualifiers removed in places where diagnostics are emitted without being modified. In subsequent commits: - chaining can be used more, making the code more concise; - more use of chaining also permits the removal of redundant diagnostic APIs like `struct_err_with_code`, which can be replaced easily with `struct_err` + `code_mv`; - `emit_without_diagnostic` can be removed, which simplifies a lot of machinery, removing the need for `DiagnosticBuilderState`. --- compiler/rustc_interface/src/queries.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'compiler/rustc_interface/src') diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 07bbe78dc2d..9da806e0779 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -108,7 +108,7 @@ impl<'tcx> Queries<'tcx> { pub fn parse(&self) -> Result> { self.parse.compute(|| { - passes::parse(&self.compiler.sess).map_err(|mut parse_error| parse_error.emit()) + passes::parse(&self.compiler.sess).map_err(|parse_error| parse_error.emit()) }) } -- cgit 1.4.1-3-g733a5 From db09eb2d3accf8909ea2813ebb00c58c7f2fad64 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 8 Jan 2024 08:27:38 +1100 Subject: Remove `{DiagCtxt,DiagCtxtInner}::emit_diagnostic_without_consuming`. They are no longer used, because `{DiagCtxt,DiagCtxtInner}::emit_diagnostic` are used everywhere instead. This also means `track_diagnostic` can become consuming. --- compiler/rustc_errors/src/lib.rs | 30 +++++++----------------------- compiler/rustc_interface/src/callbacks.rs | 2 +- 2 files changed, 8 insertions(+), 24 deletions(-) (limited to 'compiler/rustc_interface/src') diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 8411e188189..b97ec02675a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -509,11 +509,11 @@ pub enum StashKey { Cycle, } -fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) { - (*f)(d) +fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) { + (*f)(diag) } -pub static TRACK_DIAGNOSTICS: AtomicRef = +pub static TRACK_DIAGNOSTICS: AtomicRef = AtomicRef::new(&(default_track_diagnostic as _)); #[derive(Copy, Clone, Default)] @@ -1074,17 +1074,8 @@ impl DiagCtxt { self.inner.borrow_mut().emitter.emit_diagnostic(&db); } - pub fn emit_diagnostic(&self, mut diagnostic: Diagnostic) -> Option { - self.emit_diagnostic_without_consuming(&mut diagnostic) - } - - // It's unfortunate this exists. `emit_diagnostic` is preferred, because it - // consumes the diagnostic, thus ensuring it is emitted just once. - pub(crate) fn emit_diagnostic_without_consuming( - &self, - diagnostic: &mut Diagnostic, - ) -> Option { - self.inner.borrow_mut().emit_diagnostic_without_consuming(diagnostic) + pub fn emit_diagnostic(&self, diagnostic: Diagnostic) -> Option { + self.inner.borrow_mut().emit_diagnostic(diagnostic) } #[track_caller] @@ -1273,13 +1264,6 @@ impl DiagCtxtInner { } fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option { - self.emit_diagnostic_without_consuming(&mut diagnostic) - } - - fn emit_diagnostic_without_consuming( - &mut self, - diagnostic: &mut Diagnostic, - ) -> Option { if matches!(diagnostic.level, Error | Fatal) && self.treat_err_as_bug() { diagnostic.level = Bug; } @@ -1335,7 +1319,7 @@ impl DiagCtxtInner { } let mut guaranteed = None; - (*TRACK_DIAGNOSTICS)(diagnostic, &mut |diagnostic| { + (*TRACK_DIAGNOSTICS)(diagnostic, &mut |mut diagnostic| { if let Some(ref code) = diagnostic.code { self.emitted_diagnostic_codes.insert(code.clone()); } @@ -1371,7 +1355,7 @@ impl DiagCtxtInner { ); } - self.emitter.emit_diagnostic(diagnostic); + self.emitter.emit_diagnostic(&diagnostic); if diagnostic.is_error() { self.deduplicated_err_count += 1; } else if let Warning(_) = diagnostic.level { diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index ef00ced67ff..7458be2c86d 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -29,7 +29,7 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { /// This is a callback from `rustc_errors` as it cannot access the implicit state /// in `rustc_middle` otherwise. It is used when diagnostic messages are /// emitted and stores them in the current query, if there is one. -fn track_diagnostic(diagnostic: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) { +fn track_diagnostic(diagnostic: Diagnostic, f: &mut dyn FnMut(Diagnostic)) { tls::with_context_opt(|icx| { if let Some(icx) = icx { if let Some(diagnostics) = icx.diagnostics { -- cgit 1.4.1-3-g733a5