1#![allow(internal_features)]
7#![allow(rustc::direct_use_of_rustc_type_ir)]
8#![feature(assert_matches)]
9#![feature(associated_type_defaults)]
10#![feature(box_patterns)]
11#![feature(default_field_values)]
12#![feature(error_reporter)]
13#![feature(macro_metavar_expr_concat)]
14#![feature(negative_impls)]
15#![feature(never_type)]
16#![feature(rustc_attrs)]
17#![feature(try_blocks)]
18#![feature(yeet_expr)]
19extern crate self as rustc_errors;
22
23use std::backtrace::{Backtrace, BacktraceStatus};
24use std::borrow::Cow;
25use std::cell::Cell;
26use std::error::Report;
27use std::ffi::OsStr;
28use std::hash::Hash;
29use std::io::Write;
30use std::num::NonZero;
31use std::ops::DerefMut;
32use std::path::{Path, PathBuf};
33use std::{fmt, panic};
34
35use Level::*;
36pub use anstream::{AutoStream, ColorChoice};
39pub use anstyle::{
40 Ansi256Color, AnsiColor, Color, EffectIter, Effects, Reset, RgbColor, Style as Anstyle,
41};
42pub use codes::*;
43pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer};
44pub use diagnostic::{
45 BugAbort, Diag, DiagArgMap, DiagInner, DiagStyledString, Diagnostic, EmissionGuarantee,
46 FatalAbort, LintDiagnostic, LintDiagnosticBox, StringPart, Subdiag, Subdiagnostic,
47};
48pub use diagnostic_impls::{
49 DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,
50 IndicateAnonymousLifetime, SingleLabelManySpans,
51};
52pub use emitter::ColorConfig;
53use emitter::{DynEmitter, Emitter};
54use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
55use rustc_data_structures::stable_hasher::StableHasher;
56use rustc_data_structures::sync::{DynSend, Lock};
57use rustc_data_structures::{AtomicRef, assert_matches};
58pub use rustc_error_messages::{
59 DiagArg, DiagArgFromDisplay, DiagArgName, DiagArgValue, DiagMessage, FluentBundle, IntoDiagArg,
60 LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage,
61 fallback_fluent_bundle, fluent_bundle, into_diag_arg_using_display,
62};
63use rustc_hashes::Hash128;
64use rustc_lint_defs::LintExpectationId;
65pub use rustc_lint_defs::{Applicability, listify, pluralize};
66use rustc_macros::{Decodable, Encodable};
67pub use rustc_span::ErrorGuaranteed;
68pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors};
69use rustc_span::source_map::SourceMap;
70use rustc_span::{DUMMY_SP, Span};
71use tracing::debug;
72
73use crate::emitter::TimingEvent;
74use crate::timings::TimingRecord;
75
76pub mod annotate_snippet_emitter_writer;
77pub mod codes;
78mod decorate_diag;
79mod diagnostic;
80mod diagnostic_impls;
81pub mod emitter;
82pub mod error;
83pub mod json;
84mod lock;
85pub mod markdown;
86pub mod timings;
87pub mod translation;
88
89pub type PResult<'a, T> = Result<T, Diag<'a>>;
90
91#[cfg(target_pointer_width = "64")]
93const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, ()>>()];rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24);
94#[cfg(target_pointer_width = "64")]
95const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, bool>>()];rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
96
97#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SuggestionStyle {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
SuggestionStyle::HideCodeInline => "HideCodeInline",
SuggestionStyle::HideCodeAlways => "HideCodeAlways",
SuggestionStyle::CompletelyHidden => "CompletelyHidden",
SuggestionStyle::ShowCode => "ShowCode",
SuggestionStyle::ShowAlways => "ShowAlways",
})
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for SuggestionStyle {
#[inline]
fn eq(&self, other: &SuggestionStyle) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SuggestionStyle {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::clone::Clone for SuggestionStyle {
#[inline]
fn clone(&self) -> SuggestionStyle { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for SuggestionStyle { }Copy, #[automatically_derived]
impl ::core::hash::Hash for SuggestionStyle {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for SuggestionStyle {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
SuggestionStyle::HideCodeInline => { 0usize }
SuggestionStyle::HideCodeAlways => { 1usize }
SuggestionStyle::CompletelyHidden => { 2usize }
SuggestionStyle::ShowCode => { 3usize }
SuggestionStyle::ShowAlways => { 4usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
SuggestionStyle::HideCodeInline => {}
SuggestionStyle::HideCodeAlways => {}
SuggestionStyle::CompletelyHidden => {}
SuggestionStyle::ShowCode => {}
SuggestionStyle::ShowAlways => {}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for SuggestionStyle {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { SuggestionStyle::HideCodeInline }
1usize => { SuggestionStyle::HideCodeAlways }
2usize => { SuggestionStyle::CompletelyHidden }
3usize => { SuggestionStyle::ShowCode }
4usize => { SuggestionStyle::ShowAlways }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `SuggestionStyle`, expected 0..5, actual {0}",
n));
}
}
}
}
};Decodable)]
98pub enum SuggestionStyle {
99 HideCodeInline,
101 HideCodeAlways,
103 CompletelyHidden,
105 ShowCode,
109 ShowAlways,
111}
112
113impl SuggestionStyle {
114 fn hide_inline(&self) -> bool {
115 !#[allow(non_exhaustive_omitted_patterns)] match *self {
SuggestionStyle::ShowCode => true,
_ => false,
}matches!(*self, SuggestionStyle::ShowCode)
116 }
117}
118
119#[derive(#[automatically_derived]
impl ::core::clone::Clone for Suggestions {
#[inline]
fn clone(&self) -> Suggestions {
match self {
Suggestions::Enabled(__self_0) =>
Suggestions::Enabled(::core::clone::Clone::clone(__self_0)),
Suggestions::Sealed(__self_0) =>
Suggestions::Sealed(::core::clone::Clone::clone(__self_0)),
Suggestions::Disabled => Suggestions::Disabled,
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Suggestions {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Suggestions::Enabled(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Enabled", &__self_0),
Suggestions::Sealed(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Sealed",
&__self_0),
Suggestions::Disabled =>
::core::fmt::Formatter::write_str(f, "Disabled"),
}
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Suggestions {
#[inline]
fn eq(&self, other: &Suggestions) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Suggestions::Enabled(__self_0),
Suggestions::Enabled(__arg1_0)) => __self_0 == __arg1_0,
(Suggestions::Sealed(__self_0), Suggestions::Sealed(__arg1_0))
=> __self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for Suggestions {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
Suggestions::Enabled(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Suggestions::Sealed(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
_ => {}
}
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Suggestions {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
Suggestions::Enabled(ref __binding_0) => { 0usize }
Suggestions::Sealed(ref __binding_0) => { 1usize }
Suggestions::Disabled => { 2usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
Suggestions::Enabled(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
Suggestions::Sealed(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
Suggestions::Disabled => {}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Suggestions {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => {
Suggestions::Enabled(::rustc_serialize::Decodable::decode(__decoder))
}
1usize => {
Suggestions::Sealed(::rustc_serialize::Decodable::decode(__decoder))
}
2usize => { Suggestions::Disabled }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Suggestions`, expected 0..3, actual {0}",
n));
}
}
}
}
};Decodable)]
121pub enum Suggestions {
122 Enabled(Vec<CodeSuggestion>),
127 Sealed(Box<[CodeSuggestion]>),
131 Disabled,
135}
136
137impl Suggestions {
138 pub fn unwrap_tag(self) -> Vec<CodeSuggestion> {
140 match self {
141 Suggestions::Enabled(suggestions) => suggestions,
142 Suggestions::Sealed(suggestions) => suggestions.into_vec(),
143 Suggestions::Disabled => Vec::new(),
144 }
145 }
146}
147
148impl Default for Suggestions {
149 fn default() -> Self {
150 Self::Enabled(::alloc::vec::Vec::new()vec![])
151 }
152}
153
154#[derive(#[automatically_derived]
impl ::core::clone::Clone for CodeSuggestion {
#[inline]
fn clone(&self) -> CodeSuggestion {
CodeSuggestion {
substitutions: ::core::clone::Clone::clone(&self.substitutions),
msg: ::core::clone::Clone::clone(&self.msg),
style: ::core::clone::Clone::clone(&self.style),
applicability: ::core::clone::Clone::clone(&self.applicability),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for CodeSuggestion {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"CodeSuggestion", "substitutions", &self.substitutions, "msg",
&self.msg, "style", &self.style, "applicability",
&&self.applicability)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for CodeSuggestion {
#[inline]
fn eq(&self, other: &CodeSuggestion) -> bool {
self.substitutions == other.substitutions && self.msg == other.msg &&
self.style == other.style &&
self.applicability == other.applicability
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for CodeSuggestion {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.substitutions, state);
::core::hash::Hash::hash(&self.msg, state);
::core::hash::Hash::hash(&self.style, state);
::core::hash::Hash::hash(&self.applicability, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for CodeSuggestion {
fn encode(&self, __encoder: &mut __E) {
match *self {
CodeSuggestion {
substitutions: ref __binding_0,
msg: ref __binding_1,
style: ref __binding_2,
applicability: ref __binding_3 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_2,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_3,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for CodeSuggestion {
fn decode(__decoder: &mut __D) -> Self {
CodeSuggestion {
substitutions: ::rustc_serialize::Decodable::decode(__decoder),
msg: ::rustc_serialize::Decodable::decode(__decoder),
style: ::rustc_serialize::Decodable::decode(__decoder),
applicability: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
155pub struct CodeSuggestion {
156 pub substitutions: Vec<Substitution>,
178 pub msg: DiagMessage,
179 pub style: SuggestionStyle,
181 pub applicability: Applicability,
187}
188
189#[derive(#[automatically_derived]
impl ::core::clone::Clone for Substitution {
#[inline]
fn clone(&self) -> Substitution {
Substitution { parts: ::core::clone::Clone::clone(&self.parts) }
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Substitution {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "Substitution",
"parts", &&self.parts)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Substitution {
#[inline]
fn eq(&self, other: &Substitution) -> bool { self.parts == other.parts }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for Substitution {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.parts, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Substitution {
fn encode(&self, __encoder: &mut __E) {
match *self {
Substitution { parts: ref __binding_0 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Substitution {
fn decode(__decoder: &mut __D) -> Self {
Substitution {
parts: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
190pub struct Substitution {
192 pub parts: Vec<SubstitutionPart>,
193}
194
195#[derive(#[automatically_derived]
impl ::core::clone::Clone for SubstitutionPart {
#[inline]
fn clone(&self) -> SubstitutionPart {
SubstitutionPart {
span: ::core::clone::Clone::clone(&self.span),
snippet: ::core::clone::Clone::clone(&self.snippet),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for SubstitutionPart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"SubstitutionPart", "span", &self.span, "snippet", &&self.snippet)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for SubstitutionPart {
#[inline]
fn eq(&self, other: &SubstitutionPart) -> bool {
self.span == other.span && self.snippet == other.snippet
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for SubstitutionPart {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.span, state);
::core::hash::Hash::hash(&self.snippet, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for SubstitutionPart {
fn encode(&self, __encoder: &mut __E) {
match *self {
SubstitutionPart {
span: ref __binding_0, snippet: ref __binding_1 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for SubstitutionPart {
fn decode(__decoder: &mut __D) -> Self {
SubstitutionPart {
span: ::rustc_serialize::Decodable::decode(__decoder),
snippet: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
196pub struct SubstitutionPart {
197 pub span: Span,
198 pub snippet: String,
199}
200
201#[derive(#[automatically_derived]
impl ::core::clone::Clone for TrimmedSubstitutionPart {
#[inline]
fn clone(&self) -> TrimmedSubstitutionPart {
TrimmedSubstitutionPart {
original_span: ::core::clone::Clone::clone(&self.original_span),
span: ::core::clone::Clone::clone(&self.span),
snippet: ::core::clone::Clone::clone(&self.snippet),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for TrimmedSubstitutionPart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"TrimmedSubstitutionPart", "original_span", &self.original_span,
"span", &self.span, "snippet", &&self.snippet)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for TrimmedSubstitutionPart {
#[inline]
fn eq(&self, other: &TrimmedSubstitutionPart) -> bool {
self.original_span == other.original_span && self.span == other.span
&& self.snippet == other.snippet
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for TrimmedSubstitutionPart {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.original_span, state);
::core::hash::Hash::hash(&self.span, state);
::core::hash::Hash::hash(&self.snippet, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for TrimmedSubstitutionPart {
fn encode(&self, __encoder: &mut __E) {
match *self {
TrimmedSubstitutionPart {
original_span: ref __binding_0,
span: ref __binding_1,
snippet: ref __binding_2 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_2,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for TrimmedSubstitutionPart {
fn decode(__decoder: &mut __D) -> Self {
TrimmedSubstitutionPart {
original_span: ::rustc_serialize::Decodable::decode(__decoder),
span: ::rustc_serialize::Decodable::decode(__decoder),
snippet: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
202pub struct TrimmedSubstitutionPart {
203 pub original_span: Span,
204 pub span: Span,
205 pub snippet: String,
206}
207
208impl TrimmedSubstitutionPart {
209 pub fn is_addition(&self, sm: &SourceMap) -> bool {
210 !self.snippet.is_empty() && !self.replaces_meaningful_content(sm)
211 }
212
213 pub fn is_deletion(&self, sm: &SourceMap) -> bool {
214 self.snippet.trim().is_empty() && self.replaces_meaningful_content(sm)
215 }
216
217 pub fn is_replacement(&self, sm: &SourceMap) -> bool {
218 !self.snippet.is_empty() && self.replaces_meaningful_content(sm)
219 }
220
221 pub fn is_destructive_replacement(&self, sm: &SourceMap) -> bool {
226 self.is_replacement(sm)
227 && !sm
228 .span_to_snippet(self.span)
229 .is_ok_and(|snippet| as_substr(snippet.trim(), self.snippet.trim()).is_some())
230 }
231
232 fn replaces_meaningful_content(&self, sm: &SourceMap) -> bool {
233 sm.span_to_snippet(self.span)
234 .map_or(!self.span.is_empty(), |snippet| !snippet.trim().is_empty())
235 }
236}
237
238fn as_substr<'a>(original: &'a str, suggestion: &'a str) -> Option<(usize, &'a str, usize)> {
243 let common_prefix = original
244 .chars()
245 .zip(suggestion.chars())
246 .take_while(|(c1, c2)| c1 == c2)
247 .map(|(c, _)| c.len_utf8())
248 .sum();
249 let original = &original[common_prefix..];
250 let suggestion = &suggestion[common_prefix..];
251 if suggestion.ends_with(original) {
252 let common_suffix = original.len();
253 Some((common_prefix, &suggestion[..suggestion.len() - original.len()], common_suffix))
254 } else {
255 None
256 }
257}
258
259pub struct ExplicitBug;
262
263pub struct DelayedBugPanic;
266
267pub struct DiagCtxt {
271 inner: Lock<DiagCtxtInner>,
272}
273
274#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for DiagCtxtHandle<'a> { }Copy, #[automatically_derived]
impl<'a> ::core::clone::Clone for DiagCtxtHandle<'a> {
#[inline]
fn clone(&self) -> DiagCtxtHandle<'a> {
let _: ::core::clone::AssertParamIsClone<&'a DiagCtxt>;
let _:
::core::clone::AssertParamIsClone<Option<&'a Cell<Option<ErrorGuaranteed>>>>;
*self
}
}Clone)]
275pub struct DiagCtxtHandle<'a> {
276 dcx: &'a DiagCtxt,
277 tainted_with_errors: Option<&'a Cell<Option<ErrorGuaranteed>>>,
280}
281
282impl<'a> std::ops::Deref for DiagCtxtHandle<'a> {
283 type Target = &'a DiagCtxt;
284
285 fn deref(&self) -> &Self::Target {
286 &self.dcx
287 }
288}
289
290struct DiagCtxtInner {
294 flags: DiagCtxtFlags,
295
296 err_guars: Vec<ErrorGuaranteed>,
298 lint_err_guars: Vec<ErrorGuaranteed>,
301 delayed_bugs: Vec<(DelayedDiagInner, ErrorGuaranteed)>,
303
304 deduplicated_err_count: usize,
306 deduplicated_warn_count: usize,
308
309 emitter: Box<DynEmitter>,
310
311 must_produce_diag: Option<Backtrace>,
314
315 has_printed: bool,
318
319 suppressed_expected_diag: bool,
322
323 taught_diagnostics: FxHashSet<ErrCode>,
327
328 emitted_diagnostic_codes: FxIndexSet<ErrCode>,
330
331 emitted_diagnostics: FxHashSet<Hash128>,
335
336 stashed_diagnostics:
342 FxIndexMap<StashKey, FxIndexMap<Span, (DiagInner, Option<ErrorGuaranteed>)>>,
343
344 future_breakage_diagnostics: Vec<DiagInner>,
345
346 fulfilled_expectations: FxIndexSet<LintExpectationId>,
358
359 ice_file: Option<PathBuf>,
362}
363
364#[derive(#[automatically_derived]
impl ::core::marker::Copy for StashKey { }Copy, #[automatically_derived]
impl ::core::clone::Clone for StashKey {
#[inline]
fn clone(&self) -> StashKey { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for StashKey {
#[inline]
fn eq(&self, other: &StashKey) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for StashKey {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for StashKey {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for StashKey {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
StashKey::ItemNoType => "ItemNoType",
StashKey::UnderscoreForArrayLengths =>
"UnderscoreForArrayLengths",
StashKey::EarlySyntaxWarning => "EarlySyntaxWarning",
StashKey::CallIntoMethod => "CallIntoMethod",
StashKey::LifetimeIsChar => "LifetimeIsChar",
StashKey::MaybeFruTypo => "MaybeFruTypo",
StashKey::CallAssocMethod => "CallAssocMethod",
StashKey::AssociatedTypeSuggestion =>
"AssociatedTypeSuggestion",
StashKey::Cycle => "Cycle",
StashKey::UndeterminedMacroResolution =>
"UndeterminedMacroResolution",
StashKey::ExprInPat => "ExprInPat",
StashKey::GenericInFieldExpr => "GenericInFieldExpr",
})
}
}Debug)]
366pub enum StashKey {
367 ItemNoType,
368 UnderscoreForArrayLengths,
369 EarlySyntaxWarning,
370 CallIntoMethod,
371 LifetimeIsChar,
374 MaybeFruTypo,
377 CallAssocMethod,
378 AssociatedTypeSuggestion,
379 Cycle,
381 UndeterminedMacroResolution,
382 ExprInPat,
384 GenericInFieldExpr,
388}
389
390fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
391 (*f)(diag)
392}
393
394pub static TRACK_DIAGNOSTIC: AtomicRef<
397 fn(DiagInner, &mut dyn FnMut(DiagInner) -> Option<ErrorGuaranteed>) -> Option<ErrorGuaranteed>,
398> = AtomicRef::new(&(default_track_diagnostic as _));
399
400#[derive(#[automatically_derived]
impl ::core::marker::Copy for DiagCtxtFlags { }Copy, #[automatically_derived]
impl ::core::clone::Clone for DiagCtxtFlags {
#[inline]
fn clone(&self) -> DiagCtxtFlags {
let _: ::core::clone::AssertParamIsClone<bool>;
let _: ::core::clone::AssertParamIsClone<Option<NonZero<usize>>>;
*self
}
}Clone, #[automatically_derived]
impl ::core::default::Default for DiagCtxtFlags {
#[inline]
fn default() -> DiagCtxtFlags {
DiagCtxtFlags {
can_emit_warnings: ::core::default::Default::default(),
treat_err_as_bug: ::core::default::Default::default(),
eagerly_emit_delayed_bugs: ::core::default::Default::default(),
macro_backtrace: ::core::default::Default::default(),
deduplicate_diagnostics: ::core::default::Default::default(),
track_diagnostics: ::core::default::Default::default(),
}
}
}Default)]
401pub struct DiagCtxtFlags {
402 pub can_emit_warnings: bool,
405 pub treat_err_as_bug: Option<NonZero<usize>>,
408 pub eagerly_emit_delayed_bugs: bool,
411 pub macro_backtrace: bool,
414 pub deduplicate_diagnostics: bool,
416 pub track_diagnostics: bool,
418}
419
420impl Drop for DiagCtxtInner {
421 fn drop(&mut self) {
422 self.emit_stashed_diagnostics();
430
431 self.flush_delayed();
435
436 if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
440 if let Some(backtrace) = &self.must_produce_diag {
441 let suggestion = match backtrace.status() {
442 BacktraceStatus::Disabled => String::from(
443 "Backtraces are currently disabled: set `RUST_BACKTRACE=1` and re-run \
444 to see where it happened.",
445 ),
446 BacktraceStatus::Captured => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("This happened in the following `must_produce_diag` call\'s backtrace:\n{0}",
backtrace))
})format!(
447 "This happened in the following `must_produce_diag` call's backtrace:\n\
448 {backtrace}",
449 ),
450 _ => String::from("(impossible to capture backtrace where this happened)"),
451 };
452 {
::core::panicking::panic_fmt(format_args!("`trimmed_def_paths` called, diagnostics were expected but none were emitted. Use `with_no_trimmed_paths` for debugging. {0}",
suggestion));
};panic!(
453 "`trimmed_def_paths` called, diagnostics were expected but none were emitted. \
454 Use `with_no_trimmed_paths` for debugging. {suggestion}"
455 );
456 }
457 }
458 }
459}
460
461impl DiagCtxt {
462 pub fn disable_warnings(mut self) -> Self {
463 self.inner.get_mut().flags.can_emit_warnings = false;
464 self
465 }
466
467 pub fn with_flags(mut self, flags: DiagCtxtFlags) -> Self {
468 self.inner.get_mut().flags = flags;
469 self
470 }
471
472 pub fn with_ice_file(mut self, ice_file: PathBuf) -> Self {
473 self.inner.get_mut().ice_file = Some(ice_file);
474 self
475 }
476
477 pub fn new(emitter: Box<DynEmitter>) -> Self {
478 Self { inner: Lock::new(DiagCtxtInner::new(emitter)) }
479 }
480
481 pub fn make_silent(&self) {
482 let mut inner = self.inner.borrow_mut();
483 let translator = inner.emitter.translator().clone();
484 inner.emitter = Box::new(emitter::SilentEmitter { translator });
485 }
486
487 pub fn set_emitter(&self, emitter: Box<dyn Emitter + DynSend>) {
488 self.inner.borrow_mut().emitter = emitter;
489 }
490
491 pub fn eagerly_translate<'a>(
493 &self,
494 message: DiagMessage,
495 args: impl Iterator<Item = DiagArg<'a>>,
496 ) -> SubdiagMessage {
497 let inner = self.inner.borrow();
498 inner.eagerly_translate(message, args)
499 }
500
501 pub fn eagerly_translate_to_string<'a>(
503 &self,
504 message: DiagMessage,
505 args: impl Iterator<Item = DiagArg<'a>>,
506 ) -> String {
507 let inner = self.inner.borrow();
508 inner.eagerly_translate_to_string(message, args)
509 }
510
511 pub fn can_emit_warnings(&self) -> bool {
515 self.inner.borrow_mut().flags.can_emit_warnings
516 }
517
518 pub fn reset_err_count(&self) {
524 let mut inner = self.inner.borrow_mut();
527 let DiagCtxtInner {
528 flags: _,
529 err_guars,
530 lint_err_guars,
531 delayed_bugs,
532 deduplicated_err_count,
533 deduplicated_warn_count,
534 emitter: _,
535 must_produce_diag,
536 has_printed,
537 suppressed_expected_diag,
538 taught_diagnostics,
539 emitted_diagnostic_codes,
540 emitted_diagnostics,
541 stashed_diagnostics,
542 future_breakage_diagnostics,
543 fulfilled_expectations,
544 ice_file: _,
545 } = inner.deref_mut();
546
547 *err_guars = Default::default();
550 *lint_err_guars = Default::default();
551 *delayed_bugs = Default::default();
552 *deduplicated_err_count = 0;
553 *deduplicated_warn_count = 0;
554 *must_produce_diag = None;
555 *has_printed = false;
556 *suppressed_expected_diag = false;
557 *taught_diagnostics = Default::default();
558 *emitted_diagnostic_codes = Default::default();
559 *emitted_diagnostics = Default::default();
560 *stashed_diagnostics = Default::default();
561 *future_breakage_diagnostics = Default::default();
562 *fulfilled_expectations = Default::default();
563 }
564
565 pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> {
566 DiagCtxtHandle { dcx: self, tainted_with_errors: None }
567 }
568
569 pub fn taintable_handle<'a>(
573 &'a self,
574 tainted_with_errors: &'a Cell<Option<ErrorGuaranteed>>,
575 ) -> DiagCtxtHandle<'a> {
576 DiagCtxtHandle { dcx: self, tainted_with_errors: Some(tainted_with_errors) }
577 }
578}
579
580impl<'a> DiagCtxtHandle<'a> {
581 pub fn stash_diagnostic(
603 &self,
604 span: Span,
605 key: StashKey,
606 diag: DiagInner,
607 ) -> Option<ErrorGuaranteed> {
608 let guar = match diag.level {
609 Bug | Fatal => {
610 self.span_bug(
611 span,
612 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid level in `stash_diagnostic`: {0:?}",
diag.level))
})format!("invalid level in `stash_diagnostic`: {:?}", diag.level),
613 );
614 }
615 Error => Some(self.span_delayed_bug(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("stashing {0:?}", key))
})format!("stashing {key:?}"))),
619 DelayedBug => {
620 return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors);
621 }
622 ForceWarning | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow
623 | Expect => None,
624 };
625
626 self.inner
630 .borrow_mut()
631 .stashed_diagnostics
632 .entry(key)
633 .or_default()
634 .insert(span.with_parent(None), (diag, guar));
635
636 guar
637 }
638
639 pub fn steal_non_err(self, span: Span, key: StashKey) -> Option<Diag<'a, ()>> {
643 let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
645 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
646 )?;
647 if !!diag.is_error() {
::core::panicking::panic("assertion failed: !diag.is_error()")
};assert!(!diag.is_error());
648 if !guar.is_none() {
::core::panicking::panic("assertion failed: guar.is_none()")
};assert!(guar.is_none());
649 Some(Diag::new_diagnostic(self, diag))
650 }
651
652 pub fn try_steal_modify_and_emit_err<F>(
657 self,
658 span: Span,
659 key: StashKey,
660 mut modify_err: F,
661 ) -> Option<ErrorGuaranteed>
662 where
663 F: FnMut(&mut Diag<'_>),
664 {
665 let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
667 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
668 );
669 err.map(|(err, guar)| {
670 match (&err.level, &Error) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(err.level, Error);
672 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
673 let mut err = Diag::<ErrorGuaranteed>::new_diagnostic(self, err);
674 modify_err(&mut err);
675 match (&err.level, &Error) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(err.level, Error);
676 err.emit()
677 })
678 }
679
680 pub fn try_steal_replace_and_emit_err(
684 self,
685 span: Span,
686 key: StashKey,
687 new_err: Diag<'_>,
688 ) -> ErrorGuaranteed {
689 let old_err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
691 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
692 );
693 match old_err {
694 Some((old_err, guar)) => {
695 match (&old_err.level, &Error) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(old_err.level, Error);
696 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
697 Diag::<ErrorGuaranteed>::new_diagnostic(self, old_err).cancel();
700 }
701 None => {}
702 };
703 new_err.emit()
704 }
705
706 pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool {
707 let inner = self.inner.borrow();
708 if let Some(stashed_diagnostics) = inner.stashed_diagnostics.get(&key)
709 && !stashed_diagnostics.is_empty()
710 {
711 stashed_diagnostics.contains_key(&span.with_parent(None))
712 } else {
713 false
714 }
715 }
716
717 pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
719 self.inner.borrow_mut().emit_stashed_diagnostics()
720 }
721
722 #[inline]
724 pub fn err_count(&self) -> usize {
725 let inner = self.inner.borrow();
726 inner.err_guars.len()
727 + inner.lint_err_guars.len()
728 + inner
729 .stashed_diagnostics
730 .values()
731 .map(|a| a.values().filter(|(_, guar)| guar.is_some()).count())
732 .sum::<usize>()
733 }
734
735 pub fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
738 self.inner.borrow().has_errors_excluding_lint_errors()
739 }
740
741 pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
743 self.inner.borrow().has_errors()
744 }
745
746 pub fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
749 self.inner.borrow().has_errors_or_delayed_bugs()
750 }
751
752 pub fn print_error_count(&self) {
753 let mut inner = self.inner.borrow_mut();
754
755 if !inner.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: inner.stashed_diagnostics.is_empty()")
};assert!(inner.stashed_diagnostics.is_empty());
758
759 if inner.treat_err_as_bug() {
760 return;
761 }
762
763 let warnings = match inner.deduplicated_warn_count {
764 0 => Cow::from(""),
765 1 => Cow::from("1 warning emitted"),
766 count => Cow::from(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} warnings emitted", count))
})format!("{count} warnings emitted")),
767 };
768 let errors = match inner.deduplicated_err_count {
769 0 => Cow::from(""),
770 1 => Cow::from("aborting due to 1 previous error"),
771 count => Cow::from(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("aborting due to {0} previous errors",
count))
})format!("aborting due to {count} previous errors")),
772 };
773
774 match (errors.len(), warnings.len()) {
775 (0, 0) => return,
776 (0, _) => {
777 inner.emit_diagnostic(
780 DiagInner::new(ForceWarning, DiagMessage::Str(warnings)),
781 None,
782 );
783 }
784 (_, 0) => {
785 inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors);
786 }
787 (_, _) => {
788 inner.emit_diagnostic(
789 DiagInner::new(Error, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}; {1}", errors, warnings))
})format!("{errors}; {warnings}")),
790 self.tainted_with_errors,
791 );
792 }
793 }
794
795 let can_show_explain = inner.emitter.should_show_explain();
796 let are_there_diagnostics = !inner.emitted_diagnostic_codes.is_empty();
797 if can_show_explain && are_there_diagnostics {
798 let mut error_codes = inner
799 .emitted_diagnostic_codes
800 .iter()
801 .filter_map(|&code| {
802 if crate::codes::try_find_description(code).is_ok() {
803 Some(code.to_string())
804 } else {
805 None
806 }
807 })
808 .collect::<Vec<_>>();
809 if !error_codes.is_empty() {
810 error_codes.sort();
811 if error_codes.len() > 1 {
812 let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
813 let msg1 = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Some errors have detailed explanations: {0}{1}",
error_codes[..limit].join(", "),
if error_codes.len() > 9 { "..." } else { "." }))
})format!(
814 "Some errors have detailed explanations: {}{}",
815 error_codes[..limit].join(", "),
816 if error_codes.len() > 9 { "..." } else { "." }
817 );
818 let msg2 = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("For more information about an error, try `rustc --explain {0}`.",
&error_codes[0]))
})format!(
819 "For more information about an error, try `rustc --explain {}`.",
820 &error_codes[0]
821 );
822 inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None);
823 inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None);
824 } else {
825 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("For more information about this error, try `rustc --explain {0}`.",
&error_codes[0]))
})format!(
826 "For more information about this error, try `rustc --explain {}`.",
827 &error_codes[0]
828 );
829 inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None);
830 }
831 }
832 }
833 }
834
835 pub fn abort_if_errors(&self) {
840 if let Some(guar) = self.has_errors() {
841 guar.raise_fatal();
842 }
843 }
844
845 pub fn must_teach(&self, code: ErrCode) -> bool {
851 self.inner.borrow_mut().taught_diagnostics.insert(code)
852 }
853
854 pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
855 self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors)
856 }
857
858 pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
859 self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type);
860 }
861
862 pub fn emit_timing_section_start(&self, record: TimingRecord) {
863 self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start);
864 }
865
866 pub fn emit_timing_section_end(&self, record: TimingRecord) {
867 self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::End);
868 }
869
870 pub fn emit_future_breakage_report(&self) {
871 let inner = &mut *self.inner.borrow_mut();
872 let diags = std::mem::take(&mut inner.future_breakage_diagnostics);
873 if !diags.is_empty() {
874 inner.emitter.emit_future_breakage_report(diags);
875 }
876 }
877
878 pub fn emit_unused_externs(
879 &self,
880 lint_level: rustc_lint_defs::Level,
881 loud: bool,
882 unused_externs: &[&str],
883 ) {
884 let mut inner = self.inner.borrow_mut();
885
886 if loud && lint_level.is_error() {
897 #[allow(deprecated)]
900 inner.lint_err_guars.push(ErrorGuaranteed::unchecked_error_guaranteed());
901 inner.panic_if_treat_err_as_bug();
902 }
903
904 inner.emitter.emit_unused_externs(lint_level, unused_externs)
905 }
906
907 #[must_use]
910 pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet<LintExpectationId> {
911 std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations)
912 }
913
914 pub fn flush_delayed(&self) {
919 self.inner.borrow_mut().flush_delayed();
920 }
921
922 #[track_caller]
925 pub fn set_must_produce_diag(&self) {
926 if !self.inner.borrow().must_produce_diag.is_none() {
{
::core::panicking::panic_fmt(format_args!("should only need to collect a backtrace once"));
}
};assert!(
927 self.inner.borrow().must_produce_diag.is_none(),
928 "should only need to collect a backtrace once"
929 );
930 self.inner.borrow_mut().must_produce_diag = Some(Backtrace::capture());
931 }
932}
933
934impl<'a> DiagCtxtHandle<'a> {
939 #[track_caller]
940 pub fn struct_bug(self, msg: impl Into<Cow<'static, str>>) -> Diag<'a, BugAbort> {
941 Diag::new(self, Bug, msg.into())
942 }
943
944 #[track_caller]
945 pub fn bug(self, msg: impl Into<Cow<'static, str>>) -> ! {
946 self.struct_bug(msg).emit()
947 }
948
949 #[track_caller]
950 pub fn struct_span_bug(
951 self,
952 span: impl Into<MultiSpan>,
953 msg: impl Into<Cow<'static, str>>,
954 ) -> Diag<'a, BugAbort> {
955 self.struct_bug(msg).with_span(span)
956 }
957
958 #[track_caller]
959 pub fn span_bug(self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! {
960 self.struct_span_bug(span, msg.into()).emit()
961 }
962
963 #[track_caller]
964 pub fn create_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> Diag<'a, BugAbort> {
965 bug.into_diag(self, Bug)
966 }
967
968 #[track_caller]
969 pub fn emit_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> ! {
970 self.create_bug(bug).emit()
971 }
972
973 #[track_caller]
974 pub fn struct_fatal(self, msg: impl Into<DiagMessage>) -> Diag<'a, FatalAbort> {
975 Diag::new(self, Fatal, msg)
976 }
977
978 #[track_caller]
979 pub fn fatal(self, msg: impl Into<DiagMessage>) -> ! {
980 self.struct_fatal(msg).emit()
981 }
982
983 #[track_caller]
984 pub fn struct_span_fatal(
985 self,
986 span: impl Into<MultiSpan>,
987 msg: impl Into<DiagMessage>,
988 ) -> Diag<'a, FatalAbort> {
989 self.struct_fatal(msg).with_span(span)
990 }
991
992 #[track_caller]
993 pub fn span_fatal(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) -> ! {
994 self.struct_span_fatal(span, msg).emit()
995 }
996
997 #[track_caller]
998 pub fn create_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> Diag<'a, FatalAbort> {
999 fatal.into_diag(self, Fatal)
1000 }
1001
1002 #[track_caller]
1003 pub fn emit_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> ! {
1004 self.create_fatal(fatal).emit()
1005 }
1006
1007 #[track_caller]
1008 pub fn create_almost_fatal(
1009 self,
1010 fatal: impl Diagnostic<'a, FatalError>,
1011 ) -> Diag<'a, FatalError> {
1012 fatal.into_diag(self, Fatal)
1013 }
1014
1015 #[track_caller]
1016 pub fn emit_almost_fatal(self, fatal: impl Diagnostic<'a, FatalError>) -> FatalError {
1017 self.create_almost_fatal(fatal).emit()
1018 }
1019
1020 #[track_caller]
1022 pub fn struct_err(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
1023 Diag::new(self, Error, msg)
1024 }
1025
1026 #[track_caller]
1027 pub fn err(self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed {
1028 self.struct_err(msg).emit()
1029 }
1030
1031 #[track_caller]
1032 pub fn struct_span_err(
1033 self,
1034 span: impl Into<MultiSpan>,
1035 msg: impl Into<DiagMessage>,
1036 ) -> Diag<'a> {
1037 self.struct_err(msg).with_span(span)
1038 }
1039
1040 #[track_caller]
1041 pub fn span_err(
1042 self,
1043 span: impl Into<MultiSpan>,
1044 msg: impl Into<DiagMessage>,
1045 ) -> ErrorGuaranteed {
1046 self.struct_span_err(span, msg).emit()
1047 }
1048
1049 #[track_caller]
1050 pub fn create_err(self, err: impl Diagnostic<'a>) -> Diag<'a> {
1051 err.into_diag(self, Error)
1052 }
1053
1054 #[track_caller]
1055 pub fn emit_err(self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
1056 self.create_err(err).emit()
1057 }
1058
1059 #[track_caller]
1061 pub fn delayed_bug(self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed {
1062 Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).emit()
1063 }
1064
1065 #[track_caller]
1070 pub fn span_delayed_bug(
1071 self,
1072 sp: impl Into<MultiSpan>,
1073 msg: impl Into<Cow<'static, str>>,
1074 ) -> ErrorGuaranteed {
1075 Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).with_span(sp).emit()
1076 }
1077
1078 #[track_caller]
1079 pub fn struct_warn(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1080 Diag::new(self, Warning, msg)
1081 }
1082
1083 #[track_caller]
1084 pub fn warn(self, msg: impl Into<DiagMessage>) {
1085 self.struct_warn(msg).emit()
1086 }
1087
1088 #[track_caller]
1089 pub fn struct_span_warn(
1090 self,
1091 span: impl Into<MultiSpan>,
1092 msg: impl Into<DiagMessage>,
1093 ) -> Diag<'a, ()> {
1094 self.struct_warn(msg).with_span(span)
1095 }
1096
1097 #[track_caller]
1098 pub fn span_warn(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1099 self.struct_span_warn(span, msg).emit()
1100 }
1101
1102 #[track_caller]
1103 pub fn create_warn(self, warning: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
1104 warning.into_diag(self, Warning)
1105 }
1106
1107 #[track_caller]
1108 pub fn emit_warn(self, warning: impl Diagnostic<'a, ()>) {
1109 self.create_warn(warning).emit()
1110 }
1111
1112 #[track_caller]
1113 pub fn struct_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1114 Diag::new(self, Note, msg)
1115 }
1116
1117 #[track_caller]
1118 pub fn note(&self, msg: impl Into<DiagMessage>) {
1119 self.struct_note(msg).emit()
1120 }
1121
1122 #[track_caller]
1123 pub fn struct_span_note(
1124 self,
1125 span: impl Into<MultiSpan>,
1126 msg: impl Into<DiagMessage>,
1127 ) -> Diag<'a, ()> {
1128 self.struct_note(msg).with_span(span)
1129 }
1130
1131 #[track_caller]
1132 pub fn span_note(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1133 self.struct_span_note(span, msg).emit()
1134 }
1135
1136 #[track_caller]
1137 pub fn create_note(self, note: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
1138 note.into_diag(self, Note)
1139 }
1140
1141 #[track_caller]
1142 pub fn emit_note(self, note: impl Diagnostic<'a, ()>) {
1143 self.create_note(note).emit()
1144 }
1145
1146 #[track_caller]
1147 pub fn struct_help(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1148 Diag::new(self, Help, msg)
1149 }
1150
1151 #[track_caller]
1152 pub fn struct_failure_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1153 Diag::new(self, FailureNote, msg)
1154 }
1155
1156 #[track_caller]
1157 pub fn struct_allow(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1158 Diag::new(self, Allow, msg)
1159 }
1160
1161 #[track_caller]
1162 pub fn struct_expect(self, msg: impl Into<DiagMessage>, id: LintExpectationId) -> Diag<'a, ()> {
1163 Diag::new(self, Expect, msg).with_lint_id(id)
1164 }
1165}
1166
1167impl DiagCtxtInner {
1172 fn new(emitter: Box<DynEmitter>) -> Self {
1173 Self {
1174 flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
1175 err_guars: Vec::new(),
1176 lint_err_guars: Vec::new(),
1177 delayed_bugs: Vec::new(),
1178 deduplicated_err_count: 0,
1179 deduplicated_warn_count: 0,
1180 emitter,
1181 must_produce_diag: None,
1182 has_printed: false,
1183 suppressed_expected_diag: false,
1184 taught_diagnostics: Default::default(),
1185 emitted_diagnostic_codes: Default::default(),
1186 emitted_diagnostics: Default::default(),
1187 stashed_diagnostics: Default::default(),
1188 future_breakage_diagnostics: Vec::new(),
1189 fulfilled_expectations: Default::default(),
1190 ice_file: None,
1191 }
1192 }
1193
1194 fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
1196 let mut guar = None;
1197 let has_errors = !self.err_guars.is_empty();
1198 for (_, stashed_diagnostics) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
1199 for (_, (diag, _guar)) in stashed_diagnostics {
1200 if !diag.is_error() {
1201 if !diag.is_force_warn() && has_errors {
1205 continue;
1206 }
1207 }
1208 guar = guar.or(self.emit_diagnostic(diag, None));
1209 }
1210 }
1211 guar
1212 }
1213
1214 fn emit_diagnostic(
1216 &mut self,
1217 mut diagnostic: DiagInner,
1218 taint: Option<&Cell<Option<ErrorGuaranteed>>>,
1219 ) -> Option<ErrorGuaranteed> {
1220 if diagnostic.has_future_breakage() {
1221 match diagnostic.level {
Error | ForceWarning | Warning | Allow | Expect => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"Error | ForceWarning | Warning | Allow | Expect",
::core::option::Option::None);
}
};assert_matches!(diagnostic.level, Error | ForceWarning | Warning | Allow | Expect);
1225 self.future_breakage_diagnostics.push(diagnostic.clone());
1226 }
1227
1228 match diagnostic.level {
1232 Bug => {}
1233 Fatal | Error => {
1234 if self.treat_next_err_as_bug() {
1235 diagnostic.level = Bug;
1237 }
1238 }
1239 DelayedBug => {
1240 if self.flags.eagerly_emit_delayed_bugs {
1245 if self.treat_next_err_as_bug() {
1247 diagnostic.level = Bug;
1248 } else {
1249 diagnostic.level = Error;
1250 }
1251 } else {
1252 return if let Some(guar) = self.has_errors() {
1255 Some(guar)
1256 } else {
1257 let backtrace = std::backtrace::Backtrace::capture();
1261 #[allow(deprecated)]
1265 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1266 self.delayed_bugs
1267 .push((DelayedDiagInner::with_backtrace(diagnostic, backtrace), guar));
1268 Some(guar)
1269 };
1270 }
1271 }
1272 ForceWarning if diagnostic.lint_id.is_none() => {} Warning => {
1274 if !self.flags.can_emit_warnings {
1275 if diagnostic.has_future_breakage() {
1277 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1279 }
1280 return None;
1281 }
1282 }
1283 Note | Help | FailureNote => {}
1284 OnceNote | OnceHelp => {
::core::panicking::panic_fmt(format_args!("bad level: {0:?}",
diagnostic.level));
}panic!("bad level: {:?}", diagnostic.level),
1285 Allow => {
1286 if diagnostic.has_future_breakage() {
1288 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1290 self.suppressed_expected_diag = true;
1291 }
1292 return None;
1293 }
1294 Expect | ForceWarning => {
1295 self.fulfilled_expectations.insert(diagnostic.lint_id.unwrap());
1296 if let Expect = diagnostic.level {
1297 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1299 self.suppressed_expected_diag = true;
1300 return None;
1301 }
1302 }
1303 }
1304
1305 TRACK_DIAGNOSTIC(diagnostic, &mut |mut diagnostic| {
1306 if let Some(code) = diagnostic.code {
1307 self.emitted_diagnostic_codes.insert(code);
1308 }
1309
1310 let already_emitted = {
1311 let mut hasher = StableHasher::new();
1312 diagnostic.hash(&mut hasher);
1313 let diagnostic_hash = hasher.finish();
1314 !self.emitted_diagnostics.insert(diagnostic_hash)
1315 };
1316
1317 let is_error = diagnostic.is_error();
1318 let is_lint = diagnostic.is_lint.is_some();
1319
1320 if !(self.flags.deduplicate_diagnostics && already_emitted) {
1323 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/lib.rs:1323",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1323u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&["diagnostic"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&diagnostic)
as &dyn Value))])
});
} else { ; }
};debug!(?diagnostic);
1324 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/lib.rs:1324",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1324u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&["self.emitted_diagnostics"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&self.emitted_diagnostics)
as &dyn Value))])
});
} else { ; }
};debug!(?self.emitted_diagnostics);
1325
1326 let not_yet_emitted = |sub: &mut Subdiag| {
1327 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/lib.rs:1327",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1327u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&["sub"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&sub) as
&dyn Value))])
});
} else { ; }
};debug!(?sub);
1328 if sub.level != OnceNote && sub.level != OnceHelp {
1329 return true;
1330 }
1331 let mut hasher = StableHasher::new();
1332 sub.hash(&mut hasher);
1333 let diagnostic_hash = hasher.finish();
1334 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/lib.rs:1334",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1334u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&["diagnostic_hash"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&diagnostic_hash)
as &dyn Value))])
});
} else { ; }
};debug!(?diagnostic_hash);
1335 self.emitted_diagnostics.insert(diagnostic_hash)
1336 };
1337 diagnostic.children.retain_mut(not_yet_emitted);
1338 if already_emitted {
1339 let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
1340 diagnostic.sub(Note, msg, MultiSpan::new());
1341 }
1342
1343 if is_error {
1344 self.deduplicated_err_count += 1;
1345 } else if #[allow(non_exhaustive_omitted_patterns)] match diagnostic.level {
ForceWarning | Warning => true,
_ => false,
}matches!(diagnostic.level, ForceWarning | Warning) {
1346 self.deduplicated_warn_count += 1;
1347 }
1348 self.has_printed = true;
1349
1350 self.emitter.emit_diagnostic(diagnostic);
1351 }
1352
1353 if is_error {
1354 if !self.delayed_bugs.is_empty() {
1359 match (&(self.lint_err_guars.len() + self.err_guars.len()), &0) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(self.lint_err_guars.len() + self.err_guars.len(), 0);
1360 self.delayed_bugs.clear();
1361 self.delayed_bugs.shrink_to_fit();
1362 }
1363
1364 #[allow(deprecated)]
1367 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1368 if is_lint {
1369 self.lint_err_guars.push(guar);
1370 } else {
1371 if let Some(taint) = taint {
1372 taint.set(Some(guar));
1373 }
1374 self.err_guars.push(guar);
1375 }
1376 self.panic_if_treat_err_as_bug();
1377 Some(guar)
1378 } else {
1379 None
1380 }
1381 })
1382 }
1383
1384 fn treat_err_as_bug(&self) -> bool {
1385 self.flags
1386 .treat_err_as_bug
1387 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() >= c.get())
1388 }
1389
1390 fn treat_next_err_as_bug(&self) -> bool {
1392 self.flags
1393 .treat_err_as_bug
1394 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() + 1 >= c.get())
1395 }
1396
1397 fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
1398 self.err_guars.get(0).copied().or_else(|| {
1399 if let Some((_diag, guar)) = self
1400 .stashed_diagnostics
1401 .values()
1402 .flat_map(|stashed_diagnostics| stashed_diagnostics.values())
1403 .find(|(diag, guar)| guar.is_some() && diag.is_lint.is_none())
1404 {
1405 *guar
1406 } else {
1407 None
1408 }
1409 })
1410 }
1411
1412 fn has_errors(&self) -> Option<ErrorGuaranteed> {
1413 self.err_guars.get(0).copied().or_else(|| self.lint_err_guars.get(0).copied()).or_else(
1414 || {
1415 self.stashed_diagnostics.values().find_map(|stashed_diagnostics| {
1416 stashed_diagnostics.values().find_map(|(_, guar)| *guar)
1417 })
1418 },
1419 )
1420 }
1421
1422 fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
1423 self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
1424 }
1425
1426 fn eagerly_translate<'a>(
1428 &self,
1429 message: DiagMessage,
1430 args: impl Iterator<Item = DiagArg<'a>>,
1431 ) -> SubdiagMessage {
1432 SubdiagMessage::Str(Cow::from(self.eagerly_translate_to_string(message, args)))
1433 }
1434
1435 fn eagerly_translate_to_string<'a>(
1437 &self,
1438 message: DiagMessage,
1439 args: impl Iterator<Item = DiagArg<'a>>,
1440 ) -> String {
1441 let args = crate::translation::to_fluent_args(args);
1442 self.emitter
1443 .translator()
1444 .translate_message(&message, &args)
1445 .map_err(Report::new)
1446 .unwrap()
1447 .to_string()
1448 }
1449
1450 fn eagerly_translate_for_subdiag(
1451 &self,
1452 diag: &DiagInner,
1453 msg: impl Into<SubdiagMessage>,
1454 ) -> SubdiagMessage {
1455 let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
1456 self.eagerly_translate(msg, diag.args.iter())
1457 }
1458
1459 fn flush_delayed(&mut self) {
1460 if !self.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: self.stashed_diagnostics.is_empty()")
};assert!(self.stashed_diagnostics.is_empty());
1464
1465 if !self.err_guars.is_empty() {
1466 return;
1468 }
1469
1470 if self.delayed_bugs.is_empty() {
1471 return;
1473 }
1474
1475 let bugs: Vec<_> =
1476 std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();
1477
1478 let backtrace = std::env::var_os("RUST_BACKTRACE").as_deref() != Some(OsStr::new("0"));
1479 let decorate = backtrace || self.ice_file.is_none();
1480 let mut out = self
1481 .ice_file
1482 .as_ref()
1483 .and_then(|file| std::fs::File::options().create(true).append(true).open(file).ok());
1484
1485 let note1 = "no errors encountered even though delayed bugs were created";
1490 let note2 = "those delayed bugs will now be shown as internal compiler errors";
1491 self.emit_diagnostic(DiagInner::new(Note, note1), None);
1492 self.emit_diagnostic(DiagInner::new(Note, note2), None);
1493
1494 for bug in bugs {
1495 if let Some(out) = &mut out {
1496 _ = out.write_fmt(format_args!("delayed bug: {0}\n{1}\n",
bug.inner.messages.iter().filter_map(|(msg, _)|
msg.as_str()).collect::<String>(), &bug.note))write!(
1497 out,
1498 "delayed bug: {}\n{}\n",
1499 bug.inner
1500 .messages
1501 .iter()
1502 .filter_map(|(msg, _)| msg.as_str())
1503 .collect::<String>(),
1504 &bug.note
1505 );
1506 }
1507
1508 let mut bug = if decorate { bug.decorate(self) } else { bug.inner };
1509
1510 if bug.level != DelayedBug {
1512 bug.arg("level", bug.level);
1519 let msg = rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"))inline_fluent!(
1520 "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"
1521 );
1522 let msg = self.eagerly_translate_for_subdiag(&bug, msg); bug.sub(Note, msg, bug.span.primary_span().unwrap().into());
1524 }
1525 bug.level = Bug;
1526
1527 self.emit_diagnostic(bug, None);
1528 }
1529
1530 panic::panic_any(DelayedBugPanic);
1532 }
1533
1534 fn panic_if_treat_err_as_bug(&self) {
1535 if self.treat_err_as_bug() {
1536 let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
1537 match (&n, &(self.err_guars.len() + self.lint_err_guars.len())) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(n, self.err_guars.len() + self.lint_err_guars.len());
1538 if n == 1 {
1539 {
::core::panicking::panic_fmt(format_args!("aborting due to `-Z treat-err-as-bug=1`"));
};panic!("aborting due to `-Z treat-err-as-bug=1`");
1540 } else {
1541 {
::core::panicking::panic_fmt(format_args!("aborting after {0} errors due to `-Z treat-err-as-bug={0}`",
n));
};panic!("aborting after {n} errors due to `-Z treat-err-as-bug={n}`");
1542 }
1543 }
1544 }
1545}
1546
1547struct DelayedDiagInner {
1548 inner: DiagInner,
1549 note: Backtrace,
1550}
1551
1552impl DelayedDiagInner {
1553 fn with_backtrace(diagnostic: DiagInner, backtrace: Backtrace) -> Self {
1554 DelayedDiagInner { inner: diagnostic, note: backtrace }
1555 }
1556
1557 fn decorate(self, dcx: &DiagCtxtInner) -> DiagInner {
1558 let mut diag = self.inner;
1562 let msg = match self.note.status() {
1563 BacktraceStatus::Captured => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at}
{$note}"))inline_fluent!(
1564 "delayed at {$emitted_at}
1565{$note}"
1566 ),
1567 _ => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at} - {$note}"))inline_fluent!("delayed at {$emitted_at} - {$note}"),
1570 };
1571 diag.arg("emitted_at", diag.emitted_at.clone());
1572 diag.arg("note", self.note);
1573 let msg = dcx.eagerly_translate_for_subdiag(&diag, msg); diag.sub(Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
1575 diag
1576 }
1577}
1578
1579#[derive(#[automatically_derived]
impl ::core::marker::Copy for Level { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for Level {
#[inline]
fn eq(&self, other: &Level) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Level {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::clone::Clone for Level {
#[inline]
fn clone(&self) -> Level { *self }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for Level {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Level {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Level::Bug => "Bug",
Level::Fatal => "Fatal",
Level::Error => "Error",
Level::DelayedBug => "DelayedBug",
Level::ForceWarning => "ForceWarning",
Level::Warning => "Warning",
Level::Note => "Note",
Level::OnceNote => "OnceNote",
Level::Help => "Help",
Level::OnceHelp => "OnceHelp",
Level::FailureNote => "FailureNote",
Level::Allow => "Allow",
Level::Expect => "Expect",
})
}
}Debug, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Level {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
Level::Bug => { 0usize }
Level::Fatal => { 1usize }
Level::Error => { 2usize }
Level::DelayedBug => { 3usize }
Level::ForceWarning => { 4usize }
Level::Warning => { 5usize }
Level::Note => { 6usize }
Level::OnceNote => { 7usize }
Level::Help => { 8usize }
Level::OnceHelp => { 9usize }
Level::FailureNote => { 10usize }
Level::Allow => { 11usize }
Level::Expect => { 12usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
Level::Bug => {}
Level::Fatal => {}
Level::Error => {}
Level::DelayedBug => {}
Level::ForceWarning => {}
Level::Warning => {}
Level::Note => {}
Level::OnceNote => {}
Level::Help => {}
Level::OnceHelp => {}
Level::FailureNote => {}
Level::Allow => {}
Level::Expect => {}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Level {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { Level::Bug }
1usize => { Level::Fatal }
2usize => { Level::Error }
3usize => { Level::DelayedBug }
4usize => { Level::ForceWarning }
5usize => { Level::Warning }
6usize => { Level::Note }
7usize => { Level::OnceNote }
8usize => { Level::Help }
9usize => { Level::OnceHelp }
10usize => { Level::FailureNote }
11usize => { Level::Allow }
12usize => { Level::Expect }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Level`, expected 0..13, actual {0}",
n));
}
}
}
}
};Decodable)]
1599pub enum Level {
1600 Bug,
1602
1603 Fatal,
1606
1607 Error,
1610
1611 DelayedBug,
1616
1617 ForceWarning,
1623
1624 Warning,
1627
1628 Note,
1630
1631 OnceNote,
1633
1634 Help,
1636
1637 OnceHelp,
1639
1640 FailureNote,
1643
1644 Allow,
1646
1647 Expect,
1649}
1650
1651impl fmt::Display for Level {
1652 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1653 self.to_str().fmt(f)
1654 }
1655}
1656
1657impl Level {
1658 fn color(self) -> anstyle::Style {
1659 match self {
1660 Bug | Fatal | Error | DelayedBug => AnsiColor::BrightRed.on_default(),
1661 ForceWarning | Warning => {
1662 if falsecfg!(windows) {
1663 AnsiColor::BrightYellow.on_default()
1664 } else {
1665 AnsiColor::Yellow.on_default()
1666 }
1667 }
1668 Note | OnceNote => AnsiColor::BrightGreen.on_default(),
1669 Help | OnceHelp => AnsiColor::BrightCyan.on_default(),
1670 FailureNote => anstyle::Style::new(),
1671 Allow | Expect => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1672 }
1673 }
1674
1675 pub fn to_str(self) -> &'static str {
1676 match self {
1677 Bug | DelayedBug => "error: internal compiler error",
1678 Fatal | Error => "error",
1679 ForceWarning | Warning => "warning",
1680 Note | OnceNote => "note",
1681 Help | OnceHelp => "help",
1682 FailureNote => "failure-note",
1683 Allow | Expect => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1684 }
1685 }
1686
1687 pub fn is_failure_note(&self) -> bool {
1688 #[allow(non_exhaustive_omitted_patterns)] match *self {
FailureNote => true,
_ => false,
}matches!(*self, FailureNote)
1689 }
1690}
1691
1692impl IntoDiagArg for Level {
1693 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
1694 DiagArgValue::Str(Cow::from(self.to_string()))
1695 }
1696}
1697
1698#[derive(#[automatically_derived]
impl ::core::marker::Copy for Style { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Style {
#[inline]
fn clone(&self) -> Style {
let _: ::core::clone::AssertParamIsClone<Level>;
*self
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Style {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Style::MainHeaderMsg =>
::core::fmt::Formatter::write_str(f, "MainHeaderMsg"),
Style::HeaderMsg =>
::core::fmt::Formatter::write_str(f, "HeaderMsg"),
Style::LineAndColumn =>
::core::fmt::Formatter::write_str(f, "LineAndColumn"),
Style::LineNumber =>
::core::fmt::Formatter::write_str(f, "LineNumber"),
Style::Quotation =>
::core::fmt::Formatter::write_str(f, "Quotation"),
Style::UnderlinePrimary =>
::core::fmt::Formatter::write_str(f, "UnderlinePrimary"),
Style::UnderlineSecondary =>
::core::fmt::Formatter::write_str(f, "UnderlineSecondary"),
Style::LabelPrimary =>
::core::fmt::Formatter::write_str(f, "LabelPrimary"),
Style::LabelSecondary =>
::core::fmt::Formatter::write_str(f, "LabelSecondary"),
Style::NoStyle => ::core::fmt::Formatter::write_str(f, "NoStyle"),
Style::Level(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Level",
&__self_0),
Style::Highlight =>
::core::fmt::Formatter::write_str(f, "Highlight"),
Style::Addition =>
::core::fmt::Formatter::write_str(f, "Addition"),
Style::Removal => ::core::fmt::Formatter::write_str(f, "Removal"),
}
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Style {
#[inline]
fn eq(&self, other: &Style) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Style::Level(__self_0), Style::Level(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Style {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Level>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Style {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
Style::Level(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
_ => {}
}
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Style {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
Style::MainHeaderMsg => { 0usize }
Style::HeaderMsg => { 1usize }
Style::LineAndColumn => { 2usize }
Style::LineNumber => { 3usize }
Style::Quotation => { 4usize }
Style::UnderlinePrimary => { 5usize }
Style::UnderlineSecondary => { 6usize }
Style::LabelPrimary => { 7usize }
Style::LabelSecondary => { 8usize }
Style::NoStyle => { 9usize }
Style::Level(ref __binding_0) => { 10usize }
Style::Highlight => { 11usize }
Style::Addition => { 12usize }
Style::Removal => { 13usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
Style::MainHeaderMsg => {}
Style::HeaderMsg => {}
Style::LineAndColumn => {}
Style::LineNumber => {}
Style::Quotation => {}
Style::UnderlinePrimary => {}
Style::UnderlineSecondary => {}
Style::LabelPrimary => {}
Style::LabelSecondary => {}
Style::NoStyle => {}
Style::Level(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
Style::Highlight => {}
Style::Addition => {}
Style::Removal => {}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Style {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { Style::MainHeaderMsg }
1usize => { Style::HeaderMsg }
2usize => { Style::LineAndColumn }
3usize => { Style::LineNumber }
4usize => { Style::Quotation }
5usize => { Style::UnderlinePrimary }
6usize => { Style::UnderlineSecondary }
7usize => { Style::LabelPrimary }
8usize => { Style::LabelSecondary }
9usize => { Style::NoStyle }
10usize => {
Style::Level(::rustc_serialize::Decodable::decode(__decoder))
}
11usize => { Style::Highlight }
12usize => { Style::Addition }
13usize => { Style::Removal }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Style`, expected 0..14, actual {0}",
n));
}
}
}
}
};Decodable)]
1699pub enum Style {
1700 MainHeaderMsg,
1701 HeaderMsg,
1702 LineAndColumn,
1703 LineNumber,
1704 Quotation,
1705 UnderlinePrimary,
1706 UnderlineSecondary,
1707 LabelPrimary,
1708 LabelSecondary,
1709 NoStyle,
1710 Level(Level),
1711 Highlight,
1712 Addition,
1713 Removal,
1714}
1715
1716pub fn elided_lifetime_in_path_suggestion(
1718 source_map: &SourceMap,
1719 n: usize,
1720 path_span: Span,
1721 incl_angl_brckt: bool,
1722 insertion_span: Span,
1723) -> ElidedLifetimeInPathSubdiag {
1724 let expected = ExpectedLifetimeParameter { span: path_span, count: n };
1725 let indicate = source_map.is_span_accessible(insertion_span).then(|| {
1727 let anon_lts = ::alloc::vec::from_elem("'_", n)vec!["'_"; n].join(", ");
1728 let suggestion =
1729 if incl_angl_brckt { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0}>", anon_lts))
})format!("<{anon_lts}>") } else { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}, ", anon_lts))
})format!("{anon_lts}, ") };
1730
1731 IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }
1732 });
1733
1734 ElidedLifetimeInPathSubdiag { expected, indicate }
1735}
1736
1737pub fn a_or_an(s: &str) -> &'static str {
1741 let mut chars = s.chars();
1742 let Some(mut first_alpha_char) = chars.next() else {
1743 return "a";
1744 };
1745 if first_alpha_char == '`' {
1746 let Some(next) = chars.next() else {
1747 return "a";
1748 };
1749 first_alpha_char = next;
1750 }
1751 if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) {
1752 "an"
1753 } else {
1754 "a"
1755 }
1756}
1757
1758#[derive(#[automatically_derived]
impl ::core::clone::Clone for TerminalUrl {
#[inline]
fn clone(&self) -> TerminalUrl { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TerminalUrl { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for TerminalUrl {
#[inline]
fn eq(&self, other: &TerminalUrl) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for TerminalUrl {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for TerminalUrl {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
TerminalUrl::No => "No",
TerminalUrl::Yes => "Yes",
TerminalUrl::Auto => "Auto",
})
}
}Debug)]
1759pub enum TerminalUrl {
1760 No,
1761 Yes,
1762 Auto,
1763}