Skip to content

Commit 11ebe65

Browse files
committed
Auto merge of #103217 - mejrs:track, r=eholk
Track where diagnostics were created. This implements the `-Ztrack-diagnostics` flag, which uses `#[track_caller]` to track where diagnostics are created. It is meant as a debugging tool much like `-Ztreat-err-as-bug`. For example, the following code... ```rust struct A; struct B; fn main(){ let _: A = B; } ``` ...now emits the following error message: ``` error[E0308]: mismatched types --> src\main.rs:5:16 | 5 | let _: A = B; | - ^ expected struct `A`, found struct `B` | | | expected due to this -Ztrack-diagnostics: created at compiler\rustc_infer\src\infer\error_reporting\mod.rs:2275:31 ```
2 parents ab5a2bc + cbeb244 commit 11ebe65

File tree

42 files changed

+385
-8
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+385
-8
lines changed

compiler/rustc_driver/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
12001200
false,
12011201
None,
12021202
false,
1203+
false,
12031204
));
12041205
let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
12051206

compiler/rustc_errors/src/diagnostic.rs

+29
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_span::{Span, DUMMY_SP};
1212
use std::borrow::Cow;
1313
use std::fmt;
1414
use std::hash::{Hash, Hasher};
15+
use std::panic::Location;
1516

1617
/// Error type for `Diagnostic`'s `suggestions` field, indicating that
1718
/// `.disable_suggestions()` was called on the `Diagnostic`.
@@ -107,6 +108,31 @@ pub struct Diagnostic {
107108
/// If diagnostic is from Lint, custom hash function ignores notes
108109
/// otherwise hash is based on the all the fields
109110
pub is_lint: bool,
111+
112+
/// With `-Ztrack_diagnostics` enabled,
113+
/// we print where in rustc this error was emitted.
114+
pub emitted_at: DiagnosticLocation,
115+
}
116+
117+
#[derive(Clone, Debug, Encodable, Decodable)]
118+
pub struct DiagnosticLocation {
119+
file: Cow<'static, str>,
120+
line: u32,
121+
col: u32,
122+
}
123+
124+
impl DiagnosticLocation {
125+
#[track_caller]
126+
fn caller() -> Self {
127+
let loc = Location::caller();
128+
DiagnosticLocation { file: loc.file().into(), line: loc.line(), col: loc.column() }
129+
}
130+
}
131+
132+
impl fmt::Display for DiagnosticLocation {
133+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134+
write!(f, "{}:{}:{}", self.file, self.line, self.col)
135+
}
110136
}
111137

112138
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
@@ -173,10 +199,12 @@ impl StringPart {
173199
}
174200

