1
Fork 0

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
```
This commit is contained in:
bors 2022-11-01 21:09:45 +00:00
commit 11ebe6512b
42 changed files with 385 additions and 8 deletions

View file

@ -794,6 +794,7 @@ impl UnstableOptions {
report_delayed_bugs: self.report_delayed_bugs,
macro_backtrace: self.macro_backtrace,
deduplicate_diagnostics: self.deduplicate_diagnostics,
track_diagnostics: self.track_diagnostics,
}
}
}

View file

@ -1587,6 +1587,8 @@ options! {
"choose the TLS model to use (`rustc --print tls-models` for details)"),
trace_macros: bool = (false, parse_bool, [UNTRACKED],
"for every macro invocation, print its name and arguments (default: no)"),
track_diagnostics: bool = (false, parse_bool, [UNTRACKED],
"tracks where in rustc a diagnostic was emitted"),
// Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved
// alongside query results and changes to translation options can affect diagnostics - so
// translation options should be tracked.

View file

@ -97,6 +97,7 @@ pub fn feature_err<'a>(
///
/// This variant allows you to control whether it is a library or language feature.
/// Almost always, you want to use this for a language feature. If so, prefer `feature_err`.
#[track_caller]
pub fn feature_err_issue<'a>(
sess: &'a ParseSess,
feature: Symbol,
@ -332,6 +333,7 @@ impl ParseSess {
self.proc_macro_quoted_spans.lock().clone()
}
#[track_caller]
pub fn create_err<'a>(
&'a self,
err: impl IntoDiagnostic<'a>,
@ -339,10 +341,12 @@ impl ParseSess {
err.into_diagnostic(&self.span_diagnostic)
}
#[track_caller]
pub fn emit_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed {
self.create_err(err).emit()
}
#[track_caller]
pub fn create_warning<'a>(
&'a self,
warning: impl IntoDiagnostic<'a, ()>,
@ -350,6 +354,7 @@ impl ParseSess {
warning.into_diagnostic(&self.span_diagnostic)
}
#[track_caller]
pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) {
self.create_warning(warning).emit()
}
@ -377,6 +382,7 @@ impl ParseSess {
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_err(
&self,
msg: impl Into<DiagnosticMessage>,

View file

@ -286,6 +286,7 @@ impl Session {
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_span_warn<S: Into<MultiSpan>>(
&self,
sp: S,
@ -294,6 +295,7 @@ impl Session {
self.diagnostic().struct_span_warn(sp, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_span_warn_with_expectation<S: Into<MultiSpan>>(
&self,
sp: S,
@ -303,6 +305,7 @@ impl Session {
self.diagnostic().struct_span_warn_with_expectation(sp, msg, id)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@ -312,10 +315,12 @@ impl Session {
self.diagnostic().struct_span_warn_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_warn(msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_warn_with_expectation(
&self,
msg: impl Into<DiagnosticMessage>,
@ -324,6 +329,7 @@ impl Session {
self.diagnostic().struct_warn_with_expectation(msg, id)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_span_allow<S: Into<MultiSpan>>(
&self,
sp: S,
@ -332,10 +338,12 @@ impl Session {
self.diagnostic().struct_span_allow(sp, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_allow(msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_expect(
&self,
msg: impl Into<DiagnosticMessage>,
@ -344,6 +352,7 @@ impl Session {
self.diagnostic().struct_expect(msg, id)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@ -352,6 +361,7 @@ impl Session {
self.diagnostic().struct_span_err(sp, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@ -362,12 +372,14 @@ impl Session {
}
// FIXME: This method should be removed (every error should have an associated error code).
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_err(
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
self.parse_sess.struct_err(msg)
}
#[track_caller]
#[rustc_lint_diagnostics]
pub fn struct_err_with_code(
&self,
@ -377,6 +389,7 @@ impl Session {
self.diagnostic().struct_err_with_code(msg, code)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_warn_with_code(
&self,
msg: impl Into<DiagnosticMessage>,
@ -385,6 +398,7 @@ impl Session {
self.diagnostic().struct_warn_with_code(msg, code)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_span_fatal<S: Into<MultiSpan>>(
&self,
sp: S,
@ -407,6 +421,7 @@ impl Session {
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
self.diagnostic().span_fatal(sp, msg)
}
@ -424,6 +439,7 @@ impl Session {
self.diagnostic().fatal(msg).raise()
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn span_err_or_warn<S: Into<MultiSpan>>(
&self,
is_warning: bool,
@ -437,6 +453,7 @@ impl Session {
}
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@ -457,12 +474,14 @@ impl Session {
pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
self.diagnostic().err(msg)
}
#[track_caller]
pub fn create_err<'a>(
&'a self,
err: impl IntoDiagnostic<'a>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
self.parse_sess.create_err(err)
}
#[track_caller]
pub fn create_feature_err<'a>(
&'a self,
err: impl IntoDiagnostic<'a>,
@ -475,33 +494,40 @@ impl Session {
add_feature_diagnostics(&mut err, &self.parse_sess, feature);
err
}
#[track_caller]
pub fn emit_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed {
self.parse_sess.emit_err(err)
}
#[track_caller]
pub fn create_warning<'a>(
&'a self,
err: impl IntoDiagnostic<'a, ()>,
) -> DiagnosticBuilder<'a, ()> {
self.parse_sess.create_warning(err)
}
#[track_caller]
pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) {
self.parse_sess.emit_warning(warning)
}
#[track_caller]
pub fn create_note<'a>(
&'a self,
note: impl IntoDiagnostic<'a, Noted>,
) -> DiagnosticBuilder<'a, Noted> {
self.parse_sess.create_note(note)
}
#[track_caller]
pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted {
self.parse_sess.emit_note(note)
}
#[track_caller]
pub fn create_fatal<'a>(
&'a self,
fatal: impl IntoDiagnostic<'a, !>,
) -> DiagnosticBuilder<'a, !> {
self.parse_sess.create_fatal(fatal)
}
#[track_caller]
pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! {
self.parse_sess.emit_fatal(fatal)
}
@ -541,6 +567,7 @@ impl Session {
}
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
#[track_caller]
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
self.diagnostic().span_warn(sp, msg)
}
@ -587,6 +614,8 @@ impl Session {
pub fn note_without_error(&self, msg: impl Into<DiagnosticMessage>) {
self.diagnostic().note_without_error(msg)
}
#[track_caller]
pub fn span_note_without_error<S: Into<MultiSpan>>(
&self,
sp: S,
@ -1213,6 +1242,7 @@ fn default_emitter(
fallback_bundle: LazyFallbackBundle,
) -> Box<dyn Emitter + sync::Send> {
let macro_backtrace = sopts.unstable_opts.macro_backtrace;
let track_diagnostics = sopts.unstable_opts.track_diagnostics;
match sopts.error_format {
config::ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip();
@ -1236,6 +1266,7 @@ fn default_emitter(
sopts.unstable_opts.teach,
sopts.diagnostic_width,
macro_backtrace,
track_diagnostics,
);
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
}
@ -1250,6 +1281,7 @@ fn default_emitter(
json_rendered,
sopts.diagnostic_width,
macro_backtrace,
track_diagnostics,
)
.ui_testing(sopts.unstable_opts.ui_testing),
),
@ -1552,11 +1584,18 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
false,
None,
false,
false,
))
}
config::ErrorOutputType::Json { pretty, json_rendered } => {
Box::new(JsonEmitter::basic(pretty, json_rendered, None, fallback_bundle, None, false))
}
config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::basic(
pretty,
json_rendered,
None,
fallback_bundle,
None,
false,
false,
)),
};
rustc_errors::Handler::with_emitter(true, None, emitter)
}