diff options
| author | The Miri Conjob Bot <miri@cron.bot> | 2024-01-13 05:03:10 +0000 |
|---|---|---|
| committer | The Miri Conjob Bot <miri@cron.bot> | 2024-01-13 05:03:10 +0000 |
| commit | 9b46f3bb6499c263c9c81e7cea4815396bbbce14 (patch) | |
| tree | ab6ca2c31a68888b7c34f3b091e899054f3a56aa /compiler/rustc_errors/src | |
| parent | 86190488cd05ffd48394d9d1c464d7f50ee19614 (diff) | |
| parent | f1f8687b06a5908dd096f51da32347b3313279db (diff) | |
| download | rust-9b46f3bb6499c263c9c81e7cea4815396bbbce14.tar.gz rust-9b46f3bb6499c263c9c81e7cea4815396bbbce14.zip | |
Merge from rustc
Diffstat (limited to 'compiler/rustc_errors/src')
| -rw-r--r-- | compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic_builder.rs | 30 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/lib.rs | 122 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/markdown/tests/term.rs | 5 |
5 files changed, 89 insertions, 96 deletions
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 97f2efa7874..648c9118400 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -12,8 +12,7 @@ use crate::{ CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic, }; -use annotate_snippets::display_list::{DisplayList, FormatOptions}; -use annotate_snippets::snippet::*; +use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; use rustc_data_structures::sync::Lrc; use rustc_error_messages::FluentArgs; use rustc_span::source_map::SourceMap; @@ -86,7 +85,7 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String { /// Maps `Diagnostic::Level` to `snippet::AnnotationType` fn annotation_type_for_level(level: Level) -> AnnotationType { match level { - Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error => AnnotationType::Error, + Level::Bug | Level::DelayedBug(_) | Level::Fatal | Level::Error => AnnotationType::Error, Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning, Level::Note | Level::OnceNote => AnnotationType::Note, Level::Help | Level::OnceHelp => AnnotationType::Help, @@ -190,11 +189,6 @@ impl AnnotateSnippetEmitter { annotation_type: annotation_type_for_level(*level), }), footer: vec![], - opt: FormatOptions { - color: true, - anonymized_line_numbers: self.ui_testing, - margin: None, - }, slices: annotated_files .iter() .map(|(file_name, source, line_index, annotations)| { @@ -222,7 +216,8 @@ impl AnnotateSnippetEmitter { // FIXME(#59346): Figure out if we can _always_ print to stderr or not. // `emitter.rs` has the `Destination` enum that lists various possible output // destinations. - eprintln!("{}", DisplayList::from(snippet)) + let renderer = Renderer::plain().anonymized_line_numbers(self.ui_testing); + eprintln!("{}", renderer.render(snippet)) } // FIXME(#59346): Is it ok to return None if there's no source_map? } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index d8d6922a1bc..786aced5b4f 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,7 +1,7 @@ use crate::snippet::Style; use crate::{ - CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level, MultiSpan, - SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle, + CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level, + MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle, }; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_error_messages::fluent_value_from_str_list_sep_by_and; @@ -243,12 +243,15 @@ impl Diagnostic { pub fn is_error(&self) -> bool { match self.level { - Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error | Level::FailureNote => { - true - } + Level::Bug + | Level::DelayedBug(DelayedBugKind::Normal) + | Level::Fatal + | Level::Error + | Level::FailureNote => true, Level::ForceWarning(_) | Level::Warning + | Level::DelayedBug(DelayedBugKind::GoodPath) | Level::Note | Level::OnceNote | Level::Help @@ -318,7 +321,7 @@ impl Diagnostic { "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error", self.level ); - self.level = Level::DelayedBug; + self.level = Level::DelayedBug(DelayedBugKind::Normal); } /// Appends a labeled span to the diagnostic. diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index a02909f29c4..bd7c58d904e 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -255,35 +255,13 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Stashes diagnostic for possible later improvement in a different, /// later stage of the compiler. The diagnostic can be accessed with /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`]. - /// - /// As with `buffer`, this is unless the dcx has disabled such buffering. pub fn stash(self, span: Span, key: StashKey) { - if let Some((diag, dcx)) = self.into_diagnostic() { - dcx.stash_diagnostic(span, key, diag); - } - } - - /// Converts the builder to a `Diagnostic` for later emission, - /// unless dcx has disabled such buffering. - fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> { - if self.dcx.inner.lock().flags.treat_err_as_bug.is_some() { - self.emit(); - return None; - } - - let diag = self.take_diag(); - - // Logging here is useful to help track down where in logs an error was - // actually emitted. - debug!("buffer: diag={:?}", diag); - - Some((diag, self.dcx)) + self.dcx.stash_diagnostic(span, key, self.into_diagnostic()); } - /// Buffers the diagnostic for later emission, - /// unless dcx has disabled such buffering. - pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) { - buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag)); + /// Converts the builder to a `Diagnostic` for later emission. + pub fn into_diagnostic(mut self) -> Diagnostic { + self.take_diag() } /// Delay emission of this diagnostic as a bug. diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 8fb539fc358..8c2752af659 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -519,6 +519,12 @@ fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) { pub static TRACK_DIAGNOSTIC: AtomicRef<fn(Diagnostic, &mut dyn FnMut(Diagnostic))> = AtomicRef::new(&(default_track_diagnostic as _)); +#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] +pub enum DelayedBugKind { + Normal, + GoodPath, +} + #[derive(Copy, Clone, Default)] pub struct DiagCtxtFlags { /// If false, warning-level lints are suppressed. @@ -527,6 +533,9 @@ pub struct DiagCtxtFlags { /// If Some, the Nth error-level diagnostic is upgraded to bug-level. /// (rustc: see `-Z treat-err-as-bug`) pub treat_err_as_bug: Option<NonZeroUsize>, + /// Eagerly emit delayed bugs as errors, so that the compiler debugger may + /// see all of the errors being emitted at once. + pub eagerly_emit_delayed_bugs: bool, /// Show macro backtraces. /// (rustc: see `-Z macro-backtrace`) pub macro_backtrace: bool, @@ -541,8 +550,7 @@ impl Drop for DiagCtxtInner { self.emit_stashed_diagnostics(); if !self.has_errors() { - let bugs = std::mem::replace(&mut self.span_delayed_bugs, Vec::new()); - self.flush_delayed(bugs, "no errors encountered even though `span_delayed_bug` issued"); + self.flush_delayed(DelayedBugKind::Normal) } // FIXME(eddyb) this explains what `good_path_delayed_bugs` are! @@ -551,11 +559,7 @@ impl Drop for DiagCtxtInner { // lints can be `#[allow]`'d, potentially leading to this triggering. // Also, "good path" should be replaced with a better naming. if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() { - let bugs = std::mem::replace(&mut self.good_path_delayed_bugs, Vec::new()); - self.flush_delayed( - bugs, - "no warnings or errors encountered even though `good_path_delayed_bugs` issued", - ); + self.flush_delayed(DelayedBugKind::GoodPath); } if self.check_unstable_expect_diagnostics { @@ -865,7 +869,8 @@ impl DiagCtxt { if treat_next_err_as_bug { self.bug(msg); } - DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).emit() + DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg) + .emit() } /// Like `delayed_bug`, but takes an additional span. @@ -882,16 +887,15 @@ impl DiagCtxt { if treat_next_err_as_bug { self.span_bug(sp, msg); } - DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).with_span(sp).emit() + DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg) + .with_span(sp) + .emit() } // FIXME(eddyb) note the comment inside `impl Drop for DiagCtxtInner`, that's // where the explanation of what "good path" is (also, it should be renamed). pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) { - let mut inner = self.inner.borrow_mut(); - let diagnostic = Diagnostic::new(DelayedBug, msg); - let backtrace = std::backtrace::Backtrace::capture(); - inner.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); + DiagnosticBuilder::<()>::new(self, DelayedBug(DelayedBugKind::GoodPath), msg).emit() } #[track_caller] @@ -981,6 +985,10 @@ impl DiagCtxt { inner.emit_stashed_diagnostics(); + if inner.treat_err_as_bug() { + return; + } + let warnings = match inner.deduplicated_warn_count { 0 => Cow::from(""), 1 => Cow::from("1 warning emitted"), @@ -991,9 +999,6 @@ impl DiagCtxt { 1 => Cow::from("aborting due to 1 previous error"), count => Cow::from(format!("aborting due to {count} previous errors")), }; - if inner.treat_err_as_bug() { - return; - } match (errors.len(), warnings.len()) { (0, 0) => return, @@ -1168,7 +1173,8 @@ impl DiagCtxt { let mut inner = self.inner.borrow_mut(); if loud && lint_level.is_error() { - inner.bump_err_count(); + inner.err_count += 1; + inner.panic_if_treat_err_as_bug(); } inner.emitter.emit_unused_externs(lint_level, unused_externs) @@ -1216,9 +1222,7 @@ impl DiagCtxt { } pub fn flush_delayed(&self) { - let mut inner = self.inner.borrow_mut(); - let bugs = std::mem::replace(&mut inner.span_delayed_bugs, Vec::new()); - inner.flush_delayed(bugs, "no errors encountered even though `span_delayed_bug` issued"); + self.inner.borrow_mut().flush_delayed(DelayedBugKind::Normal); } } @@ -1255,7 +1259,7 @@ impl DiagCtxtInner { } fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option<ErrorGuaranteed> { - if matches!(diagnostic.level, Error | Fatal) && self.treat_err_as_bug() { + if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() { diagnostic.level = Bug; } @@ -1268,17 +1272,30 @@ impl DiagCtxtInner { return None; } - 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 - // in which that's not sound? otherwise this is really inefficient. - let backtrace = std::backtrace::Backtrace::capture(); - self.span_delayed_bugs - .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace)); + // 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 + // in which that's not sound? otherwise this is really inefficient. + match diagnostic.level { + DelayedBug(_) if self.flags.eagerly_emit_delayed_bugs => { + diagnostic.level = Error; + } + DelayedBug(DelayedBugKind::Normal) => { + let backtrace = std::backtrace::Backtrace::capture(); + self.span_delayed_bugs + .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace)); - #[allow(deprecated)] - return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); + #[allow(deprecated)] + return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); + } + DelayedBug(DelayedBugKind::GoodPath) => { + let backtrace = std::backtrace::Backtrace::capture(); + self.good_path_delayed_bugs + .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace)); + + return None; + } + _ => {} } if diagnostic.has_future_breakage() { @@ -1353,10 +1370,11 @@ impl DiagCtxtInner { } if diagnostic.is_error() { if diagnostic.is_lint { - self.bump_lint_err_count(); + self.lint_err_count += 1; } else { - self.bump_err_count(); + self.err_count += 1; } + self.panic_if_treat_err_as_bug(); #[allow(deprecated)] { @@ -1393,11 +1411,18 @@ impl DiagCtxtInner { self.emit_diagnostic(Diagnostic::new(FailureNote, msg)); } - fn flush_delayed( - &mut self, - bugs: Vec<DelayedDiagnostic>, - explanation: impl Into<DiagnosticMessage> + Copy, - ) { + fn flush_delayed(&mut self, kind: DelayedBugKind) { + let (bugs, explanation) = match kind { + DelayedBugKind::Normal => ( + std::mem::take(&mut self.span_delayed_bugs), + "no errors encountered even though `span_delayed_bug` issued", + ), + DelayedBugKind::GoodPath => ( + std::mem::take(&mut self.good_path_delayed_bugs), + "no warnings or errors encountered even though `good_path_delayed_bugs` issued", + ), + }; + if bugs.is_empty() { return; } @@ -1430,7 +1455,7 @@ impl DiagCtxtInner { if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner }; // "Undelay" the `DelayedBug`s (into plain `Bug`s). - if bug.level != DelayedBug { + if !matches!(bug.level, DelayedBug(_)) { // NOTE(eddyb) not panicking here because we're already producing // an ICE, and the more information the merrier. bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel { @@ -1447,16 +1472,6 @@ impl DiagCtxtInner { panic::panic_any(DelayedBugPanic); } - fn bump_lint_err_count(&mut self) { - self.lint_err_count += 1; - self.panic_if_treat_err_as_bug(); - } - - fn bump_err_count(&mut self) { - self.err_count += 1; - self.panic_if_treat_err_as_bug(); - } - fn panic_if_treat_err_as_bug(&self) { if self.treat_err_as_bug() { match ( @@ -1528,8 +1543,9 @@ pub enum Level { /// 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, + /// Its `EmissionGuarantee` is `ErrorGuaranteed` for `Normal` delayed bugs, and `()` for + /// `GoodPath` delayed bugs. + DelayedBug(DelayedBugKind), /// An error that causes an immediate abort. Used for things like configuration errors, /// internal overflows, some file operation errors. @@ -1604,7 +1620,7 @@ impl Level { fn color(self) -> ColorSpec { let mut spec = ColorSpec::new(); match self { - Bug | DelayedBug | Fatal | Error => { + Bug | DelayedBug(_) | Fatal | Error => { spec.set_fg(Some(Color::Red)).set_intense(true); } ForceWarning(_) | Warning => { @@ -1624,7 +1640,7 @@ impl Level { pub fn to_str(self) -> &'static str { match self { - Bug | DelayedBug => "error: internal compiler error", + Bug | DelayedBug(_) => "error: internal compiler error", Fatal | Error => "error", ForceWarning(_) | Warning => "warning", Note | OnceNote => "note", diff --git a/compiler/rustc_errors/src/markdown/tests/term.rs b/compiler/rustc_errors/src/markdown/tests/term.rs index a0d956bf0cd..bab47dcc175 100644 --- a/compiler/rustc_errors/src/markdown/tests/term.rs +++ b/compiler/rustc_errors/src/markdown/tests/term.rs @@ -5,7 +5,8 @@ use termcolor::{BufferWriter, ColorChoice}; use super::*; const INPUT: &str = include_str!("input.md"); -const OUTPUT_PATH: &[&str] = &[env!("CARGO_MANIFEST_DIR"), "src","markdown","tests","output.stdout"]; +const OUTPUT_PATH: &[&str] = + &[env!("CARGO_MANIFEST_DIR"), "src", "markdown", "tests", "output.stdout"]; const TEST_WIDTH: usize = 80; @@ -34,7 +35,7 @@ quis dolor non venenatis. Aliquam ut. "; fn test_wrapping_write() { WIDTH.with(|w| w.set(TEST_WIDTH)); let mut buf = BufWriter::new(Vec::new()); - let txt = TXT.replace("-\n","-").replace("_\n","_").replace('\n', " ").replace(" ", ""); + let txt = TXT.replace("-\n", "-").replace("_\n", "_").replace('\n', " ").replace(" ", ""); write_wrapping(&mut buf, &txt, 0, None).unwrap(); write_wrapping(&mut buf, &txt, 4, None).unwrap(); write_wrapping( |