175201
impl Diagnostic {
202+
#[track_caller]
176203
pub fn new<M: Into<DiagnosticMessage>>(level: Level, message: M) -> Self {
177204
Diagnostic::new_with_code(level, None, message)
178205
}
179206

207+
#[track_caller]
180208
pub fn new_with_code<M: Into<DiagnosticMessage>>(
181209
level: Level,
182210
code: Option<DiagnosticId>,
@@ -192,6 +220,7 @@ impl Diagnostic {
192220
args: Default::default(),
193221
sort_span: DUMMY_SP,
194222
is_lint: false,
223+
emitted_at: DiagnosticLocation::caller(),
195224
}
196225
}
197226

compiler/rustc_errors/src/diagnostic_builder.rs

+5
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ mod sealed_level_is_error {
133133
impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> {
134134
/// Convenience function for internal use, clients should use one of the
135135
/// `struct_*` methods on [`Handler`].
136+
#[track_caller]
136137
pub(crate) fn new_guaranteeing_error<M: Into<DiagnosticMessage>, const L: Level>(
137138
handler: &'a Handler,
138139
message: M,
@@ -196,6 +197,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
196197
}
197198
}
198199

200+
#[track_caller]
199201
fn make_diagnostic_builder(
200202
handler: &Handler,
201203
msg: impl Into<DiagnosticMessage>,
@@ -209,6 +211,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
209211
impl<'a> DiagnosticBuilder<'a, ()> {
210212
/// Convenience function for internal use, clients should use one of the
211213
/// `struct_*` methods on [`Handler`].
214+
#[track_caller]
212215
pub(crate) fn new<M: Into<DiagnosticMessage>>(
213216
handler: &'a Handler,
214217
level: Level,
@@ -220,6 +223,7 @@ impl<'a> DiagnosticBuilder<'a, ()> {
220223

221224
/// Creates a new `DiagnosticBuilder` with an already constructed
222225
/// diagnostic.
226+
#[track_caller]
223227
pub(crate) fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
224228
debug!("Created new diagnostic");
225229
Self {
@@ -308,6 +312,7 @@ impl EmissionGuarantee for Noted {
308312
impl<'a> DiagnosticBuilder<'a, !> {
309313
/// Convenience function for internal use, clients should use one of the
310314
/// `struct_*` methods on [`Handler`].
315+
#[track_caller]
311316
pub(crate) fn new_fatal(handler: &'a Handler, message: impl Into<DiagnosticMessage>) -> Self {
312317
let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message);
313318
Self::new_diagnostic_fatal(handler, diagnostic)

compiler/rustc_errors/src/emitter.rs

+31-5
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Styl
1616
use crate::styled_buffer::StyledBuffer;
1717
use crate::translation::{to_fluent_args, Translate};
1818
use crate::{
19-
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, FluentBundle, Handler,
20-
LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight, SuggestionStyle,
19+
diagnostic::DiagnosticLocation, CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage,
20+
FluentBundle, Handler, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic,
21+
SubstitutionHighlight, SuggestionStyle,
2122
};
22-
2323
use rustc_lint_defs::pluralize;
2424

2525
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
@@ -64,6 +64,7 @@ impl HumanReadableErrorType {
6464
teach: bool,
6565
diagnostic_width: Option<usize>,
6666
macro_backtrace: bool,
67+
track_diagnostics: bool,
6768
) -> EmitterWriter {
6869
let (short, color_config) = self.unzip();
6970
let color = color_config.suggests_using_colors();
@@ -77,6 +78,7 @@ impl HumanReadableErrorType {
7778
color,
7879
diagnostic_width,
7980
macro_backtrace,
81+
track_diagnostics,
8082
)
8183
}
8284
}
@@ -557,6 +559,7 @@ impl Emitter for EmitterWriter {
557559
&primary_span,
558560
&children,
559561
&suggestions,
562+
self.track_diagnostics.then_some(&diag.emitted_at),
560563
);
561564
}
562565

@@ -650,6 +653,7 @@ pub struct EmitterWriter {
650653
diagnostic_width: Option<usize>,
651654

652655
macro_backtrace: bool,
656+
track_diagnostics: bool,
653657
}
654658

655659
#[derive(Debug)]
@@ -669,6 +673,7 @@ impl EmitterWriter {
669673
teach: bool,
670674
diagnostic_width: Option<usize>,
671675
macro_backtrace: bool,
676+
track_diagnostics: bool,
672677
) -> EmitterWriter {
673678
let dst = Destination::from_stderr(color_config);
674679
EmitterWriter {
@@ -681,6 +686,7 @@ impl EmitterWriter {
681686
ui_testing: false,
682687
diagnostic_width,
683688
macro_backtrace,
689+
track_diagnostics,
684690
}
685691
}
686692

@@ -694,6 +700,7 @@ impl EmitterWriter {
694700
colored: bool,
695701
diagnostic_width: Option<usize>,
696702
macro_backtrace: bool,
703+
track_diagnostics: bool,
697704
) -> EmitterWriter {
698705
EmitterWriter {
699706
dst: Raw(dst, colored),
@@ -705,6 +712,7 @@ impl EmitterWriter {
705712
ui_testing: false,
706713
diagnostic_width,
707714
macro_backtrace,
715+
track_diagnostics,
708716
}
709717
}
710718

@@ -1327,6 +1335,7 @@ impl EmitterWriter {
13271335
level: &Level,
13281336
max_line_num_len: usize,
13291337
is_secondary: bool,
1338+
emitted_at: Option<&DiagnosticLocation>,
13301339
) -> io::Result<()> {
13311340
let mut buffer = StyledBuffer::new();
13321341

@@ -1377,7 +1386,6 @@ impl EmitterWriter {
13771386
}
13781387
}
13791388
}
1380-
13811389
let mut annotated_files = FileWithAnnotatedLines::collect_annotations(self, args, msp);
13821390

13831391
// Make sure our primary file comes first
@@ -1653,6 +1661,12 @@ impl EmitterWriter {
16531661
}
16541662
}
16551663

1664+
if let Some(tracked) = emitted_at {
1665+
let track = format!("-Ztrack-diagnostics: created at {tracked}");
1666+
let len = buffer.num_lines();
1667+
buffer.append(len, &track, Style::NoStyle);
1668+
}
1669+
16561670
// final step: take our styled buffer, render it, then output it
16571671
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
16581672

@@ -1977,6 +1991,7 @@ impl EmitterWriter {
19771991
span: &MultiSpan,
19781992
children: &[SubDiagnostic],
19791993
suggestions: &[CodeSuggestion],
1994+
emitted_at: Option<&DiagnosticLocation>,
19801995
) {
19811996
let max_line_num_len = if self.ui_testing {
19821997
ANONYMIZED_LINE_NUM.len()
@@ -1985,7 +2000,16 @@ impl EmitterWriter {
19852000
num_decimal_digits(n)
19862001
};
19872002

1988-
match self.emit_message_default(span, message, args, code, level, max_line_num_len, false) {
2003+
match self.emit_message_default(
2004+
span,
2005+
message,
2006+
args,
2007+
code,
2008+
level,
2009+
max_line_num_len,
2010+
false,
2011+
emitted_at,
2012+
) {
19892013
Ok(()) => {
19902014
if !children.is_empty()
19912015
|| suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden)
@@ -2014,6 +2038,7 @@ impl EmitterWriter {
20142038
&child.level,
20152039
max_line_num_len,
20162040
true,
2041+
None,
20172042
) {
20182043
panic!("failed to emit error: {}", err);
20192044
}
@@ -2030,6 +2055,7 @@ impl EmitterWriter {
20302055
&Level::Help,
20312056
max_line_num_len,
20322057
true,
2058+
None,
20332059
) {
20342060
panic!("failed to emit error: {}", e);
20352061
}

compiler/rustc_errors/src/json.rs

+8
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub struct JsonEmitter {
4545
json_rendered: HumanReadableErrorType,
4646
diagnostic_width: Option<usize>,
4747
macro_backtrace: bool,
48+
track_diagnostics: bool,
4849
}
4950

5051
impl JsonEmitter {
@@ -57,6 +58,7 @@ impl JsonEmitter {
5758
json_rendered: HumanReadableErrorType,
5859
diagnostic_width: Option<usize>,
5960
macro_backtrace: bool,
61+
track_diagnostics: bool,
6062
) -> JsonEmitter {
6163
JsonEmitter {
6264
dst: Box::new(io::BufWriter::new(io::stderr())),
@@ -69,6 +71,7 @@ impl JsonEmitter {
6971
json_rendered,
7072
diagnostic_width,
7173
macro_backtrace,
74+
track_diagnostics,
7275
}
7376
}
7477

@@ -79,6 +82,7 @@ impl JsonEmitter {
7982
fallback_bundle: LazyFallbackBundle,
8083
diagnostic_width: Option<usize>,
8184
macro_backtrace: bool,
85+
track_diagnostics: bool,
8286
) -> JsonEmitter {
8387
let file_path_mapping = FilePathMapping::empty();
8488
JsonEmitter::stderr(
@@ -90,6 +94,7 @@ impl JsonEmitter {
9094
json_rendered,
9195
diagnostic_width,
9296
macro_backtrace,
97+
track_diagnostics,
9398
)
9499
}
95100

@@ -103,6 +108,7 @@ impl JsonEmitter {
103108
json_rendered: HumanReadableErrorType,
104109
diagnostic_width: Option<usize>,
105110
macro_backtrace: bool,
111+
track_diagnostics: bool,
106112
) -> JsonEmitter {
107113
JsonEmitter {
108114
dst,
@@ -115,6 +121,7 @@ impl JsonEmitter {
115121
json_rendered,
116122
diagnostic_width,
117123
macro_backtrace,
124+
track_diagnostics,
118125
}
119126
}
120127

@@ -350,6 +357,7 @@ impl Diagnostic {
350357
false,
351358
je.diagnostic_width,
352359
je.macro_backtrace,
360+
je.track_diagnostics,
353361
)
354362
.ui_testing(je.ui_testing)
355363
.emit_diagnostic(diag);

compiler/rustc_errors/src/json/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
5959
HumanReadableErrorType::Short(ColorConfig::Never),
6060
None,
6161
false,
62+
false,
6263
);
6364

6465
let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));

0 commit comments

Comments
 (0)