未验证 提交 3c87772a 编写于 作者: D Dylan DPC 提交者: GitHub

Rollup merge of #67709 - petrochenkov:nodedup2, r=Centril

Introduce an option for disabling deduplication of diagnostics

With the intent of using it in UI tests (https://github.com/rust-lang/rust/pull/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.
......@@ -329,6 +329,8 @@ pub struct HandlerFlags {
/// show macro backtraces even for non-local macros.
/// (rustc: see `-Z external-macro-backtrace`)
pub external_macro_backtrace: bool,
/// If true, identical diagnostics are reported only once.
pub deduplicate_diagnostics: bool,
}
impl Drop for HandlerInner {
......@@ -736,16 +738,17 @@ fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
self.emitted_diagnostic_codes.insert(code.clone());
}
let diagnostic_hash = {
let already_emitted = |this: &mut Self| {
use std::hash::Hash;
let mut hasher = StableHasher::new();
diagnostic.hash(&mut hasher);
hasher.finish()
let diagnostic_hash = hasher.finish();
!this.emitted_diagnostics.insert(diagnostic_hash)
};
// Only emit the diagnostic if we haven't already emitted an equivalent
// one:
if self.emitted_diagnostics.insert(diagnostic_hash) {
// Only emit the diagnostic if we've been asked to deduplicate and
// haven't already emitted an equivalent diagnostic.
if !(self.flags.deduplicate_diagnostics && already_emitted(self)) {
self.emitter.emit_diagnostic(diagnostic);
if diagnostic.is_error() {
self.deduplicated_err_count += 1;
......
......@@ -20,7 +20,7 @@
use rustc_span::symbol::{sym, Symbol};
use rustc_errors::emitter::HumanReadableErrorType;
use rustc_errors::{ColorConfig, FatalError, Handler};
use rustc_errors::{ColorConfig, FatalError, Handler, HandlerFlags};
use getopts;
......@@ -597,6 +597,17 @@ impl DebuggingOptions {
pub fn ui_testing(&self) -> bool {
self.ui_testing.unwrap_or(false)
}
pub fn diagnostic_handler_flags(&self, can_emit_warnings: bool) -> HandlerFlags {
HandlerFlags {
can_emit_warnings,
treat_err_as_bug: self.treat_err_as_bug,
dont_buffer_diagnostics: self.dont_buffer_diagnostics,
report_delayed_bugs: self.report_delayed_bugs,
external_macro_backtrace: self.external_macro_backtrace,
deduplicate_diagnostics: self.deduplicate_diagnostics.unwrap_or(true),
}
}
}
// The type of entry function, so users can have their own entry functions
......
......@@ -946,4 +946,6 @@ fn parse_symbol_mangling_version(
insert_sideeffect: bool = (false, parse_bool, [TRACKED],
"fix undefined behavior when a thread doesn't eventually make progress \
(such as entering an empty infinite loop) by inserting llvm.sideeffect"),
deduplicate_diagnostics: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
"deduplicate identical diagnostics"),
}
......@@ -941,15 +941,8 @@ pub fn build_session_with_source_map(
.last()
.unwrap_or(false);
let cap_lints_allow = sopts.lint_cap.map_or(false, |cap| cap == lint::Allow);
let can_emit_warnings = !(warnings_allow || cap_lints_allow);
let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug;
let dont_buffer_diagnostics = sopts.debugging_opts.dont_buffer_diagnostics;
let report_delayed_bugs = sopts.debugging_opts.report_delayed_bugs;
let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
let write_dest = match diagnostics_output {
DiagnosticOutput::Default => None,
DiagnosticOutput::Raw(write) => Some(write),
......@@ -958,14 +951,7 @@ pub fn build_session_with_source_map(
let diagnostic_handler = rustc_errors::Handler::with_emitter_and_flags(
emitter,
rustc_errors::HandlerFlags {
can_emit_warnings,
treat_err_as_bug,
report_delayed_bugs,
dont_buffer_diagnostics,
external_macro_backtrace,
..Default::default()
},
sopts.debugging_opts.diagnostic_handler_flags(can_emit_warnings),
);
build_session_(sopts, local_crate_source_file, diagnostic_handler, source_map, lint_caps)
......
......@@ -269,12 +269,7 @@ pub fn from_matches(matches: &getopts::Matches) -> Result<Options, i32> {
let codegen_options = build_codegen_options(matches, error_format);
let debugging_options = build_debugging_options(matches, error_format);
let diag = new_handler(
error_format,
None,
debugging_options.treat_err_as_bug,
debugging_options.ui_testing(),
);
let diag = new_handler(error_format, None, &debugging_options);
// check for deprecated options
check_deprecated_options(&matches, &diag);
......
......@@ -35,7 +35,7 @@
use crate::passes;
pub use rustc::session::config::{CodegenOptions, Input, Options};
pub use rustc::session::config::{CodegenOptions, DebuggingOptions, Input, Options};
pub use rustc::session::search_paths::SearchPath;
pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
......@@ -170,12 +170,8 @@ pub fn deprecation(&self, id: HirId) -> Option<attr::Deprecation> {
pub fn new_handler(
error_format: ErrorOutputType,
source_map: Option<Lrc<source_map::SourceMap>>,
treat_err_as_bug: Option<usize>,
ui_testing: bool,
debugging_opts: &DebuggingOptions,
) -> errors::Handler {
// rustdoc doesn't override (or allow to override) anything from this that is relevant here, so
// stick to the defaults
let sessopts = Options::default();
let emitter: Box<dyn Emitter + sync::Send> = match error_format {
ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip();
......@@ -184,34 +180,25 @@ pub fn new_handler(
color_config,
source_map.map(|cm| cm as _),
short,
sessopts.debugging_opts.teach,
sessopts.debugging_opts.terminal_width,
debugging_opts.teach,
debugging_opts.terminal_width,
false,
)
.ui_testing(ui_testing),
.ui_testing(debugging_opts.ui_testing()),
)
}
ErrorOutputType::Json { pretty, json_rendered } => {
let source_map = source_map.unwrap_or_else(|| {
Lrc::new(source_map::SourceMap::new(sessopts.file_path_mapping()))
Lrc::new(source_map::SourceMap::new(source_map::FilePathMapping::empty()))
});
Box::new(
JsonEmitter::stderr(None, source_map, pretty, json_rendered, false)
.ui_testing(ui_testing),
.ui_testing(debugging_opts.ui_testing()),
)
}
};
errors::Handler::with_emitter_and_flags(
emitter,
errors::HandlerFlags {
can_emit_warnings: true,
treat_err_as_bug,
report_delayed_bugs: false,
external_macro_backtrace: false,
..Default::default()
},
)
errors::Handler::with_emitter_and_flags(emitter, debugging_opts.diagnostic_handler_flags(true))
}
pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOptions) {
......
......@@ -445,12 +445,7 @@ fn main_args(args: &[String]) -> i32 {
}
fn main_options(options: config::Options) -> i32 {
let diag = core::new_handler(
options.error_format,
None,
options.debugging_options.treat_err_as_bug,
options.debugging_options.ui_testing(),
);
let diag = core::new_handler(options.error_format, None, &options.debugging_options);
match (options.should_test, options.markdown_input()) {
(true, true) => return markdown::test(options, &diag),
......@@ -463,12 +458,7 @@ fn main_options(options: config::Options) -> i32 {
// need to move these items separately because we lose them by the time the closure is called,
// but we can't crates the Handler ahead of time because it's not Send
let diag_opts = (
options.error_format,
options.debugging_options.treat_err_as_bug,
options.debugging_options.ui_testing(),
options.edition,
);
let diag_opts = (options.error_format, options.edition, options.debugging_options.clone());
let show_coverage = options.show_coverage;
rust_input(options, move |out| {
if show_coverage {
......@@ -479,8 +469,8 @@ fn main_options(options: config::Options) -> i32 {
let Output { krate, renderinfo, renderopts } = out;
info!("going to format");
let (error_format, treat_err_as_bug, ui_testing, edition) = diag_opts;
let diag = core::new_handler(error_format, None, treat_err_as_bug, ui_testing);
let (error_format, edition, debugging_options) = diag_opts;
let diag = core::new_handler(error_format, None, &debugging_options);
match html::render::run(krate, renderopts, renderinfo, &diag, edition) {
Ok(_) => rustc_driver::EXIT_SUCCESS,
Err(e) => {
......
......@@ -10,7 +10,7 @@ error: internal compiler error: mutable allocation in constant
LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:345:17
thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:347:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
error: internal compiler error: unexpected panic
......
error: cannot find derive macro `Unresolved` in this scope
--> $DIR/deduplicate-diagnostics.rs:4:10
|
LL | #[derive(Unresolved)]
| ^^^^^^^^^^
error: aborting due to previous error
error: cannot find derive macro `Unresolved` in this scope
--> $DIR/deduplicate-diagnostics.rs:4:10
|
LL | #[derive(Unresolved)]
| ^^^^^^^^^^
error: cannot find derive macro `Unresolved` in this scope
--> $DIR/deduplicate-diagnostics.rs:4:10
|
LL | #[derive(Unresolved)]
| ^^^^^^^^^^
error: aborting due to 2 previous errors
// revisions: duplicate deduplicate
//[duplicate] compile-flags: -Z deduplicate-diagnostics=no
#[derive(Unresolved)] //~ ERROR cannot find derive macro `Unresolved` in this scope
//[duplicate]~| ERROR cannot find derive macro `Unresolved` in this scope
struct S;
fn main() {}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册