Skip to content

Commit 3dfb6d3

Browse files
committed
Add -Zerror-metrics=PATH to save diagnostic metadata to disk
Add nightly only flag to store information about encountered errors to disk. The information being tracked is: - Error code - Path to error being emitted - Number of subdiagnostics - Number of structured suggestions
1 parent 2df6406 commit 3dfb6d3

File tree

5 files changed

+31
-3
lines changed

5 files changed

+31
-3
lines changed

compiler/rustc_errors/src/emitter.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use rustc_span::hygiene::{ExpnKind, MacroKind};
3030
use std::borrow::Cow;
3131
use std::cmp::{max, min, Reverse};
3232
use std::error::Report;
33+
use std::fs::File;
3334
use std::io::prelude::*;
3435
use std::io::{self, IsTerminal};
3536
use std::iter;
@@ -538,7 +539,7 @@ impl Emitter for EmitterWriter {
538539
&primary_span,
539540
&children,
540541
suggestions,
541-
self.track_diagnostics.then_some(&diag.emitted_at),
542+
&diag.emitted_at,
542543
);
543544
}
544545

@@ -637,6 +638,7 @@ pub struct EmitterWriter {
637638

638639
macro_backtrace: bool,
639640
track_diagnostics: bool,
641+
metrics: Option<File>,
640642
terminal_url: TerminalUrl,
641643
}
642644

@@ -666,6 +668,7 @@ impl EmitterWriter {
666668
diagnostic_width: None,
667669
macro_backtrace: false,
668670
track_diagnostics: false,
671+
metrics: None,
669672
terminal_url: TerminalUrl::No,
670673
}
671674
}
@@ -2079,15 +2082,27 @@ impl EmitterWriter {
20792082
span: &MultiSpan,
20802083
children: &[SubDiagnostic],
20812084
suggestions: &[CodeSuggestion],
2082-
emitted_at: Option<&DiagnosticLocation>,
2085+
emitted_at_location: &DiagnosticLocation,
20832086
) {
2087+
let emitted_at = self.track_diagnostics.then_some(emitted_at_location);
20842088
let max_line_num_len = if self.ui_testing {
20852089
ANONYMIZED_LINE_NUM.len()
20862090
} else {
20872091
let n = self.get_max_line_num(span, children);
20882092
num_decimal_digits(n)
20892093
};
20902094

2095+
if let Some(ref mut file) = &mut self.metrics {
2096+
let _ = writeln!(
2097+
file,
2098+
"{:?},{:?},{},{}",
2099+
code,
2100+
emitted_at_location,
2101+
children.len(),
2102+
suggestions.len()
2103+
);
2104+
}
2105+
20912106
match self.emit_messages_default_inner(
20922107
span,
20932108
messages,

compiler/rustc_errors/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnosti
514514
pub static TRACK_DIAGNOSTICS: AtomicRef<fn(&mut Diagnostic, &mut dyn FnMut(&mut Diagnostic))> =
515515
AtomicRef::new(&(default_track_diagnostic as _));
516516

517-
#[derive(Copy, Clone, Default)]
517+
#[derive(Clone, Default)]
518518
pub struct DiagCtxtFlags {
519519
/// If false, warning-level lints are suppressed.
520520
/// (rustc: see `--allow warnings` and `--cap-lints`)
@@ -535,6 +535,8 @@ pub struct DiagCtxtFlags {
535535
pub deduplicate_diagnostics: bool,
536536
/// Track where errors are created. Enabled with `-Ztrack-diagnostics`.
537537
pub track_diagnostics: bool,
538+
/// Track whether error metrics are stored. Enabled with `-Zerror-metrics=path`.
539+
pub metrics: Option<PathBuf>,
538540
}
539541

540542
impl Drop for DiagCtxtInner {

compiler/rustc_session/src/config.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,7 @@ impl UnstableOptions {
11651165
macro_backtrace: self.macro_backtrace,
11661166
deduplicate_diagnostics: self.deduplicate_diagnostics,
11671167
track_diagnostics: self.track_diagnostics,
1168+
metrics: self.error_metrics.clone(),
11681169
}
11691170
}
11701171
}

compiler/rustc_session/src/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1943,6 +1943,8 @@ written to standard error output)"),
19431943
"for every macro invocation, print its name and arguments (default: no)"),
19441944
track_diagnostics: bool = (false, parse_bool, [UNTRACKED],
19451945
"tracks where in rustc a diagnostic was emitted"),
1946+
error_metrics: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
1947+
"stores metrics about the errors being emitted by rustc to disk"),
19461948
// Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved
19471949
// alongside query results and changes to translation options can affect diagnostics - so
19481950
// translation options should be tracked.

compiler/rustc_session/src/session.rs

+8
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use std::any::Any;
4141
use std::cell::{self, RefCell};
4242
use std::env;
4343
use std::fmt;
44+
use std::fs::File;
4445
use std::ops::{Div, Mul};
4546
use std::path::{Path, PathBuf};
4647
use std::str::FromStr;
@@ -1009,6 +1010,12 @@ fn default_emitter(
10091010
);
10101011
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
10111012
} else {
1013+
let metrics = sopts.unstable_opts.error_metrics.as_ref().and_then(|path| {
1014+
let mut path = path.clone();
1015+
std::fs::create_dir_all(&path).ok()?;
1016+
path.push(format!("error_metrics_{}", std::process::id()));
1017+
File::options().create(true).append(true).open(&path).ok()
1018+
});
10121019
let emitter = EmitterWriter::stderr(color_config, fallback_bundle)
10131020
.fluent_bundle(bundle)
10141021
.sm(Some(source_map))
@@ -1018,6 +1025,7 @@ fn default_emitter(
10181025
.macro_backtrace(macro_backtrace)
10191026
.track_diagnostics(track_diagnostics)
10201027
.terminal_url(terminal_url)
1028+
.metrics(metrics)
10211029
.ignored_directories_in_source_blocks(
10221030
sopts.unstable_opts.ignore_directory_in_diagnostics_source_blocks.clone(),
10231031
);

0 commit comments

Comments
 (0)