Skip to content

Commit 3c87772

Browse files
authored
Rollup merge of rust-lang#67709 - petrochenkov:nodedup2, r=Centril
Introduce an option for disabling deduplication of diagnostics With the intent of using it in UI tests (rust-lang#67122). The option is boolean (`-Z deduplicate-diagnostics=yes/no`) and can be specified multiple times with later values overriding earlier values (`-Z deduplicate-diagnostics=no -Z deduplicate-diagnostics=yes` == `-Z deduplicate-diagnostics=yes`), so it can be set in a hierarchical way, e.g. UI testing infra may disable the deduplication by default with specific tests being able to enable it back.
2 parents cce055d + 5bf8105 commit 3c87772

File tree

11 files changed

+67
-63
lines changed

11 files changed

+67
-63
lines changed

src/librustc_errors/lib.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,8 @@ pub struct HandlerFlags {
329329
/// show macro backtraces even for non-local macros.
330330
/// (rustc: see `-Z external-macro-backtrace`)
331331
pub external_macro_backtrace: bool,
332+
/// If true, identical diagnostics are reported only once.
333+
pub deduplicate_diagnostics: bool,
332334
}
333335

334336
impl Drop for HandlerInner {
@@ -736,16 +738,17 @@ impl HandlerInner {
736738
self.emitted_diagnostic_codes.insert(code.clone());
737739
}
738740

739-
let diagnostic_hash = {
741+
let already_emitted = |this: &mut Self| {
740742
use std::hash::Hash;
741743
let mut hasher = StableHasher::new();
742744
diagnostic.hash(&mut hasher);
743-
hasher.finish()
745+
let diagnostic_hash = hasher.finish();
746+
!this.emitted_diagnostics.insert(diagnostic_hash)
744747
};
745748

746-
// Only emit the diagnostic if we haven't already emitted an equivalent
747-
// one:
748-
if self.emitted_diagnostics.insert(diagnostic_hash) {
749+
// Only emit the diagnostic if we've been asked to deduplicate and
750+
// haven't already emitted an equivalent diagnostic.
751+
if !(self.flags.deduplicate_diagnostics && already_emitted(self)) {
749752
self.emitter.emit_diagnostic(diagnostic);
750753
if diagnostic.is_error() {
751754
self.deduplicated_err_count += 1;

src/librustc_session/config.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_span::source_map::{FileName, FilePathMapping};
2020
use rustc_span::symbol::{sym, Symbol};
2121

2222
use rustc_errors::emitter::HumanReadableErrorType;
23-
use rustc_errors::{ColorConfig, FatalError, Handler};
23+
use rustc_errors::{ColorConfig, FatalError, Handler, HandlerFlags};
2424

2525
use getopts;
2626

@@ -597,6 +597,17 @@ impl DebuggingOptions {
597597
pub fn ui_testing(&self) -> bool {
598598
self.ui_testing.unwrap_or(false)
599599
}
600+
601+
pub fn diagnostic_handler_flags(&self, can_emit_warnings: bool) -> HandlerFlags {
602+
HandlerFlags {
603+
can_emit_warnings,
604+
treat_err_as_bug: self.treat_err_as_bug,
605+
dont_buffer_diagnostics: self.dont_buffer_diagnostics,
606+
report_delayed_bugs: self.report_delayed_bugs,
607+
external_macro_backtrace: self.external_macro_backtrace,
608+
deduplicate_diagnostics: self.deduplicate_diagnostics.unwrap_or(true),
609+
}
610+
}
600611
}
601612

602613
// The type of entry function, so users can have their own entry functions

src/librustc_session/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -946,4 +946,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
946946
insert_sideeffect: bool = (false, parse_bool, [TRACKED],
947947
"fix undefined behavior when a thread doesn't eventually make progress \
948948
(such as entering an empty infinite loop) by inserting llvm.sideeffect"),
949+
deduplicate_diagnostics: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
950+
"deduplicate identical diagnostics"),
949951
}

src/librustc_session/session.rs

+1-15
Original file line numberDiff line numberDiff line change
@@ -941,15 +941,8 @@ pub fn build_session_with_source_map(
941941
.last()
942942
.unwrap_or(false);
943943
let cap_lints_allow = sopts.lint_cap.map_or(false, |cap| cap == lint::Allow);
944-
945944
let can_emit_warnings = !(warnings_allow || cap_lints_allow);
946945

947-
let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug;
948-
let dont_buffer_diagnostics = sopts.debugging_opts.dont_buffer_diagnostics;
949-
let report_delayed_bugs = sopts.debugging_opts.report_delayed_bugs;
950-
951-
let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
952-
953946
let write_dest = match diagnostics_output {
954947
DiagnosticOutput::Default => None,
955948
DiagnosticOutput::Raw(write) => Some(write),
@@ -958,14 +951,7 @@ pub fn build_session_with_source_map(
958951

959952
let diagnostic_handler = rustc_errors::Handler::with_emitter_and_flags(
960953
emitter,
961-
rustc_errors::HandlerFlags {
962-
can_emit_warnings,
963-
treat_err_as_bug,
964-
report_delayed_bugs,
965-
dont_buffer_diagnostics,
966-
external_macro_backtrace,
967-
..Default::default()
968-
},
954+
sopts.debugging_opts.diagnostic_handler_flags(can_emit_warnings),
969955
);
970956

971957
build_session_(sopts, local_crate_source_file, diagnostic_handler, source_map, lint_caps)

src/librustdoc/config.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -269,12 +269,7 @@ impl Options {
269269
let codegen_options = build_codegen_options(matches, error_format);
270270
let debugging_options = build_debugging_options(matches, error_format);
271271

272-
let diag = new_handler(
273-
error_format,
274-
None,
275-
debugging_options.treat_err_as_bug,
276-
debugging_options.ui_testing(),
277-
);
272+
let diag = new_handler(error_format, None, &debugging_options);
278273

279274
// check for deprecated options
280275
check_deprecated_options(&matches, &diag);

src/librustdoc/core.rs

+8-21
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use crate::html::render::RenderInfo;
3535

3636
use crate::passes;
3737

38-
pub use rustc::session::config::{CodegenOptions, Input, Options};
38+
pub use rustc::session::config::{CodegenOptions, DebuggingOptions, Input, Options};
3939
pub use rustc::session::search_paths::SearchPath;
4040

4141
pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
@@ -170,12 +170,8 @@ impl<'tcx> DocContext<'tcx> {
170170
pub fn new_handler(
171171
error_format: ErrorOutputType,
172172
source_map: Option<Lrc<source_map::SourceMap>>,
173-
treat_err_as_bug: Option<usize>,
174-
ui_testing: bool,
173+
debugging_opts: &DebuggingOptions,
175174
) -> errors::Handler {
176-
// rustdoc doesn't override (or allow to override) anything from this that is relevant here, so
177-
// stick to the defaults
178-
let sessopts = Options::default();
179175
let emitter: Box<dyn Emitter + sync::Send> = match error_format {
180176
ErrorOutputType::HumanReadable(kind) => {
181177
let (short, color_config) = kind.unzip();
@@ -184,34 +180,25 @@ pub fn new_handler(
184180
color_config,
185181
source_map.map(|cm| cm as _),
186182
short,
187-
sessopts.debugging_opts.teach,
188-
sessopts.debugging_opts.terminal_width,
183+
debugging_opts.teach,
184+
debugging_opts.terminal_width,
189185
false,
190186
)
191-
.ui_testing(ui_testing),
187+
.ui_testing(debugging_opts.ui_testing()),
192188
)
193189
}
194190
ErrorOutputType::Json { pretty, json_rendered } => {
195191
let source_map = source_map.unwrap_or_else(|| {
196-
Lrc::new(source_map::SourceMap::new(sessopts.file_path_mapping()))
192+
Lrc::new(source_map::SourceMap::new(source_map::FilePathMapping::empty()))
197193
});
198194
Box::new(
199195
JsonEmitter::stderr(None, source_map, pretty, json_rendered, false)
200-
.ui_testing(ui_testing),
196+
.ui_testing(debugging_opts.ui_testing()),
201197
)
202198
}
203199
};
204200

205-
errors::Handler::with_emitter_and_flags(
206-
emitter,
207-
errors::HandlerFlags {
208-
can_emit_warnings: true,
209-
treat_err_as_bug,
210-
report_delayed_bugs: false,
211-
external_macro_backtrace: false,
212-
..Default::default()
213-
},
214-
)
201+
errors::Handler::with_emitter_and_flags(emitter, debugging_opts.diagnostic_handler_flags(true))
215202
}
216203

217204
pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOptions) {

src/librustdoc/lib.rs

+4-14
Original file line numberDiff line numberDiff line change
@@ -445,12 +445,7 @@ fn main_args(args: &[String]) -> i32 {
445445
}
446446

447447
fn main_options(options: config::Options) -> i32 {
448-
let diag = core::new_handler(
449-
options.error_format,
450-
None,
451-
options.debugging_options.treat_err_as_bug,
452-
options.debugging_options.ui_testing(),
453-
);
448+
let diag = core::new_handler(options.error_format, None, &options.debugging_options);
454449

455450
match (options.should_test, options.markdown_input()) {
456451
(true, true) => return markdown::test(options, &diag),
@@ -463,12 +458,7 @@ fn main_options(options: config::Options) -> i32 {
463458

464459
// need to move these items separately because we lose them by the time the closure is called,
465460
// but we can't crates the Handler ahead of time because it's not Send
466-
let diag_opts = (
467-
options.error_format,
468-
options.debugging_options.treat_err_as_bug,
469-
options.debugging_options.ui_testing(),
470-
options.edition,
471-
);
461+
let diag_opts = (options.error_format, options.edition, options.debugging_options.clone());
472462
let show_coverage = options.show_coverage;
473463
rust_input(options, move |out| {
474464
if show_coverage {
@@ -479,8 +469,8 @@ fn main_options(options: config::Options) -> i32 {
479469

480470
let Output { krate, renderinfo, renderopts } = out;
481471
info!("going to format");
482-
let (error_format, treat_err_as_bug, ui_testing, edition) = diag_opts;
483-
let diag = core::new_handler(error_format, None, treat_err_as_bug, ui_testing);
472+
let (error_format, edition, debugging_options) = diag_opts;
473+
let diag = core::new_handler(error_format, None, &debugging_options);
484474
match html::render::run(krate, renderopts, renderinfo, &diag, edition) {
485475
Ok(_) => rustc_driver::EXIT_SUCCESS,
486476
Err(e) => {

src/test/ui/consts/miri_unleashed/mutable_const2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ error: internal compiler error: mutable allocation in constant
1010
LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

13-
thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:345:17
13+
thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:347:17
1414
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
1515

1616
error: internal compiler error: unexpected panic
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: cannot find derive macro `Unresolved` in this scope
2+
--> $DIR/deduplicate-diagnostics.rs:4:10
3+
|
4+
LL | #[derive(Unresolved)]
5+
| ^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: cannot find derive macro `Unresolved` in this scope
2+
--> $DIR/deduplicate-diagnostics.rs:4:10
3+
|
4+
LL | #[derive(Unresolved)]
5+
| ^^^^^^^^^^
6+
7+
error: cannot find derive macro `Unresolved` in this scope
8+
--> $DIR/deduplicate-diagnostics.rs:4:10
9+
|
10+
LL | #[derive(Unresolved)]
11+
| ^^^^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// revisions: duplicate deduplicate
2+
//[duplicate] compile-flags: -Z deduplicate-diagnostics=no
3+
4+
#[derive(Unresolved)] //~ ERROR cannot find derive macro `Unresolved` in this scope
5+
//[duplicate]~| ERROR cannot find derive macro `Unresolved` in this scope
6+
struct S;
7+
8+
fn main() {}

0 commit comments

Comments
 (0)