diff options
| author | bors <bors@rust-lang.org> | 2023-12-23 04:09:45 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-12-23 04:09:45 +0000 |
| commit | c03d978a4bcb7c01d8cdf80bd7600b27e2d21588 (patch) | |
| tree | ad0c5d00194aa5bb53375d28a77f3a3077aaa980 /compiler/rustc_errors/src | |
| parent | 495203bf61efabecc2c460be38e1eb0f9952601b (diff) | |
| parent | 8c50e3eaeef34470a80f099feb2cbbdba2e7d61f (diff) | |
| download | rust-c03d978a4bcb7c01d8cdf80bd7600b27e2d21588.tar.gz rust-c03d978a4bcb7c01d8cdf80bd7600b27e2d21588.zip | |
Auto merge of #119237 - compiler-errors:rollup-umyyu7d, r=compiler-errors
Rollup of 6 pull requests
Successful merges:
- #119012 (Extract `layout_of_{struct,enum}` fn)
- #119077 (Separate MIR lints from validation)
- #119171 (Cleanup error handlers: round 4)
- #119198 (Split coroutine desugaring kind from source)
- #119222 (Add `IntoAsyncIterator`)
- #119230 (Exhaustiveness: clean up after librarification)
r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_errors/src')
| -rw-r--r-- | compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic.rs | 79 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic_builder.rs | 80 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic_impls.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/emitter.rs | 37 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/json.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/lib.rs | 327 |
7 files changed, 228 insertions, 321 deletions
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index da266bf9c63..48e48f59a99 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -60,7 +60,7 @@ impl Emitter for AnnotateSnippetEmitterWriter { self.emit_messages_default( &diag.level, - &diag.message, + &diag.messages, &fluent_args, &diag.code, &primary_span, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index be506806065..c226b2d41bd 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -103,7 +103,7 @@ pub struct Diagnostic { // outside of what methods in this crate themselves allow. pub(crate) level: Level, - pub message: Vec<(DiagnosticMessage, Style)>, + pub messages: Vec<(DiagnosticMessage, Style)>, pub code: Option<DiagnosticId>, pub span: MultiSpan, pub children: Vec<SubDiagnostic>, @@ -161,9 +161,8 @@ pub enum DiagnosticId { #[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)] pub struct SubDiagnostic { pub level: Level, - pub message: Vec<(DiagnosticMessage, Style)>, + pub messages: Vec<(DiagnosticMessage, Style)>, pub span: MultiSpan, - pub render_span: Option<MultiSpan>, } #[derive(Debug, PartialEq, Eq)] @@ -216,14 +215,14 @@ impl StringPart { impl Diagnostic { #[track_caller] pub fn new<M: Into<DiagnosticMessage>>(level: Level, message: M) -> Self { - Diagnostic::new_with_code(level, None, message) + Diagnostic::new_with_messages(level, vec![(message.into(), Style::NoStyle)]) } #[track_caller] pub fn new_with_messages(level: Level, messages: Vec<(DiagnosticMessage, Style)>) -> Self { Diagnostic { level, - message: messages, + messages, code: None, span: MultiSpan::new(), children: vec![], @@ -235,26 +234,6 @@ impl Diagnostic { } } - #[track_caller] - pub(crate) fn new_with_code<M: Into<DiagnosticMessage>>( - level: Level, - code: Option<DiagnosticId>, - message: M, - ) -> Self { - Diagnostic { - level, - message: vec![(message.into(), Style::NoStyle)], - code, - span: MultiSpan::new(), - children: vec![], - suggestions: Ok(vec![]), - args: Default::default(), - sort_span: DUMMY_SP, - is_lint: false, - emitted_at: DiagnosticLocation::caller(), - } - } - #[inline(always)] pub fn level(&self) -> Level { self.level @@ -445,7 +424,7 @@ impl Diagnostic { /// Add a note attached to this diagnostic. #[rustc_lint_diagnostics] pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { - self.sub(Level::Note, msg, MultiSpan::new(), None); + self.sub(Level::Note, msg, MultiSpan::new()); self } @@ -453,14 +432,14 @@ impl Diagnostic { &mut self, msg: Vec<(M, Style)>, ) -> &mut Self { - self.sub_with_highlights(Level::Note, msg, MultiSpan::new(), None); + self.sub_with_highlights(Level::Note, msg, MultiSpan::new()); self } /// Prints the span with a note above it. /// This is like [`Diagnostic::note()`], but it gets its own span. pub fn note_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { - self.sub(Level::OnceNote, msg, MultiSpan::new(), None); + self.sub(Level::OnceNote, msg, MultiSpan::new()); self } @@ -472,7 +451,7 @@ impl Diagnostic { sp: S, msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { - self.sub(Level::Note, msg, sp.into(), None); + self.sub(Level::Note, msg, sp.into()); self } @@ -483,14 +462,14 @@ impl Diagnostic { sp: S, msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { - self.sub(Level::OnceNote, msg, sp.into(), None); + self.sub(Level::OnceNote, msg, sp.into()); self } /// Add a warning attached to this diagnostic. #[rustc_lint_diagnostics] pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { - self.sub(Level::Warning(None), msg, MultiSpan::new(), None); + self.sub(Level::Warning(None), msg, MultiSpan::new()); self } @@ -502,27 +481,27 @@ impl Diagnostic { sp: S, msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { - self.sub(Level::Warning(None), msg, sp.into(), None); + self.sub(Level::Warning(None), msg, sp.into()); self } /// Add a help message attached to this diagnostic. #[rustc_lint_diagnostics] pub fn help(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { - self.sub(Level::Help, msg, MultiSpan::new(), None); + self.sub(Level::Help, msg, MultiSpan::new()); self } /// Prints the span with a help above it. /// This is like [`Diagnostic::help()`], but it gets its own span. pub fn help_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { - self.sub(Level::OnceHelp, msg, MultiSpan::new(), None); + self.sub(Level::OnceHelp, msg, MultiSpan::new()); self } /// Add a help message attached to this diagnostic with a customizable highlighted message. pub fn highlighted_help(&mut self, msg: Vec<(String, Style)>) -> &mut Self { - self.sub_with_highlights(Level::Help, msg, MultiSpan::new(), None); + self.sub_with_highlights(Level::Help, msg, MultiSpan::new()); self } @@ -534,7 +513,7 @@ impl Diagnostic { sp: S, msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { - self.sub(Level::Help, msg, sp.into(), None); + self.sub(Level::Help, msg, sp.into()); self } @@ -925,7 +904,7 @@ impl Diagnostic { } pub fn set_primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { - self.message[0] = (msg.into(), Style::NoStyle); + self.messages[0] = (msg.into(), Style::NoStyle); self } @@ -952,8 +931,8 @@ impl Diagnostic { self.args = args; } - pub fn styled_message(&self) -> &[(DiagnosticMessage, Style)] { - &self.message + pub fn messages(&self) -> &[(DiagnosticMessage, Style)] { + &self.messages } /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by @@ -964,7 +943,7 @@ impl Diagnostic { attr: impl Into<SubdiagnosticMessage>, ) -> DiagnosticMessage { let msg = - self.message.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages"); + self.messages.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages"); msg.with_subdiagnostic_message(attr.into()) } @@ -972,21 +951,14 @@ impl Diagnostic { /// public methods above. /// /// Used by `proc_macro_server` for implementing `server::Diagnostic`. - pub fn sub( - &mut self, - level: Level, - message: impl Into<SubdiagnosticMessage>, - span: MultiSpan, - render_span: Option<MultiSpan>, - ) { + pub fn sub(&mut self, level: Level, message: impl Into<SubdiagnosticMessage>, span: MultiSpan) { let sub = SubDiagnostic { level, - message: vec![( + messages: vec![( self.subdiagnostic_message_to_diagnostic_message(message), Style::NoStyle, )], span, - render_span, }; self.children.push(sub); } @@ -996,15 +968,14 @@ impl Diagnostic { fn sub_with_highlights<M: Into<SubdiagnosticMessage>>( &mut self, level: Level, - message: Vec<(M, Style)>, + messages: Vec<(M, Style)>, span: MultiSpan, - render_span: Option<MultiSpan>, ) { - let message = message + let messages = messages .into_iter() .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.0), m.1)) .collect(); - let sub = SubDiagnostic { level, message, span, render_span }; + let sub = SubDiagnostic { level, messages, span }; self.children.push(sub); } @@ -1022,7 +993,7 @@ impl Diagnostic { ) { ( &self.level, - &self.message, + &self.messages, self.args().collect(), &self.code, &self.span, diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 828560ec452..4703e71523d 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -15,7 +15,7 @@ use std::ops::{Deref, DerefMut}; use std::panic; use std::thread::panicking; -/// Trait implemented by error types. This should not be implemented manually. Instead, use +/// Trait implemented by error types. This is rarely implemented manually. Instead, use /// `#[derive(Diagnostic)]` -- see [rustc_macros::Diagnostic]. #[rustc_diagnostic_item = "IntoDiagnostic"] pub trait IntoDiagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> { @@ -43,24 +43,7 @@ where /// extending `DiagCtxtFlags`. #[must_use] #[derive(Clone)] -pub struct DiagnosticBuilder<'a, G: EmissionGuarantee> { - inner: DiagnosticBuilderInner<'a>, - _marker: PhantomData<G>, -} - -/// This type exists only for `DiagnosticBuilder::forget_guarantee`, because it: -/// 1. lacks the `G` parameter and therefore `DiagnosticBuilder<G1>` can be -/// converted into `DiagnosticBuilder<G2>` while reusing the `inner` field -/// 2. can implement the `Drop` "bomb" instead of `DiagnosticBuilder`, as it -/// contains all of the data (`state` + `diagnostic`) of `DiagnosticBuilder` -/// -/// The `diagnostic` field is not `Copy` and can't be moved out of whichever -/// type implements the `Drop` "bomb", but because of the above two facts, that -/// never needs to happen - instead, the whole `inner: DiagnosticBuilderInner` -/// can be moved out of a `DiagnosticBuilder` and into another. -#[must_use] -#[derive(Clone)] -struct DiagnosticBuilderInner<'a> { +pub struct DiagnosticBuilder<'a, G: EmissionGuarantee = ErrorGuaranteed> { state: DiagnosticBuilderState<'a>, /// `Diagnostic` is a large type, and `DiagnosticBuilder` is often used as a @@ -68,6 +51,8 @@ struct DiagnosticBuilderInner<'a> { /// In theory, return value optimization (RVO) should avoid unnecessary /// copying. In practice, it does not (at the time of writing). diagnostic: Box<Diagnostic>, + + _marker: PhantomData<G>, } #[derive(Clone)] @@ -83,7 +68,7 @@ enum DiagnosticBuilderState<'a> { /// assumed that `.emit()` was previously called, to end up in this state. /// /// While this is also used by `.cancel()`, this state is only observed by - /// the `Drop` `impl` of `DiagnosticBuilderInner`, as `.cancel()` takes + /// the `Drop` `impl` of `DiagnosticBuilder`, because `.cancel()` takes /// `self` by-value specifically to prevent any attempts to `.emit()`. /// // FIXME(eddyb) currently this doesn't prevent extending the `Diagnostic`, @@ -115,12 +100,11 @@ pub trait EmissionGuarantee: Sized { impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Most `emit_producing_guarantee` functions use this as a starting point. fn emit_producing_nothing(&mut self) { - match self.inner.state { + match self.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { - self.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - - dcx.emit_diagnostic_without_consuming(&mut self.inner.diagnostic); + self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + dcx.emit_diagnostic_without_consuming(&mut self.diagnostic); } // `.emit()` was previously called, disallowed from repeating it. DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} @@ -128,34 +112,24 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { } } -impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { - /// Discard the guarantee `.emit()` would return, in favor of having the - /// type `DiagnosticBuilder<'a, ()>`. This may be necessary whenever there - /// is a common codepath handling both errors and warnings. - pub fn forget_guarantee(self) -> DiagnosticBuilder<'a, ()> { - DiagnosticBuilder { inner: self.inner, _marker: PhantomData } - } -} - // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. impl EmissionGuarantee for ErrorGuaranteed { fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { // Contrast this with `emit_producing_nothing`. - match db.inner.state { + match db.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - - let guar = dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); + db.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + let guar = dcx.emit_diagnostic_without_consuming(&mut db.diagnostic); // Only allow a guarantee if the `level` wasn't switched to a // non-error - the field isn't `pub`, but the whole `Diagnostic` // can be overwritten with a new one, thanks to `DerefMut`. assert!( - db.inner.diagnostic.is_error(), + db.diagnostic.is_error(), "emitted non-error ({:?}) diagnostic \ from `DiagnosticBuilder<ErrorGuaranteed>`", - db.inner.diagnostic.level, + db.diagnostic.level, ); guar.unwrap() } @@ -167,10 +141,10 @@ impl EmissionGuarantee for ErrorGuaranteed { // non-error - the field isn't `pub`, but the whole `Diagnostic` // can be overwritten with a new one, thanks to `DerefMut`. assert!( - db.inner.diagnostic.is_error(), + db.diagnostic.is_error(), "`DiagnosticBuilder<ErrorGuaranteed>`'s diagnostic \ became non-error ({:?}), after original `.emit()`", - db.inner.diagnostic.level, + db.diagnostic.level, ); #[allow(deprecated)] ErrorGuaranteed::unchecked_claim_error_was_emitted() @@ -238,7 +212,7 @@ macro_rules! forward { $(#[$attrs])* #[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")] pub fn $n(&mut self, $($name: $ty),*) -> &mut Self { - self.inner.diagnostic.$n($($name),*); + self.diagnostic.$n($($name),*); self } }; @@ -248,13 +222,13 @@ impl<G: EmissionGuarantee> Deref for DiagnosticBuilder<'_, G> { type Target = Diagnostic; fn deref(&self) -> &Diagnostic { - &self.inner.diagnostic + &self.diagnostic } } impl<G: EmissionGuarantee> DerefMut for DiagnosticBuilder<'_, G> { fn deref_mut(&mut self) -> &mut Diagnostic { - &mut self.inner.diagnostic + &mut self.diagnostic } } @@ -271,10 +245,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { pub(crate) fn new_diagnostic(dcx: &'a DiagCtxt, diagnostic: Diagnostic) -> Self { debug!("Created new diagnostic"); Self { - inner: DiagnosticBuilderInner { - state: DiagnosticBuilderState::Emittable(dcx), - diagnostic: Box::new(diagnostic), - }, + state: DiagnosticBuilderState::Emittable(dcx), + diagnostic: Box::new(diagnostic), _marker: PhantomData, } } @@ -306,7 +278,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// which may be expected to *guarantee* the emission of an error, either /// at the time of the call, or through a prior `.emit()` call. pub fn cancel(mut self) { - self.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; drop(self); } @@ -324,7 +296,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Converts the builder to a `Diagnostic` for later emission, /// unless dcx has disabled such buffering, or `.emit()` was called. pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> { - let dcx = match self.inner.state { + let dcx = match self.state { // No `.emit()` calls, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => dcx, // `.emit()` was previously called, nothing we can do. @@ -342,7 +314,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { // Take the `Diagnostic` by replacing it with a dummy. let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::from("")); - let diagnostic = std::mem::replace(&mut *self.inner.diagnostic, dummy); + let diagnostic = std::mem::replace(&mut *self.diagnostic, dummy); // Disable the ICE on `Drop`. self.cancel(); @@ -356,7 +328,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Retrieves the [`DiagCtxt`] if available pub fn dcx(&self) -> Option<&DiagCtxt> { - match self.inner.state { + match self.state { DiagnosticBuilderState::Emittable(dcx) => Some(dcx), DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => None, } @@ -544,13 +516,13 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { impl<G: EmissionGuarantee> Debug for DiagnosticBuilder<'_, G> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.inner.diagnostic.fmt(f) + self.diagnostic.fmt(f) } } /// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled /// or we emit a bug. -impl Drop for DiagnosticBuilderInner<'_> { +impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> { fn drop(&mut self) { match self.state { // No `.emit()` or `.cancel()` calls. diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index ccc951543d8..29cb304e8b5 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -312,25 +312,13 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> pub struct SingleLabelManySpans { pub spans: Vec<Span>, pub label: &'static str, - pub kind: LabelKind, } impl AddToDiagnostic for SingleLabelManySpans { fn add_to_diagnostic_with<F>(self, diag: &mut crate::Diagnostic, _: F) { - match self.kind { - LabelKind::Note => diag.span_note(self.spans, self.label), - LabelKind::Label => diag.span_labels(self.spans, self.label), - LabelKind::Help => diag.span_help(self.spans, self.label), - }; + diag.span_labels(self.spans, self.label); } } -/// The kind of label to attach when using [`SingleLabelManySpans`] -pub enum LabelKind { - Note, - Label, - Help, -} - #[derive(Subdiagnostic)] #[label(errors_expected_lifetime_parameter)] pub struct ExpectedLifetimeParameter { diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 3fb993c3651..546159c9d13 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -350,9 +350,8 @@ pub trait Emitter: Translate { children.push(SubDiagnostic { level: Level::Note, - message: vec![(DiagnosticMessage::from(msg), Style::NoStyle)], + messages: vec![(DiagnosticMessage::from(msg), Style::NoStyle)], span: MultiSpan::new(), - render_span: None, }); } } @@ -533,7 +532,7 @@ impl Emitter for EmitterWriter { self.emit_messages_default( &diag.level, - &diag.message, + &diag.messages, &fluent_args, &diag.code, &primary_span, @@ -1228,10 +1227,10 @@ impl EmitterWriter { /// Adds a left margin to every line but the first, given a padding length and the label being /// displayed, keeping the provided highlighting. - fn msg_to_buffer( + fn msgs_to_buffer( &self, buffer: &mut StyledBuffer, - msg: &[(DiagnosticMessage, Style)], + msgs: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, padding: usize, label: &str, @@ -1267,7 +1266,7 @@ impl EmitterWriter { // Provided the following diagnostic message: // - // let msg = vec![ + // let msgs = vec![ // (" // ("highlighted multiline\nstring to\nsee how it ", Style::NoStyle), // ("looks", Style::Highlight), @@ -1284,7 +1283,7 @@ impl EmitterWriter { // see how it *looks* with // very *weird* formats // see? - for (text, style) in msg.iter() { + for (text, style) in msgs.iter() { let text = self.translate_message(text, args).map_err(Report::new).unwrap(); let text = &normalize_whitespace(&text); let lines = text.split('\n').collect::<Vec<_>>(); @@ -1303,10 +1302,10 @@ impl EmitterWriter { } #[instrument(level = "trace", skip(self, args), ret)] - fn emit_message_default( + fn emit_messages_default_inner( &mut self, msp: &MultiSpan, - msg: &[(DiagnosticMessage, Style)], + msgs: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, code: &Option<DiagnosticId>, level: &Level, @@ -1327,7 +1326,7 @@ impl EmitterWriter { buffer.append(0, level.to_str(), Style::MainHeaderMsg); buffer.append(0, ": ", Style::NoStyle); } - self.msg_to_buffer(&mut buffer, msg, args, max_line_num_len, "note", None); + self.msgs_to_buffer(&mut buffer, msgs, args, max_line_num_len, "note", None); } else { let mut label_width = 0; // The failure note level itself does not provide any useful diagnostic information @@ -1360,7 +1359,7 @@ impl EmitterWriter { buffer.append(0, ": ", header_style); label_width += 2; } - for (text, _) in msg.iter() { + for (text, _) in msgs.iter() { let text = self.translate_message(text, args).map_err(Report::new).unwrap(); // Account for newlines to align output to its label. for (line, text) in normalize_whitespace(&text).lines().enumerate() { @@ -1747,7 +1746,7 @@ impl EmitterWriter { buffer.append(0, level.to_str(), Style::Level(*level)); buffer.append(0, ": ", Style::HeaderMsg); - self.msg_to_buffer( + self.msgs_to_buffer( &mut buffer, &[(suggestion.msg.to_owned(), Style::NoStyle)], args, @@ -2074,7 +2073,7 @@ impl EmitterWriter { fn emit_messages_default( &mut self, level: &Level, - message: &[(DiagnosticMessage, Style)], + messages: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, code: &Option<DiagnosticId>, span: &MultiSpan, @@ -2089,9 +2088,9 @@ impl EmitterWriter { num_decimal_digits(n) }; - match self.emit_message_default( + match self.emit_messages_default_inner( span, - message, + messages, args, code, level, @@ -2118,10 +2117,10 @@ impl EmitterWriter { } if !self.short_message { for child in children { - let span = child.render_span.as_ref().unwrap_or(&child.span); - if let Err(err) = self.emit_message_default( + let span = &child.span; + if let Err(err) = self.emit_messages_default_inner( span, - &child.message, + &child.messages, args, &None, &child.level, @@ -2138,7 +2137,7 @@ impl EmitterWriter { // do not display this suggestion, it is meant only for tools } SuggestionStyle::HideCodeAlways => { - if let Err(e) = self.emit_message_default( + if let Err(e) = self.emit_messages_default_inner( &MultiSpan::new(), &[(sugg.msg.to_owned(), Style::HeaderMsg)], args, diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index aa3749334d9..52fcb50e9fb 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -398,7 +398,7 @@ impl Diagnostic { let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); let output = String::from_utf8(output).unwrap(); - let translated_message = je.translate_messages(&diag.message, &args); + let translated_message = je.translate_messages(&diag.messages, &args); Diagnostic { message: translated_message.to_string(), code: DiagnosticCode::map_opt_string(diag.code.clone(), je), @@ -419,16 +419,12 @@ impl Diagnostic { args: &FluentArgs<'_>, je: &JsonEmitter, ) -> Diagnostic { - let translated_message = je.translate_messages(&diag.message, args); + let translated_message = je.translate_messages(&diag.messages, args); Diagnostic { message: translated_message.to_string(), code: None, level: diag.level.to_str(), - spans: diag - .render_span - .as_ref() - .map(|sp| DiagnosticSpan::from_multispan(sp, args, je)) - .unwrap_or_else(|| DiagnosticSpan::from_multispan(&diag.span, args, je)), + spans: DiagnosticSpan::from_multispan(&diag.span, args, je), children: vec![], rendered: None, } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 518a2ddb71d..7a1faac04d3 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -27,26 +27,42 @@ extern crate tracing; extern crate self as rustc_errors; +pub use diagnostic::{ + AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, + DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, +}; +pub use diagnostic_builder::{ + BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort, IntoDiagnostic, +}; +pub use diagnostic_impls::{ + DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter, + IndicateAnonymousLifetime, InvalidFlushedDelayedDiagnosticLevel, SingleLabelManySpans, +}; pub use emitter::ColorConfig; +pub use rustc_error_messages::{ + fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle, + LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage, +}; +pub use rustc_lint_defs::{pluralize, Applicability}; +pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; +pub use rustc_span::ErrorGuaranteed; +pub use snippet::Style; -use rustc_lint_defs::LintExpectationId; -use Level::*; +// Used by external projects such as `rust-gpu`. +// See https://github.com/rust-lang/rust/pull/115393. +pub use termcolor::{Color, ColorSpec, WriteColor}; +use crate::diagnostic_impls::{DelayedAtWithNewline, DelayedAtWithoutNewline}; use emitter::{is_case_difference, DynEmitter, Emitter, EmitterWriter}; use registry::Registry; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; use rustc_data_structures::sync::{Lock, Lrc}; use rustc_data_structures::AtomicRef; -pub use rustc_error_messages::{ - fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle, - LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage, -}; -pub use rustc_lint_defs::{pluralize, Applicability}; +use rustc_lint_defs::LintExpectationId; use rustc_span::source_map::SourceMap; -pub use rustc_span::ErrorGuaranteed; use rustc_span::{Loc, Span, DUMMY_SP}; - +use std::backtrace::{Backtrace, BacktraceStatus}; use std::borrow::Cow; use std::error::Report; use std::fmt; @@ -56,9 +72,7 @@ use std::num::NonZeroUsize; use std::panic; use std::path::{Path, PathBuf}; -// Used by external projects such as `rust-gpu`. -// See https://github.com/rust-lang/rust/pull/115393. -pub use termcolor::{Color, ColorSpec, WriteColor}; +use Level::*; pub mod annotate_snippet_emitter_writer; mod diagnostic; @@ -76,10 +90,7 @@ mod styled_buffer; mod tests; pub mod translation; -pub use diagnostic_builder::IntoDiagnostic; -pub use snippet::Style; - -pub type PErr<'a> = DiagnosticBuilder<'a, ErrorGuaranteed>; +pub type PErr<'a> = DiagnosticBuilder<'a>; pub type PResult<'a, T> = Result<T, PErr<'a>>; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } @@ -163,7 +174,7 @@ pub struct SubstitutionPart { /// Used to translate between `Span`s and byte positions within a single output line in highlighted /// code of structured suggestions. #[derive(Debug, Clone, Copy)] -pub struct SubstitutionHighlight { +pub(crate) struct SubstitutionHighlight { start: usize, end: usize, } @@ -190,7 +201,7 @@ impl SubstitutionPart { impl CodeSuggestion { /// Returns the assembled code suggestions, whether they should be shown with an underline /// and whether the substitution only differs in capitalization. - pub fn splice_lines( + pub(crate) fn splice_lines( &self, sm: &SourceMap, ) -> Vec<(String, Vec<SubstitutionPart>, Vec<Vec<SubstitutionHighlight>>, bool)> { @@ -387,8 +398,6 @@ impl CodeSuggestion { } } -pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; - /// Signifies that the compiler died with an explicit call to `.bug` /// or `.span_bug` rather than a failed assertion, etc. pub struct ExplicitBug; @@ -397,20 +406,7 @@ pub struct ExplicitBug; /// rather than a failed assertion, etc. pub struct DelayedBugPanic; -use crate::diagnostic_impls::{DelayedAtWithNewline, DelayedAtWithoutNewline}; -pub use diagnostic::{ - AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, - DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, -}; -pub use diagnostic_builder::{BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort}; -pub use diagnostic_impls::{ - DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter, - IndicateAnonymousLifetime, InvalidFlushedDelayedDiagnosticLevel, LabelKind, - SingleLabelManySpans, -}; -use std::backtrace::{Backtrace, BacktraceStatus}; - -/// A handler deals with errors and other compiler output. +/// A `DiagCtxt` deals with errors and other compiler output. /// Certain errors (fatal, bug, unimpl) may cause immediate exit, /// others log errors for later reporting. pub struct DiagCtxt { @@ -447,7 +443,7 @@ struct DiagCtxtInner { emitted_diagnostic_codes: FxIndexSet<DiagnosticId>, /// This set contains a hash of every diagnostic that has been emitted by - /// this handler. These hashes is used to avoid emitting the same error + /// this `DiagCtxt`. These hashes is used to avoid emitting the same error /// twice. emitted_diagnostics: FxHashSet<Hash128>, @@ -677,7 +673,7 @@ impl DiagCtxt { let key = (span.with_parent(None), key); if diag.is_error() { - if matches!(diag.level, Level::Error { lint: true }) { + if matches!(diag.level, Error { lint: true }) { inner.lint_err_count += 1; } else { inner.err_count += 1; @@ -701,7 +697,7 @@ impl DiagCtxt { let key = (span.with_parent(None), key); let diag = inner.stashed_diagnostics.remove(&key)?; if diag.is_error() { - if matches!(diag.level, Level::Error { lint: true }) { + if matches!(diag.level, Error { lint: true }) { inner.lint_err_count -= 1; } else { inner.err_count -= 1; @@ -741,37 +737,6 @@ impl DiagCtxt { } /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. - /// The `id` is used for lint emissions which should also fulfill a lint expectation. - /// - /// Attempting to `.emit()` the builder will only emit if either: - /// * `can_emit_warnings` is `true` - /// * `is_force_warn` was set in `DiagnosticId::Lint` - #[track_caller] - pub fn struct_span_warn_with_expectation( - &self, - span: impl Into<MultiSpan>, - msg: impl Into<DiagnosticMessage>, - id: LintExpectationId, - ) -> DiagnosticBuilder<'_, ()> { - let mut result = self.struct_warn_with_expectation(msg, id); - result.set_span(span); - result - } - - /// Construct a builder at the `Allow` level at the given `span` and with the `msg`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_span_allow( - &self, - span: impl Into<MultiSpan>, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, ()> { - let mut result = self.struct_allow(msg); - result.set_span(span); - result - } - - /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. /// Also include a code. #[rustc_lint_diagnostics] #[track_caller] @@ -794,29 +759,14 @@ impl DiagCtxt { #[rustc_lint_diagnostics] #[track_caller] pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Warning(None), msg) - } - - /// Construct a builder at the `Warning` level with the `msg`. The `id` is used for - /// lint emissions which should also fulfill a lint expectation. - /// - /// Attempting to `.emit()` the builder will only emit if either: - /// * `can_emit_warnings` is `true` - /// * `is_force_warn` was set in `DiagnosticId::Lint` - #[track_caller] - pub fn struct_warn_with_expectation( - &self, - msg: impl Into<DiagnosticMessage>, - id: LintExpectationId, - ) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Warning(Some(id)), msg) + DiagnosticBuilder::new(self, Warning(None), msg) } /// Construct a builder at the `Allow` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Allow, msg) + DiagnosticBuilder::new(self, Allow, msg) } /// Construct a builder at the `Expect` level with the `msg`. @@ -827,7 +777,7 @@ impl DiagCtxt { msg: impl Into<DiagnosticMessage>, id: LintExpectationId, ) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Expect(id), msg) + DiagnosticBuilder::new(self, Expect(id), msg) } /// Construct a builder at the `Error` level at the given `span` and with the `msg`. @@ -837,7 +787,7 @@ impl DiagCtxt { &self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { let mut result = self.struct_err(msg); result.set_span(span); result @@ -851,7 +801,7 @@ impl DiagCtxt { span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { let mut result = self.struct_span_err(span, msg); result.code(code); result @@ -861,18 +811,8 @@ impl DiagCtxt { // 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<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - DiagnosticBuilder::new(self, Level::Error { lint: false }, msg) - } - - /// This should only be used by `rustc_middle::lint::struct_lint_level`. Do not use it for hard errors. - #[doc(hidden)] - #[track_caller] - pub fn struct_err_lint(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Error { lint: true }, msg) + pub fn struct_err(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_> { + DiagnosticBuilder::new(self, Error { lint: false }, msg) } /// Construct a builder at the `Error` level with the `msg` and the `code`. @@ -882,7 +822,7 @@ impl DiagCtxt { &self, msg: impl Into<DiagnosticMessage>, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { let mut result = self.struct_err(msg); result.code(code); result @@ -935,7 +875,7 @@ impl DiagCtxt { &self, msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, FatalAbort> { - DiagnosticBuilder::new(self, Level::Fatal, msg) + DiagnosticBuilder::new(self, Fatal, msg) } /// Construct a builder at the `Fatal` level with the `msg`, that doesn't abort. @@ -945,27 +885,27 @@ impl DiagCtxt { &self, msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, FatalError> { - DiagnosticBuilder::new(self, Level::Fatal, msg) + DiagnosticBuilder::new(self, Fatal, msg) } /// Construct a builder at the `Help` level with the `msg`. #[rustc_lint_diagnostics] pub fn struct_help(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Help, msg) + DiagnosticBuilder::new(self, Help, msg) } /// Construct a builder at the `Note` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_note(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { - DiagnosticBuilder::new(self, Level::Note, msg) + DiagnosticBuilder::new(self, Note, msg) } /// Construct a builder at the `Bug` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_bug(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, BugAbort> { - DiagnosticBuilder::new(self, Level::Bug, msg) + DiagnosticBuilder::new(self, Bug, msg) } /// Construct a builder at the `Bug` level at the given `span` with the `msg`. @@ -1037,7 +977,7 @@ impl DiagCtxt { } pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! { - self.inner.borrow_mut().span_bug(span, msg) + self.struct_span_bug(span, msg).emit() } /// For documentation on this, see `Session::span_delayed_bug`. @@ -1050,20 +990,14 @@ impl DiagCtxt { sp: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, ) -> ErrorGuaranteed { - let mut inner = self.inner.borrow_mut(); - - // This is technically `self.treat_err_as_bug()` but `span_delayed_bug` is called before - // incrementing `err_count` by one, so we need to +1 the comparing. - // FIXME: Would be nice to increment err_count in a more coherent way. - if inner.flags.treat_err_as_bug.is_some_and(|c| { - inner.err_count + inner.lint_err_count + inner.delayed_bug_count() + 1 >= c.get() - }) { + let treat_next_err_as_bug = self.inner.borrow().treat_next_err_as_bug(); + if treat_next_err_as_bug { // FIXME: don't abort here if report_delayed_bugs is off - inner.span_bug(sp, msg); + self.span_bug(sp, msg); } - let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg); + let mut diagnostic = Diagnostic::new(DelayedBug, msg); diagnostic.set_span(sp); - inner.emit_diagnostic(diagnostic).unwrap() + self.emit_diagnostic(diagnostic).unwrap() } // FIXME(eddyb) note the comment inside `impl Drop for DiagCtxtInner`, that's @@ -1071,7 +1005,7 @@ impl DiagCtxt { pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) { let mut inner = self.inner.borrow_mut(); - let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg); + let mut diagnostic = Diagnostic::new(DelayedBug, msg); if inner.flags.report_delayed_bugs { inner.emit_diagnostic_without_consuming(&mut diagnostic); } @@ -1184,10 +1118,9 @@ impl DiagCtxt { match (errors.len(), warnings.len()) { (0, 0) => return, - (0, _) => inner.emitter.emit_diagnostic(&Diagnostic::new( - Level::Warning(None), - DiagnosticMessage::Str(warnings), - )), + (0, _) => inner + .emitter + .emit_diagnostic(&Diagnostic::new(Warning(None), DiagnosticMessage::Str(warnings))), (_, 0) => { inner.emit_diagnostic(Diagnostic::new(Fatal, errors)); } @@ -1219,14 +1152,12 @@ impl DiagCtxt { if error_codes.len() > 9 { "..." } else { "." } )); inner.failure_note(format!( - "For more information about an error, try \ - `rustc --explain {}`.", + "For more information about an error, try `rustc --explain {}`.", &error_codes[0] )); } else { inner.failure_note(format!( - "For more information about this error, try \ - `rustc --explain {}`.", + "For more information about this error, try `rustc --explain {}`.", &error_codes[0] )); } @@ -1277,18 +1208,15 @@ impl DiagCtxt { } #[track_caller] - pub fn create_err<'a>( - &'a self, - err: impl IntoDiagnostic<'a>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - err.into_diagnostic(self, Level::Error { lint: false }) + pub fn create_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> DiagnosticBuilder<'a> { + err.into_diagnostic(self, Error { lint: false }) } pub fn create_warning<'a>( &'a self, warning: impl IntoDiagnostic<'a, ()>, ) -> DiagnosticBuilder<'a, ()> { - warning.into_diagnostic(self, Level::Warning(None)) + warning.into_diagnostic(self, Warning(None)) } pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) { @@ -1299,7 +1227,7 @@ impl DiagCtxt { &'a self, fatal: impl IntoDiagnostic<'a, FatalError>, ) -> DiagnosticBuilder<'a, FatalError> { - fatal.into_diagnostic(self, Level::Fatal) + fatal.into_diagnostic(self, Fatal) } pub fn emit_almost_fatal<'a>( @@ -1313,7 +1241,7 @@ impl DiagCtxt { &'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>, ) -> DiagnosticBuilder<'a, FatalAbort> { - fatal.into_diagnostic(self, Level::Fatal) + fatal.into_diagnostic(self, Fatal) } pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! { @@ -1324,7 +1252,7 @@ impl DiagCtxt { &'a self, bug: impl IntoDiagnostic<'a, BugAbort>, ) -> DiagnosticBuilder<'a, BugAbort> { - bug.into_diagnostic(self, Level::Bug) + bug.into_diagnostic(self, Bug) } pub fn emit_bug<'a>(&'a self, bug: impl IntoDiagnostic<'a, BugAbort>) -> ! { @@ -1339,7 +1267,7 @@ impl DiagCtxt { &'a self, note: impl IntoDiagnostic<'a, ()>, ) -> DiagnosticBuilder<'a, ()> { - note.into_diagnostic(self, Level::Note) + note.into_diagnostic(self, Note) } pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { @@ -1426,7 +1354,7 @@ impl DiagCtxtInner { for diag in diags { // Decrement the count tracking the stash; emitting will increment it. if diag.is_error() { - if matches!(diag.level, Level::Error { lint: true }) { + if matches!(diag.level, Error { lint: true }) { self.lint_err_count -= 1; } else { self.err_count -= 1; @@ -1457,9 +1385,8 @@ impl DiagCtxtInner { &mut self, diagnostic: &mut Diagnostic, ) -> Option<ErrorGuaranteed> { - if matches!(diagnostic.level, Level::Error { .. } | Level::Fatal) && self.treat_err_as_bug() - { - diagnostic.level = Level::Bug; + if matches!(diagnostic.level, Error { .. } | Fatal) && self.treat_err_as_bug() { + diagnostic.level = Bug; } // The `LintExpectationId` can be stable or unstable depending on when it was created. @@ -1471,7 +1398,7 @@ impl DiagCtxtInner { return None; } - if diagnostic.level == Level::DelayedBug { + if diagnostic.level == DelayedBug { // FIXME(eddyb) this should check for `has_errors` and stop pushing // once *any* errors were emitted (and truncate `span_delayed_bugs` // when an error is first emitted, also), but maybe there's a case @@ -1487,7 +1414,7 @@ impl DiagCtxtInner { } if diagnostic.has_future_breakage() { - // Future breakages aren't emitted if they're Level::Allowed, + // Future breakages aren't emitted if they're Level::Allow, // but they still need to be constructed and stashed below, // so they'll trigger the good-path bug check. self.suppressed_expected_diag = true; @@ -1509,7 +1436,7 @@ impl DiagCtxtInner { return None; } - if matches!(diagnostic.level, Level::Expect(_) | Level::Allow) { + if matches!(diagnostic.level, Expect(_) | Allow) { (*TRACK_DIAGNOSTICS)(diagnostic, &mut |_| {}); return None; } @@ -1534,7 +1461,7 @@ impl DiagCtxtInner { debug!(?self.emitted_diagnostics); let already_emitted_sub = |sub: &mut SubDiagnostic| { debug!(?sub); - if sub.level != Level::OnceNote && sub.level != Level::OnceHelp { + if sub.level != OnceNote && sub.level != OnceHelp { return false; } let mut hasher = StableHasher::new(); @@ -1559,7 +1486,7 @@ impl DiagCtxtInner { } } if diagnostic.is_error() { - if matches!(diagnostic.level, Level::Error { lint: true }) { + if matches!(diagnostic.level, Error { lint: true }) { self.bump_lint_err_count(); } else { self.bump_err_count(); @@ -1583,6 +1510,13 @@ impl DiagCtxtInner { }) } + // Use this one before incrementing `err_count`. + fn treat_next_err_as_bug(&self) -> bool { + self.flags.treat_err_as_bug.is_some_and(|c| { + self.err_count + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get() + }) + } + fn delayed_bug_count(&self) -> usize { self.span_delayed_bugs.len() + self.good_path_delayed_bugs.len() } @@ -1591,27 +1525,22 @@ impl DiagCtxtInner { self.err_count > 0 } - #[track_caller] - fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! { - let mut diag = Diagnostic::new(Bug, msg); - diag.set_span(sp); - self.emit_diagnostic(diag); - panic::panic_any(ExplicitBug); - } - fn failure_note(&mut self, msg: impl Into<DiagnosticMessage>) { self.emit_diagnostic(Diagnostic::new(FailureNote, msg)); } fn flush_delayed( &mut self, - bugs: impl IntoIterator<Item = DelayedDiagnostic>, + bugs: Vec<DelayedDiagnostic>, explanation: impl Into<DiagnosticMessage> + Copy, ) { - let mut no_bugs = true; + if bugs.is_empty() { + return; + } + // If backtraces are enabled, also print the query stack let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0"); - for bug in bugs { + for (i, bug) in bugs.into_iter().enumerate() { if let Some(file) = self.ice_file.as_ref() && let Ok(mut out) = std::fs::File::options().create(true).append(true).open(file) { @@ -1619,25 +1548,25 @@ impl DiagCtxtInner { &mut out, "delayed span bug: {}\n{}\n", bug.inner - .styled_message() + .messages() .iter() .filter_map(|(msg, _)| msg.as_str()) .collect::<String>(), &bug.note ); } - let mut bug = - if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner }; - if no_bugs { + if i == 0 { // Put the overall explanation before the `DelayedBug`s, to // frame them better (e.g. separate warnings from them). self.emit_diagnostic(Diagnostic::new(Bug, explanation)); - no_bugs = false; } + let mut bug = + if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner }; + // "Undelay" the `DelayedBug`s (into plain `Bug`s). - if bug.level != Level::DelayedBug { + if bug.level != DelayedBug { // NOTE(eddyb) not panicking here because we're already producing // an ICE, and the more information the merrier. bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel { @@ -1645,15 +1574,13 @@ impl DiagCtxtInner { level: bug.level, }); } - bug.level = Level::Bug; + bug.level = Bug; self.emit_diagnostic(bug); } // Panic with `DelayedBugPanic` to avoid "unexpected panic" messages. - if !no_bugs { - panic::panic_any(DelayedBugPanic); - } + panic::panic_any(DelayedBugPanic); } fn bump_lint_err_count(&mut self) { @@ -1731,25 +1658,80 @@ impl DelayedDiagnostic { #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] pub enum Level { + /// For bugs in the compiler. Manifests as an ICE (internal compiler error) panic. + /// + /// Its `EmissionGuarantee` is `BugAbort`. Bug, + + /// This is a strange one: lets you register an error without emitting it. If compilation ends + /// without any other errors occurring, this will be emitted as a bug. Otherwise, it will be + /// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths + /// that should only be reached when compiling erroneous code. + /// + /// Its `EmissionGuarantee` is `ErrorGuaranteed`. DelayedBug, + + /// An error that causes an immediate abort. Used for things like configuration errors, + /// internal overflows, some file operation errors. + /// + /// Its `EmissionGuarantee` is `FatalAbort`, except in the non-aborting "almost fatal" case + /// that is occasionaly used, where it is `FatalError`. Fatal, + + /// An error in the code being compiled, which prevents compilation from finishing. This is the + /// most common case. + /// + /// Its `EmissionGuarantee` is `ErrorGuaranteed`. Error { - /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is called. + /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is + /// called. lint: bool, }, + + /// A warning about the code being compiled. Does not prevent compilation from finishing. + /// /// This [`LintExpectationId`] is used for expected lint diagnostics, which should /// also emit a warning due to the `force-warn` flag. In all other cases this should /// be `None`. + /// + /// Its `EmissionGuarantee` is `()`. Warning(Option<LintExpectationId>), + + /// A message giving additional context. Rare, because notes are more commonly attached to other + /// diagnostics such as errors. + /// + /// Its `EmissionGuarantee` is `()`. Note, - /// A note that is only emitted once. + + /// A note that is only emitted once. Rare, mostly used in circumstances relating to lints. + /// + /// Its `EmissionGuarantee` is `()`. OnceNote, + + /// A message suggesting how to fix something. Rare, because help messages are more commonly + /// attached to other diagnostics such as errors. + /// + /// Its `EmissionGuarantee` is `()`. Help, - /// A help that is only emitted once. + + /// A help that is only emitted once. Rare. + /// + /// Its `EmissionGuarantee` is `()`. OnceHelp, + + /// Similar to `Note`, but used in cases where compilation has failed. Rare. + /// + /// Its `EmissionGuarantee` is `()`. FailureNote, + + /// Only used for lints. + /// + /// Its `EmissionGuarantee` is `()`. Allow, + + /// Only used for lints. + /// + /// Its `EmissionGuarantee` is `()`. Expect(LintExpectationId), } @@ -1789,8 +1771,7 @@ impl Level { Note | OnceNote => "note", Help | OnceHelp => "help", FailureNote => "failure-note", - Allow => panic!("Shouldn't call on allowed error"), - Expect(_) => panic!("Shouldn't call on expected error"), + Allow | Expect(_) => unreachable!(), } } @@ -1800,7 +1781,7 @@ impl Level { pub fn get_expectation_id(&self) -> Option<LintExpectationId> { match self { - Level::Expect(id) | Level::Warning(Some(id)) => Some(*id), + Expect(id) | Warning(Some(id)) => Some(*id), _ => None, } } |
