diff options
| author | bors <bors@rust-lang.org> | 2024-07-11 17:10:09 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-07-11 17:10:09 +0000 |
| commit | a3d6efc9bcdc379e766735cc53e065d85a1755e9 (patch) | |
| tree | 24923a8226aad3064a6c5739540c2d404d64f76e /compiler/rustc_errors/src | |
| parent | 45609a995e766d614da694d353f7aee03820b0f9 (diff) | |
| parent | 62bbce2ad2b20d5cf1282da407d01de5c54161f1 (diff) | |
| download | rust-a3d6efc9bcdc379e766735cc53e065d85a1755e9.tar.gz rust-a3d6efc9bcdc379e766735cc53e065d85a1755e9.zip | |
Auto merge of #17581 - lnicola:sync-from-rust, r=lnicola
minor: Sync from rust
Diffstat (limited to 'compiler/rustc_errors/src')
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic_impls.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/emitter.rs | 54 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/json.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/lib.rs | 102 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/markdown/mod.rs | 1 |
6 files changed, 140 insertions, 45 deletions
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index e580910af77..d500f6d88a0 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -510,7 +510,7 @@ pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> { // would be bad. impl<G> !Clone for Diag<'_, G> {} -rustc_data_structures::static_assert_size!(Diag<'_, ()>, 2 * std::mem::size_of::<usize>()); +rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * std::mem::size_of::<usize>()); impl<G: EmissionGuarantee> Deref for Diag<'_, G> { type Target = DiagInner; @@ -582,6 +582,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { Self::new_diagnostic(dcx, DiagInner::new(level, message)) } + /// Allow moving diagnostics between different error tainting contexts + pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_, G> { + Diag { dcx, diag: self.diag.take(), _marker: PhantomData } + } + /// Creates a new `Diag` with an already constructed diagnostic. #[track_caller] pub(crate) fn new_diagnostic(dcx: DiagCtxtHandle<'a>, diag: DiagInner) -> Self { diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 0af80bc5c67..e6ca1bf7bc4 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -298,15 +298,21 @@ impl IntoDiagArg for hir::def::Namespace { } #[derive(Clone)] -pub struct DiagSymbolList(Vec<Symbol>); +pub struct DiagSymbolList<S = Symbol>(Vec<S>); -impl From<Vec<Symbol>> for DiagSymbolList { - fn from(v: Vec<Symbol>) -> Self { +impl<S> From<Vec<S>> for DiagSymbolList<S> { + fn from(v: Vec<S>) -> Self { DiagSymbolList(v) } } -impl IntoDiagArg for DiagSymbolList { +impl<S> FromIterator<S> for DiagSymbolList<S> { + fn from_iter<T: IntoIterator<Item = S>>(iter: T) -> Self { + iter.into_iter().collect::<Vec<_>>().into() + } +} + +impl<S: std::fmt::Display> IntoDiagArg for DiagSymbolList<S> { fn into_diag_arg(self) -> DiagArgValue { DiagArgValue::StrListSepByAnd( self.0.into_iter().map(|sym| Cow::Owned(format!("`{sym}`"))).collect(), diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 245deda50d5..aa47ca16676 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -902,7 +902,7 @@ impl HumanEmitter { // <EMPTY LINE> // let mut annotations_position = vec![]; - let mut line_len = 0; + let mut line_len: usize = 0; let mut p = 0; for (i, annotation) in annotations.iter().enumerate() { for (j, next) in annotations.iter().enumerate() { @@ -973,6 +973,31 @@ impl HumanEmitter { return vec![]; } + if annotations_position + .iter() + .all(|(_, ann)| matches!(ann.annotation_type, AnnotationType::MultilineStart(_))) + && let Some(max_pos) = annotations_position.iter().map(|(pos, _)| *pos).max() + { + // Special case the following, so that we minimize overlapping multiline spans. + // + // 3 │ X0 Y0 Z0 + // │ ┏━━━━━┛ │ │ < We are writing these lines + // │ ┃┌───────┘ │ < by reverting the "depth" of + // │ ┃│┌─────────┘ < their multilne spans. + // 4 │ ┃││ X1 Y1 Z1 + // 5 │ ┃││ X2 Y2 Z2 + // │ ┃│└────╿──│──┘ `Z` label + // │ ┃└─────│──┤ + // │ ┗━━━━━━┥ `Y` is a good letter too + // ╰╴ `X` is a good letter + for (pos, _) in &mut annotations_position { + *pos = max_pos - *pos; + } + // We know then that we don't need an additional line for the span label, saving us + // one line of vertical space. + line_len = line_len.saturating_sub(1); + } + // Write the column separator. // // After this we will have: @@ -1905,7 +1930,7 @@ impl HumanEmitter { // // LL | this line was highlighted // LL | this line is just for context - // ... + // ... // LL | this line is just for context // LL | this line was highlighted _ => { @@ -1926,7 +1951,7 @@ impl HumanEmitter { ) } - buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber); + buffer.puts(row_num, 0, "...", Style::LineNumber); row_num += 1; if let Some((p, l)) = last_line { @@ -2248,9 +2273,26 @@ impl HumanEmitter { &normalize_whitespace(last_line), Style::NoStyle, ); - buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber); - buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition); - buffer.append(*row_num, &normalize_whitespace(line_to_add), Style::NoStyle); + if !line_to_add.trim().is_empty() { + // Check if after the removal, the line is left with only whitespace. If so, we + // will not show an "addition" line, as removing the whole line is what the user + // would really want. + // For example, for the following: + // | + // 2 - .await + // 2 + (note the left over whitepsace) + // | + // We really want + // | + // 2 - .await + // | + // *row_num -= 1; + buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber); + buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition); + buffer.append(*row_num, &normalize_whitespace(line_to_add), Style::NoStyle); + } else { + *row_num -= 1; + } } else { *row_num -= 2; } diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index af82d8092c2..764134d5335 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -135,7 +135,12 @@ impl Emitter for JsonEmitter { let data: Vec<FutureBreakageItem<'_>> = diags .into_iter() .map(|mut diag| { - if diag.level == crate::Level::Allow { + // Allowed or expected lints don't normally (by definition) emit a lint + // but future incompat lints are special and are emitted anyway. + // + // So to avoid ICEs and confused users we "upgrade" the lint level for + // those `FutureBreakageItem` to warn. + if matches!(diag.level, crate::Level::Allow | crate::Level::Expect(..)) { diag.level = crate::Level::Warning; } FutureBreakageItem { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 83d5bbff0b0..2086d4030f9 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -63,6 +63,7 @@ use rustc_span::source_map::SourceMap; use rustc_span::{Loc, Span, DUMMY_SP}; use std::backtrace::{Backtrace, BacktraceStatus}; use std::borrow::Cow; +use std::cell::Cell; use std::error::Report; use std::fmt; use std::hash::Hash; @@ -98,9 +99,9 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16); +rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24); #[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16); +rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24); #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)] pub enum SuggestionStyle { @@ -417,6 +418,9 @@ pub struct DiagCtxt { #[derive(Copy, Clone)] pub struct DiagCtxtHandle<'a> { dcx: &'a DiagCtxt, + /// Some contexts create `DiagCtxtHandle` with this field set, and thus all + /// errors emitted with it will automatically taint when emitting errors. + tainted_with_errors: Option<&'a Cell<Option<ErrorGuaranteed>>>, } impl<'a> std::ops::Deref for DiagCtxtHandle<'a> { @@ -752,7 +756,17 @@ impl DiagCtxt { } pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> { - DiagCtxtHandle { dcx: self } + DiagCtxtHandle { dcx: self, tainted_with_errors: None } + } + + /// Link this to a taintable context so that emitting errors will automatically set + /// the `Option<ErrorGuaranteed>` instead of having to do that manually at every error + /// emission site. + pub fn taintable_handle<'a>( + &'a self, + tainted_with_errors: &'a Cell<Option<ErrorGuaranteed>>, + ) -> DiagCtxtHandle<'a> { + DiagCtxtHandle { dcx: self, tainted_with_errors: Some(tainted_with_errors) } } } @@ -795,7 +809,9 @@ impl<'a> DiagCtxtHandle<'a> { // can be used to create a backtrace at the stashing site insted of whenever the // diagnostic context is dropped and thus delayed bugs are emitted. Error => Some(self.span_delayed_bug(span, format!("stashing {key:?}"))), - DelayedBug => return self.inner.borrow_mut().emit_diagnostic(diag), + DelayedBug => { + return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors); + } ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow | Expect(_) => None, }; @@ -947,16 +963,19 @@ impl<'a> DiagCtxtHandle<'a> { (0, _) => { // Use `ForceWarning` rather than `Warning` to guarantee emission, e.g. with a // configuration like `--cap-lints allow --force-warn bare_trait_objects`. - inner.emit_diagnostic(DiagInner::new( - ForceWarning(None), - DiagMessage::Str(warnings), - )); + inner.emit_diagnostic( + DiagInner::new(ForceWarning(None), DiagMessage::Str(warnings)), + None, + ); } (_, 0) => { - inner.emit_diagnostic(DiagInner::new(Error, errors)); + inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors); } (_, _) => { - inner.emit_diagnostic(DiagInner::new(Error, format!("{errors}; {warnings}"))); + inner.emit_diagnostic( + DiagInner::new(Error, format!("{errors}; {warnings}")), + self.tainted_with_errors, + ); } } @@ -987,14 +1006,14 @@ impl<'a> DiagCtxtHandle<'a> { "For more information about an error, try `rustc --explain {}`.", &error_codes[0] ); - inner.emit_diagnostic(DiagInner::new(FailureNote, msg1)); - inner.emit_diagnostic(DiagInner::new(FailureNote, msg2)); + inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None); + inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None); } else { let msg = format!( "For more information about this error, try `rustc --explain {}`.", &error_codes[0] ); - inner.emit_diagnostic(DiagInner::new(FailureNote, msg)); + inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None); } } } @@ -1020,7 +1039,7 @@ impl<'a> DiagCtxtHandle<'a> { } pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option<ErrorGuaranteed> { - self.inner.borrow_mut().emit_diagnostic(diagnostic) + self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors) } pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { @@ -1080,7 +1099,7 @@ impl<'a> DiagCtxtHandle<'a> { // Here the diagnostic is given back to `emit_diagnostic` where it was first // intercepted. Now it should be processed as usual, since the unstable expectation // id is now stable. - inner.emit_diagnostic(diag); + inner.emit_diagnostic(diag, self.tainted_with_errors); } } @@ -1430,18 +1449,40 @@ impl DiagCtxtInner { continue; } } - guar = guar.or(self.emit_diagnostic(diag)); + guar = guar.or(self.emit_diagnostic(diag, None)); } guar } // Return value is only `Some` if the level is `Error` or `DelayedBug`. - fn emit_diagnostic(&mut self, mut diagnostic: DiagInner) -> Option<ErrorGuaranteed> { + fn emit_diagnostic( + &mut self, + mut diagnostic: DiagInner, + taint: Option<&Cell<Option<ErrorGuaranteed>>>, + ) -> Option<ErrorGuaranteed> { + match diagnostic.level { + Expect(expect_id) | ForceWarning(Some(expect_id)) => { + // The `LintExpectationId` can be stable or unstable depending on when it was + // created. Diagnostics created before the definition of `HirId`s are unstable and + // can not yet be stored. Instead, they are buffered until the `LintExpectationId` + // is replaced by a stable one by the `LintLevelsBuilder`. + if let LintExpectationId::Unstable { .. } = expect_id { + // We don't call TRACK_DIAGNOSTIC because we wait for the + // unstable ID to be updated, whereupon the diagnostic will be + // passed into this method again. + self.unstable_expect_diagnostics.push(diagnostic); + return None; + } + // Continue through to the `Expect`/`ForceWarning` case below. + } + _ => {} + } + if diagnostic.has_future_breakage() { - // 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 must_produce_diag check. - assert!(matches!(diagnostic.level, Error | Warning | Allow)); + // Future breakages aren't emitted if they're `Level::Allow` or + // `Level::Expect`, but they still need to be constructed and + // stashed below, so they'll trigger the must_produce_diag check. + assert!(matches!(diagnostic.level, Error | Warning | Allow | Expect(_))); self.future_breakage_diagnostics.push(diagnostic.clone()); } @@ -1512,16 +1553,8 @@ impl DiagCtxtInner { return None; } Expect(expect_id) | ForceWarning(Some(expect_id)) => { - // Diagnostics created before the definition of `HirId`s are - // unstable and can not yet be stored. Instead, they are - // buffered until the `LintExpectationId` is replaced by a - // stable one by the `LintLevelsBuilder`. if let LintExpectationId::Unstable { .. } = expect_id { - // We don't call TRACK_DIAGNOSTIC because we wait for the - // unstable ID to be updated, whereupon the diagnostic will - // be passed into this method again. - self.unstable_expect_diagnostics.push(diagnostic); - return None; + unreachable!(); // this case was handled at the top of this function } self.fulfilled_expectations.insert(expect_id.normalize()); if let Expect(_) = diagnostic.level { @@ -1599,6 +1632,9 @@ impl DiagCtxtInner { if is_lint { self.lint_err_guars.push(guar); } else { + if let Some(taint) = taint { + taint.set(Some(guar)); + } self.err_guars.push(guar); } self.panic_if_treat_err_as_bug(); @@ -1708,8 +1744,8 @@ impl DiagCtxtInner { // `-Ztreat-err-as-bug`, which we don't want. let note1 = "no errors encountered even though delayed bugs were created"; let note2 = "those delayed bugs will now be shown as internal compiler errors"; - self.emit_diagnostic(DiagInner::new(Note, note1)); - self.emit_diagnostic(DiagInner::new(Note, note2)); + self.emit_diagnostic(DiagInner::new(Note, note1), None); + self.emit_diagnostic(DiagInner::new(Note, note2), None); for bug in bugs { if let Some(out) = &mut out { @@ -1742,7 +1778,7 @@ impl DiagCtxtInner { } bug.level = Bug; - self.emit_diagnostic(bug); + self.emit_diagnostic(bug, None); } // Panic with `DelayedBugPanic` to avoid "unexpected panic" messages. diff --git a/compiler/rustc_errors/src/markdown/mod.rs b/compiler/rustc_errors/src/markdown/mod.rs index 53b766dfcce..64576cdc8ca 100644 --- a/compiler/rustc_errors/src/markdown/mod.rs +++ b/compiler/rustc_errors/src/markdown/mod.rs @@ -1,6 +1,7 @@ //! A simple markdown parser that can write formatted text to the terminal //! //! Entrypoint is `MdStream::parse_str(...)` + use std::io; use termcolor::{Buffer, BufferWriter, ColorChoice}; |
