@@ -78,6 +78,7 @@ use std::fmt;
78
78
use std::hash::Hash;
79
79
use std::io::Write;
80
80
use std::num::NonZeroUsize;
81
+ use std::ops::DerefMut;
81
82
use std::panic;
82
83
use std::path::{Path, PathBuf};
83
84
@@ -666,22 +667,51 @@ impl DiagCtxt {
666
667
/// tools that want to reuse a `Parser` cleaning the previously emitted diagnostics as well as
667
668
/// the overall count of emitted error diagnostics.
668
669
pub fn reset_err_count(&self) {
670
+ // Use destructuring so that if a field gets added to `DiagCtxtInner`, it's impossible to
671
+ // fail to update this method as well.
669
672
let mut inner = self.inner.borrow_mut();
670
- inner.stashed_err_count = 0;
671
- inner.deduplicated_err_count = 0;
672
- inner.deduplicated_warn_count = 0;
673
- inner.must_produce_diag = false;
674
- inner.has_printed = false;
675
- inner.suppressed_expected_diag = false;
676
-
677
- // actually free the underlying memory (which `clear` would not do)
678
- inner.err_guars = Default::default();
679
- inner.lint_err_guars = Default::default();
680
- inner.delayed_bugs = Default::default();
681
- inner.taught_diagnostics = Default::default();
682
- inner.emitted_diagnostic_codes = Default::default();
683
- inner.emitted_diagnostics = Default::default();
684
- inner.stashed_diagnostics = Default::default();
673
+ let DiagCtxtInner {
674
+ flags: _,
675
+ err_guars,
676
+ lint_err_guars,
677
+ delayed_bugs,
678
+ stashed_err_count,
679
+ deduplicated_err_count,
680
+ deduplicated_warn_count,
681
+ emitter: _,
682
+ must_produce_diag,
683
+ has_printed,
684
+ suppressed_expected_diag,
685
+ taught_diagnostics,
686
+ emitted_diagnostic_codes,
687
+ emitted_diagnostics,
688
+ stashed_diagnostics,
689
+ future_breakage_diagnostics,
690
+ check_unstable_expect_diagnostics,
691
+ unstable_expect_diagnostics,
692
+ fulfilled_expectations,
693
+ ice_file: _,
694
+ } = inner.deref_mut();
695
+
696
+ // For the `Vec`s and `HashMap`s, we overwrite with an empty container to free the
697
+ // underlying memory (which `clear` would not do).
698
+ *err_guars = Default::default();
699
+ *lint_err_guars = Default::default();
700
+ *delayed_bugs = Default::default();
701
+ *stashed_err_count = 0;
702
+ *deduplicated_err_count = 0;
703
+ *deduplicated_warn_count = 0;
704
+ *must_produce_diag = false;
705
+ *has_printed = false;
706
+ *suppressed_expected_diag = false;
707
+ *taught_diagnostics = Default::default();
708
+ *emitted_diagnostic_codes = Default::default();
709
+ *emitted_diagnostics = Default::default();
710
+ *stashed_diagnostics = Default::default();
711
+ *future_breakage_diagnostics = Default::default();
712
+ *check_unstable_expect_diagnostics = false;
713
+ *unstable_expect_diagnostics = Default::default();
714
+ *fulfilled_expectations = Default::default();
685
715
}
686
716
687
717
/// Stash a given diagnostic with the given `Span` and [`StashKey`] as the key.
@@ -780,11 +810,12 @@ impl DiagCtxt {
780
810
match (errors.len(), warnings.len()) {
781
811
(0, 0) => return,
782
812
(0, _) => {
783
- // Use `inner.emitter` directly, otherwise the warning might not be emitted, e.g.
784
- // with a configuration like `--cap-lints allow --force-warn bare_trait_objects`.
785
- inner
786
- .emitter
787
- .emit_diagnostic(Diagnostic::new(Warning, DiagnosticMessage::Str(warnings)));
813
+ // Use `ForceWarning` rather than `Warning` to guarantee emission, e.g. with a
814
+ // configuration like `--cap-lints allow --force-warn bare_trait_objects`.
815
+ inner.emit_diagnostic(Diagnostic::new(
816
+ ForceWarning(None),
817
+ DiagnosticMessage::Str(warnings),
818
+ ));
788
819
}
789
820
(_, 0) => {
790
821
inner.emit_diagnostic(Diagnostic::new(Error, errors));
@@ -812,20 +843,23 @@ impl DiagCtxt {
812
843
error_codes.sort();
813
844
if error_codes.len() > 1 {
814
845
let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
815
- inner.failure_note( format!(
846
+ let msg1 = format!(
816
847
"Some errors have detailed explanations: {}{}",
817
848
error_codes[..limit].join(", "),
818
849
if error_codes.len() > 9 { "..." } else { "." }
819
- )) ;
820
- inner.failure_note( format!(
850
+ );
851
+ let msg2 = format!(
821
852
"For more information about an error, try `rustc --explain {}`.",
822
853
&error_codes[0]
823
- ));
854
+ );
855
+ inner.emit_diagnostic(Diagnostic::new(FailureNote, msg1));
856
+ inner.emit_diagnostic(Diagnostic::new(FailureNote, msg2));
824
857
} else {
825
- inner.failure_note( format!(
858
+ let msg = format!(
826
859
"For more information about this error, try `rustc --explain {}`.",
827
860
&error_codes[0]
828
- ));
861
+ );
862
+ inner.emit_diagnostic(Diagnostic::new(FailureNote, msg));
829
863
}
830
864
}
831
865
}
@@ -848,10 +882,6 @@ impl DiagCtxt {
848
882
self.inner.borrow_mut().taught_diagnostics.insert(code)
849
883
}
850
884
851
- pub fn force_print_diagnostic(&self, db: Diagnostic) {
852
- self.inner.borrow_mut().emitter.emit_diagnostic(db);
853
- }
854
-
855
885
pub fn emit_diagnostic(&self, diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
856
886
self.inner.borrow_mut().emit_diagnostic(diagnostic)
857
887
}
@@ -1179,7 +1209,7 @@ impl DiagCtxt {
1179
1209
span: impl Into<MultiSpan>,
1180
1210
msg: impl Into<DiagnosticMessage>,
1181
1211
) -> DiagnosticBuilder<'_, ()> {
1182
- DiagnosticBuilder::new( self, Note, msg).with_span(span)
1212
+ self.struct_note( msg).with_span(span)
1183
1213
}
1184
1214
1185
1215
#[rustc_lint_diagnostics]
@@ -1207,6 +1237,15 @@ impl DiagCtxt {
1207
1237
DiagnosticBuilder::new(self, Help, msg)
1208
1238
}
1209
1239
1240
+ #[rustc_lint_diagnostics]
1241
+ #[track_caller]
1242
+ pub fn struct_failure_note(
1243
+ &self,
1244
+ msg: impl Into<DiagnosticMessage>,
1245
+ ) -> DiagnosticBuilder<'_, ()> {
1246
+ DiagnosticBuilder::new(self, FailureNote, msg)
1247
+ }
1248
+
1210
1249
#[rustc_lint_diagnostics]
1211
1250
#[track_caller]
1212
1251
pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
@@ -1406,10 +1445,6 @@ impl DiagCtxtInner {
1406
1445
.or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
1407
1446
}
1408
1447
1409
- fn failure_note(&mut self, msg: impl Into<DiagnosticMessage>) {
1410
- self.emit_diagnostic(Diagnostic::new(FailureNote, msg));
1411
- }
1412
-
1413
1448
fn flush_delayed(&mut self) {
1414
1449
if self.delayed_bugs.is_empty() {
1415
1450
return;
0 commit comments