diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 07d001e9d847f..75409c71fea26 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -332,6 +332,7 @@ pub struct LongRunning { #[derive(Diagnostic)] #[diag("constant evaluation is taking a long time")] +#[note("number of steps elapsed: {$force_duplicate}")] pub struct LongRunningWarn { #[primary_span] #[label("the const evaluator is currently interpreting this expression")] diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 18f1af36b6202..a70d654b43cf1 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -9,6 +9,7 @@ use std::thread::panicking; use rustc_data_structures::sync::DynSend; use rustc_error_messages::{DiagArgMap, DiagArgName, DiagArgValue, IntoDiagArg}; +use rustc_errors::formatting::{format_diag_message, format_diag_messages}; use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_macros::{Decodable, Encodable}; use rustc_span::source_map::Spanned; @@ -350,7 +351,7 @@ impl DiagInner { } } - /// Fields used for Hash, and PartialEq trait. + /// Fields used for PartialEq trait. fn keys( &self, ) -> ( @@ -383,7 +384,41 @@ impl Hash for DiagInner { where H: Hasher, { - self.keys().hash(state); + // Instead of using `Self::keys`, we compute the hash for every field because we want to + // ensure that two independent diagnostics that are built from different structured errors + // or through the `Diag` API are equivalent if their *rendered output* is the same, which + // means we have to format the diagnostic messages (and labels) before computing the hash. + self.level.hash(state); + format_diag_messages(&self.messages, &self.args).hash(state); + self.code.hash(state); + for span in self.span.primary_spans() { + span.hash(state); + } + for span_label in self.span.span_labels() { + span_label.span.hash(state); + span_label.is_primary.hash(state); + if let Some(label) = span_label.label { + format_diag_message(&label, &self.args).hash(state); + } + } + for c in &self.children { + c.level.hash(state); + format_diag_messages(&c.messages, &self.args).hash(state); + for span_label in c.span.span_labels() { + span_label.span.hash(state); + span_label.is_primary.hash(state); + if let Some(label) = span_label.label { + format_diag_message(&label, &self.args).hash(state); + } + } + } + for s in self.suggestions.borrow_tag() { + s.style.hash(state); + s.substitutions.hash(state); + format_diag_message(&s.msg, &self.args).hash(state); + s.applicability.hash(state); + } + self.is_lint.hash(state); } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a96eceb6c715d..5c0f04df54f77 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -138,6 +138,14 @@ impl Suggestions { Suggestions::Disabled => Vec::new(), } } + + pub fn borrow_tag(&self) -> &[CodeSuggestion] { + match self { + Suggestions::Enabled(suggestions) => &suggestions, + Suggestions::Sealed(suggestions) => &suggestions, + Suggestions::Disabled => &[], + } + } } impl Default for Suggestions { @@ -1285,8 +1293,12 @@ impl DiagCtxtInner { let mut hasher = StableHasher::new(); diagnostic.hash(&mut hasher); let diagnostic_hash = hasher.finish(); + tracing::info!(?diagnostic.messages); + tracing::info!(?diagnostic.span); + tracing::info!(?diagnostic_hash); !self.emitted_diagnostics.insert(diagnostic_hash) }; + tracing::info!(?already_emitted); let is_error = diagnostic.is_error(); let is_lint = diagnostic.is_lint.is_some(); diff --git a/tests/ui/cfg/cfg-stmt-recovery.stderr b/tests/ui/cfg/cfg-stmt-recovery.stderr index e34da72afd934..a04ffad89a63f 100644 --- a/tests/ui/cfg/cfg-stmt-recovery.stderr +++ b/tests/ui/cfg/cfg-stmt-recovery.stderr @@ -15,6 +15,8 @@ error: removing an expression is not supported in this position | LL | let _ = #[cfg(false)] 0; | ^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr index dddd79a43838f..e747ee4876bb0 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr @@ -6,6 +6,7 @@ LL | / while index < n { LL | | } | |_____^ the const evaluator is currently interpreting this expression | + = note: number of steps elapsed: 32 help: the constant being evaluated --> $DIR/ctfe-simple-loop.rs:20:1 | diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr index 44abf8be6bdfa..11bdc000416f1 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr @@ -43,6 +43,7 @@ LL | / while index < n { LL | | } | |_____^ the const evaluator is currently interpreting this expression | + = note: number of steps elapsed: 32 help: the constant being evaluated --> $DIR/ctfe-simple-loop.rs:20:1 | diff --git a/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr b/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr index f41d2ea3e623d..aac22904397a3 100644 --- a/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr +++ b/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr @@ -6,6 +6,7 @@ LL | / loop { LL | | } | |_____^ the const evaluator is currently interpreting this expression | + = note: number of steps elapsed: 32 help: the constant being evaluated --> $DIR/evade-deduplication-issue-118612.rs:6:1 | @@ -20,6 +21,7 @@ LL | / loop { LL | | } | |_____^ the const evaluator is currently interpreting this expression | + = note: number of steps elapsed: 64 help: the constant being evaluated --> $DIR/evade-deduplication-issue-118612.rs:6:1 | @@ -34,6 +36,7 @@ LL | / loop { LL | | } | |_____^ the const evaluator is currently interpreting this expression | + = note: number of steps elapsed: 128 help: the constant being evaluated --> $DIR/evade-deduplication-issue-118612.rs:6:1 | @@ -48,6 +51,7 @@ LL | / loop { LL | | } | |_____^ the const evaluator is currently interpreting this expression | + = note: number of steps elapsed: 256 help: the constant being evaluated --> $DIR/evade-deduplication-issue-118612.rs:6:1 | @@ -62,6 +66,7 @@ LL | / loop { LL | | } | |_____^ the const evaluator is currently interpreting this expression | + = note: number of steps elapsed: 512 help: the constant being evaluated --> $DIR/evade-deduplication-issue-118612.rs:6:1 | diff --git a/tests/ui/coroutine/gen_block.none.stderr b/tests/ui/coroutine/gen_block.none.stderr index b793033b5216a..3d2782ca4e121 100644 --- a/tests/ui/coroutine/gen_block.none.stderr +++ b/tests/ui/coroutine/gen_block.none.stderr @@ -73,6 +73,7 @@ LL | let _ = || yield true; = note: see issue #43122 for more information = help: add `#![feature(yield_expr)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks --> $DIR/gen_block.rs:16:16 @@ -94,6 +95,7 @@ LL | let _ = #[coroutine] || yield true; = note: see issue #43122 for more information = help: add `#![feature(yield_expr)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 11 previous errors diff --git a/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr b/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr index c29c328ac143e..826651ab1ae11 100644 --- a/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr +++ b/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr @@ -47,6 +47,7 @@ LL | yield true; = note: see issue #43122 for more information = help: add `#![feature(yield_expr)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks --> $DIR/feature-gate-coroutines.rs:5:5 @@ -68,6 +69,7 @@ LL | let _ = || yield true; = note: see issue #43122 for more information = help: add `#![feature(yield_expr)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks --> $DIR/feature-gate-coroutines.rs:10:16 diff --git a/tests/ui/feature-gates/feature-gate-coroutines.none.stderr b/tests/ui/feature-gates/feature-gate-coroutines.none.stderr index c29c328ac143e..826651ab1ae11 100644 --- a/tests/ui/feature-gates/feature-gate-coroutines.none.stderr +++ b/tests/ui/feature-gates/feature-gate-coroutines.none.stderr @@ -47,6 +47,7 @@ LL | yield true; = note: see issue #43122 for more information = help: add `#![feature(yield_expr)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks --> $DIR/feature-gate-coroutines.rs:5:5 @@ -68,6 +69,7 @@ LL | let _ = || yield true; = note: see issue #43122 for more information = help: add `#![feature(yield_expr)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks --> $DIR/feature-gate-coroutines.rs:10:16 diff --git a/tests/ui/feature-gates/feature-gate-yield-expr.stderr b/tests/ui/feature-gates/feature-gate-yield-expr.stderr index bfac9e498037d..522290c07636d 100644 --- a/tests/ui/feature-gates/feature-gate-yield-expr.stderr +++ b/tests/ui/feature-gates/feature-gate-yield-expr.stderr @@ -17,6 +17,7 @@ LL | yield (); = note: see issue #43122 for more information = help: add `#![feature(yield_expr)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks --> $DIR/feature-gate-yield-expr.rs:5:5