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;
86#[cfg(test)]
87mod tests;
88pub mod timings;
89pub mod translation;
90
91pub type PResult<'a, T> = Result<T, Diag<'a>>;
92
93#[cfg(target_pointer_width = "64")]
95const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, ()>>()];rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24);
96#[cfg(target_pointer_width = "64")]
97const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, bool>>()];rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
98
99#[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)]
100pub enum SuggestionStyle {
101 HideCodeInline,
103 HideCodeAlways,
105 CompletelyHidden,
107 ShowCode,
111 ShowAlways,
113}
114
115impl SuggestionStyle {
116 fn hide_inline(&self) -> bool {
117 !#[allow(non_exhaustive_omitted_patterns)] match *self {
SuggestionStyle::ShowCode => true,
_ => false,
}matches!(*self, SuggestionStyle::ShowCode)
118 }
119}
120
121#[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)]
123pub enum Suggestions {
124 Enabled(Vec<CodeSuggestion>),
129 Sealed(Box<[CodeSuggestion]>),
133 Disabled,
137}
138
139impl Suggestions {
140 pub fn unwrap_tag(self) -> Vec<CodeSuggestion> {
142 match self {
143 Suggestions::Enabled(suggestions) => suggestions,
144 Suggestions::Sealed(suggestions) => suggestions.into_vec(),
145 Suggestions::Disabled => Vec::new(),
146 }
147 }
148}
149
150impl Default for Suggestions {
151 fn default() -> Self {
152 Self::Enabled(::alloc::vec::Vec::new()vec![])
153 }
154}
155
156#[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)]
157pub struct CodeSuggestion {
158 pub substitutions: Vec<Substitution>,
180 pub msg: DiagMessage,
181 pub style: SuggestionStyle,
183 pub applicability: Applicability,
189}
190
191#[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)]
192pub struct Substitution {
194 pub parts: Vec<SubstitutionPart>,
195}
196
197#[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)]
198pub struct SubstitutionPart {
199 pub span: Span,
200 pub snippet: String,
201}
202
203#[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)]
204pub struct TrimmedSubstitutionPart {
205 pub original_span: Span,
206 pub span: Span,
207 pub snippet: String,
208}
209
210impl TrimmedSubstitutionPart {
211 pub fn is_addition(&self, sm: &SourceMap) -> bool {
212 !self.snippet.is_empty() && !self.replaces_meaningful_content(sm)
213 }
214
215 pub fn is_deletion(&self, sm: &SourceMap) -> bool {
216 self.snippet.trim().is_empty() && self.replaces_meaningful_content(sm)
217 }
218
219 pub fn is_replacement(&self, sm: &SourceMap) -> bool {
220 !self.snippet.is_empty() && self.replaces_meaningful_content(sm)
221 }
222
223 pub fn is_destructive_replacement(&self, sm: &SourceMap) -> bool {
228 self.is_replacement(sm)
229 && !sm
230 .span_to_snippet(self.span)
231 .is_ok_and(|snippet| as_substr(snippet.trim(), self.snippet.trim()).is_some())
232 }
233
234 fn replaces_meaningful_content(&self, sm: &SourceMap) -> bool {
235 sm.span_to_snippet(self.span)
236 .map_or(!self.span.is_empty(), |snippet| !snippet.trim().is_empty())
237 }
238}
239
240fn as_substr<'a>(original: &'a str, suggestion: &'a str) -> Option<(usize, &'a str, usize)> {
245 let common_prefix = original
246 .chars()
247 .zip(suggestion.chars())
248 .take_while(|(c1, c2)| c1 == c2)
249 .map(|(c, _)| c.len_utf8())
250 .sum();
251 let original = &original[common_prefix..];
252 let suggestion = &suggestion[common_prefix..];
253 if suggestion.ends_with(original) {
254 let common_suffix = original.len();
255 Some((common_prefix, &suggestion[..suggestion.len() - original.len()], common_suffix))
256 } else {
257 None
258 }
259}
260
261pub struct ExplicitBug;
264
265pub struct DelayedBugPanic;
268
269pub struct DiagCtxt {
273 inner: Lock<DiagCtxtInner>,
274}
275
276#[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)]
277pub struct DiagCtxtHandle<'a> {
278 dcx: &'a DiagCtxt,
279 tainted_with_errors: Option<&'a Cell<Option<ErrorGuaranteed>>>,
282}
283
284impl<'a> std::ops::Deref for DiagCtxtHandle<'a> {
285 type Target = &'a DiagCtxt;
286
287 fn deref(&self) -> &Self::Target {
288 &self.dcx
289 }
290}
291
292struct DiagCtxtInner {
296 flags: DiagCtxtFlags,
297
298 err_guars: Vec<ErrorGuaranteed>,
300 lint_err_guars: Vec<ErrorGuaranteed>,
303 delayed_bugs: Vec<(DelayedDiagInner, ErrorGuaranteed)>,
305
306 deduplicated_err_count: usize,
308 deduplicated_warn_count: usize,
310
311 emitter: Box<DynEmitter>,
312
313 must_produce_diag: Option<Backtrace>,
316
317 has_printed: bool,
320
321 suppressed_expected_diag: bool,
324
325 taught_diagnostics: FxHashSet<ErrCode>,
329
330 emitted_diagnostic_codes: FxIndexSet<ErrCode>,
332
333 emitted_diagnostics: FxHashSet<Hash128>,
337
338 stashed_diagnostics:
344 FxIndexMap<StashKey, FxIndexMap<Span, (DiagInner, Option<ErrorGuaranteed>)>>,
345
346 future_breakage_diagnostics: Vec<DiagInner>,
347
348 fulfilled_expectations: FxIndexSet<LintExpectationId>,
360
361 ice_file: Option<PathBuf>,
364}
365
366#[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)]
368pub enum StashKey {
369 ItemNoType,
370 UnderscoreForArrayLengths,
371 EarlySyntaxWarning,
372 CallIntoMethod,
373 LifetimeIsChar,
376 MaybeFruTypo,
379 CallAssocMethod,
380 AssociatedTypeSuggestion,
381 Cycle,
383 UndeterminedMacroResolution,
384 ExprInPat,
386 GenericInFieldExpr,
390}
391
392fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
393 (*f)(diag)
394}
395
396pub static TRACK_DIAGNOSTIC: AtomicRef<
399 fn(DiagInner, &mut dyn FnMut(DiagInner) -> Option<ErrorGuaranteed>) -> Option<ErrorGuaranteed>,
400> = AtomicRef::new(&(default_track_diagnostic as _));
401
402#[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)]
403pub struct DiagCtxtFlags {
404 pub can_emit_warnings: bool,
407 pub treat_err_as_bug: Option<NonZero<usize>>,
410 pub eagerly_emit_delayed_bugs: bool,
413 pub macro_backtrace: bool,
416 pub deduplicate_diagnostics: bool,
418 pub track_diagnostics: bool,
420}
421
422impl Drop for DiagCtxtInner {
423 fn drop(&mut self) {
424 self.emit_stashed_diagnostics();
432
433 self.flush_delayed();
437
438 if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
442 if let Some(backtrace) = &self.must_produce_diag {
443 let suggestion = match backtrace.status() {
444 BacktraceStatus::Disabled => String::from(
445 "Backtraces are currently disabled: set `RUST_BACKTRACE=1` and re-run \
446 to see where it happened.",
447 ),
448 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!(
449 "This happened in the following `must_produce_diag` call's backtrace:\n\
450 {backtrace}",
451 ),
452 _ => String::from("(impossible to capture backtrace where this happened)"),
453 };
454 {
::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!(
455 "`trimmed_def_paths` called, diagnostics were expected but none were emitted. \
456 Use `with_no_trimmed_paths` for debugging. {suggestion}"
457 );
458 }
459 }
460 }
461}
462
463impl DiagCtxt {
464 pub fn disable_warnings(mut self) -> Self {
465 self.inner.get_mut().flags.can_emit_warnings = false;
466 self
467 }
468
469 pub fn with_flags(mut self, flags: DiagCtxtFlags) -> Self {
470 self.inner.get_mut().flags = flags;
471 self
472 }
473
474 pub fn with_ice_file(mut self, ice_file: PathBuf) -> Self {
475 self.inner.get_mut().ice_file = Some(ice_file);
476 self
477 }
478
479 pub fn new(emitter: Box<DynEmitter>) -> Self {
480 Self { inner: Lock::new(DiagCtxtInner::new(emitter)) }
481 }
482
483 pub fn make_silent(&self) {
484 let mut inner = self.inner.borrow_mut();
485 let translator = inner.emitter.translator().clone();
486 inner.emitter = Box::new(emitter::SilentEmitter { translator });
487 }
488
489 pub fn set_emitter(&self, emitter: Box<dyn Emitter + DynSend>) {
490 self.inner.borrow_mut().emitter = emitter;
491 }
492
493 pub fn eagerly_translate<'a>(
495 &self,
496 message: DiagMessage,
497 args: impl Iterator<Item = DiagArg<'a>>,
498 ) -> SubdiagMessage {
499 let inner = self.inner.borrow();
500 inner.eagerly_translate(message, args)
501 }
502
503 pub fn eagerly_translate_to_string<'a>(
505 &self,
506 message: DiagMessage,
507 args: impl Iterator<Item = DiagArg<'a>>,
508 ) -> String {
509 let inner = self.inner.borrow();
510 inner.eagerly_translate_to_string(message, args)
511 }
512
513 pub fn can_emit_warnings(&self) -> bool {
517 self.inner.borrow_mut().flags.can_emit_warnings
518 }
519
520 pub fn reset_err_count(&self) {
526 let mut inner = self.inner.borrow_mut();
529 let DiagCtxtInner {
530 flags: _,
531 err_guars,
532 lint_err_guars,
533 delayed_bugs,
534 deduplicated_err_count,
535 deduplicated_warn_count,
536 emitter: _,
537 must_produce_diag,
538 has_printed,
539 suppressed_expected_diag,
540 taught_diagnostics,
541 emitted_diagnostic_codes,
542 emitted_diagnostics,
543 stashed_diagnostics,
544 future_breakage_diagnostics,
545 fulfilled_expectations,
546 ice_file: _,
547 } = inner.deref_mut();
548
549 *err_guars = Default::default();
552 *lint_err_guars = Default::default();
553 *delayed_bugs = Default::default();
554 *deduplicated_err_count = 0;
555 *deduplicated_warn_count = 0;
556 *must_produce_diag = None;
557 *has_printed = false;
558 *suppressed_expected_diag = false;
559 *taught_diagnostics = Default::default();
560 *emitted_diagnostic_codes = Default::default();
561 *emitted_diagnostics = Default::default();
562 *stashed_diagnostics = Default::default();
563 *future_breakage_diagnostics = Default::default();
564 *fulfilled_expectations = Default::default();
565 }
566
567 pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> {
568 DiagCtxtHandle { dcx: self, tainted_with_errors: None }
569 }
570
571 pub fn taintable_handle<'a>(
575 &'a self,
576 tainted_with_errors: &'a Cell<Option<ErrorGuaranteed>>,
577 ) -> DiagCtxtHandle<'a> {
578 DiagCtxtHandle { dcx: self, tainted_with_errors: Some(tainted_with_errors) }
579 }
580}
581
582impl<'a> DiagCtxtHandle<'a> {
583 pub fn stash_diagnostic(
605 &self,
606 span: Span,
607 key: StashKey,
608 diag: DiagInner,
609 ) -> Option<ErrorGuaranteed> {
610 let guar = match diag.level {
611 Bug | Fatal => {
612 self.span_bug(
613 span,
614 ::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),
615 );
616 }
617 Error => Some(self.span_delayed_bug(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("stashing {0:?}", key))
})format!("stashing {key:?}"))),
621 DelayedBug => {
622 return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors);
623 }
624 ForceWarning | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow
625 | Expect => None,
626 };
627
628 self.inner
632 .borrow_mut()
633 .stashed_diagnostics
634 .entry(key)
635 .or_default()
636 .insert(span.with_parent(None), (diag, guar));
637
638 guar
639 }
640
641 pub fn steal_non_err(self, span: Span, key: StashKey) -> Option<Diag<'a, ()>> {
645 let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
647 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
648 )?;
649 if !!diag.is_error() {
::core::panicking::panic("assertion failed: !diag.is_error()")
};assert!(!diag.is_error());
650 if !guar.is_none() {
::core::panicking::panic("assertion failed: guar.is_none()")
};assert!(guar.is_none());
651 Some(Diag::new_diagnostic(self, diag))
652 }
653
654 pub fn try_steal_modify_and_emit_err<F>(
659 self,
660 span: Span,
661 key: StashKey,
662 mut modify_err: F,
663 ) -> Option<ErrorGuaranteed>
664 where
665 F: FnMut(&mut Diag<'_>),
666 {
667 let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
669 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
670 );
671 err.map(|(err, guar)| {
672 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);
674 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
675 let mut err = Diag::<ErrorGuaranteed>::new_diagnostic(self, err);
676 modify_err(&mut err);
677 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);
678 err.emit()
679 })
680 }
681
682 pub fn try_steal_replace_and_emit_err(
686 self,
687 span: Span,
688 key: StashKey,
689 new_err: Diag<'_>,
690 ) -> ErrorGuaranteed {
691 let old_err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
693 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
694 );
695 match old_err {
696 Some((old_err, guar)) => {
697 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);
698 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
699 Diag::<ErrorGuaranteed>::new_diagnostic(self, old_err).cancel();
702 }
703 None => {}
704 };
705 new_err.emit()
706 }
707
708 pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool {
709 let inner = self.inner.borrow();
710 if let Some(stashed_diagnostics) = inner.stashed_diagnostics.get(&key)
711 && !stashed_diagnostics.is_empty()
712 {
713 stashed_diagnostics.contains_key(&span.with_parent(None))
714 } else {
715 false
716 }
717 }
718
719 pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
721 self.inner.borrow_mut().emit_stashed_diagnostics()
722 }
723
724 #[inline]
726 pub fn err_count(&self) -> usize {
727 let inner = self.inner.borrow();
728 inner.err_guars.len()
729 + inner.lint_err_guars.len()
730 + inner
731 .stashed_diagnostics
732 .values()
733 .map(|a| a.values().filter(|(_, guar)| guar.is_some()).count())
734 .sum::<usize>()
735 }
736
737 pub fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
740 self.inner.borrow().has_errors_excluding_lint_errors()
741 }
742
743 pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
745 self.inner.borrow().has_errors()
746 }
747
748 pub fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
751 self.inner.borrow().has_errors_or_delayed_bugs()
752 }
753
754 pub fn print_error_count(&self) {
755 let mut inner = self.inner.borrow_mut();
756
757 if !inner.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: inner.stashed_diagnostics.is_empty()")
};assert!(inner.stashed_diagnostics.is_empty());
760
761 if inner.treat_err_as_bug() {
762 return;
763 }
764
765 let warnings = match inner.deduplicated_warn_count {
766 0 => Cow::from(""),
767 1 => Cow::from("1 warning emitted"),
768 count => Cow::from(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} warnings emitted", count))
})format!("{count} warnings emitted")),
769 };
770 let errors = match inner.deduplicated_err_count {
771 0 => Cow::from(""),
772 1 => Cow::from("aborting due to 1 previous error"),
773 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")),
774 };
775
776 match (errors.len(), warnings.len()) {
777 (0, 0) => return,
778 (0, _) => {
779 inner.emit_diagnostic(
782 DiagInner::new(ForceWarning, DiagMessage::Str(warnings)),
783 None,
784 );
785 }
786 (_, 0) => {
787 inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors);
788 }
789 (_, _) => {
790 inner.emit_diagnostic(
791 DiagInner::new(Error, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}; {1}", errors, warnings))
})format!("{errors}; {warnings}")),
792 self.tainted_with_errors,
793 );
794 }
795 }
796
797 let can_show_explain = inner.emitter.should_show_explain();
798 let are_there_diagnostics = !inner.emitted_diagnostic_codes.is_empty();
799 if can_show_explain && are_there_diagnostics {
800 let mut error_codes = inner
801 .emitted_diagnostic_codes
802 .iter()
803 .filter_map(|&code| {
804 if crate::codes::try_find_description(code).is_ok() {
805 Some(code.to_string())
806 } else {
807 None
808 }
809 })
810 .collect::<Vec<_>>();
811 if !error_codes.is_empty() {
812 error_codes.sort();
813 if error_codes.len() > 1 {
814 let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
815 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!(
816 "Some errors have detailed explanations: {}{}",
817 error_codes[..limit].join(", "),
818 if error_codes.len() > 9 { "..." } else { "." }
819 );
820 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!(
821 "For more information about an error, try `rustc --explain {}`.",
822 &error_codes[0]
823 );
824 inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None);
825 inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None);
826 } else {
827 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!(
828 "For more information about this error, try `rustc --explain {}`.",
829 &error_codes[0]
830 );
831 inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None);
832 }
833 }
834 }
835 }
836
837 pub fn abort_if_errors(&self) {
842 if let Some(guar) = self.has_errors() {
843 guar.raise_fatal();
844 }
845 }
846
847 pub fn must_teach(&self, code: ErrCode) -> bool {
853 self.inner.borrow_mut().taught_diagnostics.insert(code)
854 }
855
856 pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
857 self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors)
858 }
859
860 pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
861 self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type);
862 }
863
864 pub fn emit_timing_section_start(&self, record: TimingRecord) {
865 self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start);
866 }
867
868 pub fn emit_timing_section_end(&self, record: TimingRecord) {
869 self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::End);
870 }
871
872 pub fn emit_future_breakage_report(&self) {
873 let inner = &mut *self.inner.borrow_mut();
874 let diags = std::mem::take(&mut inner.future_breakage_diagnostics);
875 if !diags.is_empty() {
876 inner.emitter.emit_future_breakage_report(diags);
877 }
878 }
879
880 pub fn emit_unused_externs(
881 &self,
882 lint_level: rustc_lint_defs::Level,
883 loud: bool,
884 unused_externs: &[&str],
885 ) {
886 let mut inner = self.inner.borrow_mut();
887
888 if loud && lint_level.is_error() {
899 #[allow(deprecated)]
902 inner.lint_err_guars.push(ErrorGuaranteed::unchecked_error_guaranteed());
903 inner.panic_if_treat_err_as_bug();
904 }
905
906 inner.emitter.emit_unused_externs(lint_level, unused_externs)
907 }
908
909 #[must_use]
912 pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet<LintExpectationId> {
913 std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations)
914 }
915
916 pub fn flush_delayed(&self) {
921 self.inner.borrow_mut().flush_delayed();
922 }
923
924 #[track_caller]
927 pub fn set_must_produce_diag(&self) {
928 if !self.inner.borrow().must_produce_diag.is_none() {
{
::core::panicking::panic_fmt(format_args!("should only need to collect a backtrace once"));
}
};assert!(
929 self.inner.borrow().must_produce_diag.is_none(),
930 "should only need to collect a backtrace once"
931 );
932 self.inner.borrow_mut().must_produce_diag = Some(Backtrace::capture());
933 }
934}
935
936impl<'a> DiagCtxtHandle<'a> {
941 #[track_caller]
942 pub fn struct_bug(self, msg: impl Into<Cow<'static, str>>) -> Diag<'a, BugAbort> {
943 Diag::new(self, Bug, msg.into())
944 }
945
946 #[track_caller]
947 pub fn bug(self, msg: impl Into<Cow<'static, str>>) -> ! {
948 self.struct_bug(msg).emit()
949 }
950
951 #[track_caller]
952 pub fn struct_span_bug(
953 self,
954 span: impl Into<MultiSpan>,
955 msg: impl Into<Cow<'static, str>>,
956 ) -> Diag<'a, BugAbort> {
957 self.struct_bug(msg).with_span(span)
958 }
959
960 #[track_caller]
961 pub fn span_bug(self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! {
962 self.struct_span_bug(span, msg.into()).emit()
963 }
964
965 #[track_caller]
966 pub fn create_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> Diag<'a, BugAbort> {
967 bug.into_diag(self, Bug)
968 }
969
970 #[track_caller]
971 pub fn emit_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> ! {
972 self.create_bug(bug).emit()
973 }
974
975 #[track_caller]
976 pub fn struct_fatal(self, msg: impl Into<DiagMessage>) -> Diag<'a, FatalAbort> {
977 Diag::new(self, Fatal, msg)
978 }
979
980 #[track_caller]
981 pub fn fatal(self, msg: impl Into<DiagMessage>) -> ! {
982 self.struct_fatal(msg).emit()
983 }
984
985 #[track_caller]
986 pub fn struct_span_fatal(
987 self,
988 span: impl Into<MultiSpan>,
989 msg: impl Into<DiagMessage>,
990 ) -> Diag<'a, FatalAbort> {
991 self.struct_fatal(msg).with_span(span)
992 }
993
994 #[track_caller]
995 pub fn span_fatal(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) -> ! {
996 self.struct_span_fatal(span, msg).emit()
997 }
998
999 #[track_caller]
1000 pub fn create_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> Diag<'a, FatalAbort> {
1001 fatal.into_diag(self, Fatal)
1002 }
1003
1004 #[track_caller]
1005 pub fn emit_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> ! {
1006 self.create_fatal(fatal).emit()
1007 }
1008
1009 #[track_caller]
1010 pub fn create_almost_fatal(
1011 self,
1012 fatal: impl Diagnostic<'a, FatalError>,
1013 ) -> Diag<'a, FatalError> {
1014 fatal.into_diag(self, Fatal)
1015 }
1016
1017 #[track_caller]
1018 pub fn emit_almost_fatal(self, fatal: impl Diagnostic<'a, FatalError>) -> FatalError {
1019 self.create_almost_fatal(fatal).emit()
1020 }
1021
1022 #[track_caller]
1024 pub fn struct_err(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
1025 Diag::new(self, Error, msg)
1026 }
1027
1028 #[track_caller]
1029 pub fn err(self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed {
1030 self.struct_err(msg).emit()
1031 }
1032
1033 #[track_caller]
1034 pub fn struct_span_err(
1035 self,
1036 span: impl Into<MultiSpan>,
1037 msg: impl Into<DiagMessage>,
1038 ) -> Diag<'a> {
1039 self.struct_err(msg).with_span(span)
1040 }
1041
1042 #[track_caller]
1043 pub fn span_err(
1044 self,
1045 span: impl Into<MultiSpan>,
1046 msg: impl Into<DiagMessage>,
1047 ) -> ErrorGuaranteed {
1048 self.struct_span_err(span, msg).emit()
1049 }
1050
1051 #[track_caller]
1052 pub fn create_err(self, err: impl Diagnostic<'a>) -> Diag<'a> {
1053 err.into_diag(self, Error)
1054 }
1055
1056 #[track_caller]
1057 pub fn emit_err(self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
1058 self.create_err(err).emit()
1059 }
1060
1061 #[track_caller]
1063 pub fn delayed_bug(self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed {
1064 Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).emit()
1065 }
1066
1067 #[track_caller]
1072 pub fn span_delayed_bug(
1073 self,
1074 sp: impl Into<MultiSpan>,
1075 msg: impl Into<Cow<'static, str>>,
1076 ) -> ErrorGuaranteed {
1077 Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).with_span(sp).emit()
1078 }
1079
1080 #[track_caller]
1081 pub fn struct_warn(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1082 Diag::new(self, Warning, msg)
1083 }
1084
1085 #[track_caller]
1086 pub fn warn(self, msg: impl Into<DiagMessage>) {
1087 self.struct_warn(msg).emit()
1088 }
1089
1090 #[track_caller]
1091 pub fn struct_span_warn(
1092 self,
1093 span: impl Into<MultiSpan>,
1094 msg: impl Into<DiagMessage>,
1095 ) -> Diag<'a, ()> {
1096 self.struct_warn(msg).with_span(span)
1097 }
1098
1099 #[track_caller]
1100 pub fn span_warn(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1101 self.struct_span_warn(span, msg).emit()
1102 }
1103
1104 #[track_caller]
1105 pub fn create_warn(self, warning: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
1106 warning.into_diag(self, Warning)
1107 }
1108
1109 #[track_caller]
1110 pub fn emit_warn(self, warning: impl Diagnostic<'a, ()>) {
1111 self.create_warn(warning).emit()
1112 }
1113
1114 #[track_caller]
1115 pub fn struct_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1116 Diag::new(self, Note, msg)
1117 }
1118
1119 #[track_caller]
1120 pub fn note(&self, msg: impl Into<DiagMessage>) {
1121 self.struct_note(msg).emit()
1122 }
1123
1124 #[track_caller]
1125 pub fn struct_span_note(
1126 self,
1127 span: impl Into<MultiSpan>,
1128 msg: impl Into<DiagMessage>,
1129 ) -> Diag<'a, ()> {
1130 self.struct_note(msg).with_span(span)
1131 }
1132
1133 #[track_caller]
1134 pub fn span_note(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1135 self.struct_span_note(span, msg).emit()
1136 }
1137
1138 #[track_caller]
1139 pub fn create_note(self, note: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
1140 note.into_diag(self, Note)
1141 }
1142
1143 #[track_caller]
1144 pub fn emit_note(self, note: impl Diagnostic<'a, ()>) {
1145 self.create_note(note).emit()
1146 }
1147
1148 #[track_caller]
1149 pub fn struct_help(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1150 Diag::new(self, Help, msg)
1151 }
1152
1153 #[track_caller]
1154 pub fn struct_failure_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1155 Diag::new(self, FailureNote, msg)
1156 }
1157
1158 #[track_caller]
1159 pub fn struct_allow(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1160 Diag::new(self, Allow, msg)
1161 }
1162
1163 #[track_caller]
1164 pub fn struct_expect(self, msg: impl Into<DiagMessage>, id: LintExpectationId) -> Diag<'a, ()> {
1165 Diag::new(self, Expect, msg).with_lint_id(id)
1166 }
1167}
1168
1169impl DiagCtxtInner {
1174 fn new(emitter: Box<DynEmitter>) -> Self {
1175 Self {
1176 flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
1177 err_guars: Vec::new(),
1178 lint_err_guars: Vec::new(),
1179 delayed_bugs: Vec::new(),
1180 deduplicated_err_count: 0,
1181 deduplicated_warn_count: 0,
1182 emitter,
1183 must_produce_diag: None,
1184 has_printed: false,
1185 suppressed_expected_diag: false,
1186 taught_diagnostics: Default::default(),
1187 emitted_diagnostic_codes: Default::default(),
1188 emitted_diagnostics: Default::default(),
1189 stashed_diagnostics: Default::default(),
1190 future_breakage_diagnostics: Vec::new(),
1191 fulfilled_expectations: Default::default(),
1192 ice_file: None,
1193 }
1194 }
1195
1196 fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
1198 let mut guar = None;
1199 let has_errors = !self.err_guars.is_empty();
1200 for (_, stashed_diagnostics) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
1201 for (_, (diag, _guar)) in stashed_diagnostics {
1202 if !diag.is_error() {
1203 if !diag.is_force_warn() && has_errors {
1207 continue;
1208 }
1209 }
1210 guar = guar.or(self.emit_diagnostic(diag, None));
1211 }
1212 }
1213 guar
1214 }
1215
1216 fn emit_diagnostic(
1218 &mut self,
1219 mut diagnostic: DiagInner,
1220 taint: Option<&Cell<Option<ErrorGuaranteed>>>,
1221 ) -> Option<ErrorGuaranteed> {
1222 if diagnostic.has_future_breakage() {
1223 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);
1227 self.future_breakage_diagnostics.push(diagnostic.clone());
1228 }
1229
1230 match diagnostic.level {
1234 Bug => {}
1235 Fatal | Error => {
1236 if self.treat_next_err_as_bug() {
1237 diagnostic.level = Bug;
1239 }
1240 }
1241 DelayedBug => {
1242 if self.flags.eagerly_emit_delayed_bugs {
1247 if self.treat_next_err_as_bug() {
1249 diagnostic.level = Bug;
1250 } else {
1251 diagnostic.level = Error;
1252 }
1253 } else {
1254 return if let Some(guar) = self.has_errors() {
1257 Some(guar)
1258 } else {
1259 let backtrace = std::backtrace::Backtrace::capture();
1263 #[allow(deprecated)]
1267 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1268 self.delayed_bugs
1269 .push((DelayedDiagInner::with_backtrace(diagnostic, backtrace), guar));
1270 Some(guar)
1271 };
1272 }
1273 }
1274 ForceWarning if diagnostic.lint_id.is_none() => {} Warning => {
1276 if !self.flags.can_emit_warnings {
1277 if diagnostic.has_future_breakage() {
1279 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1281 }
1282 return None;
1283 }
1284 }
1285 Note | Help | FailureNote => {}
1286 OnceNote | OnceHelp => {
::core::panicking::panic_fmt(format_args!("bad level: {0:?}",
diagnostic.level));
}panic!("bad level: {:?}", diagnostic.level),
1287 Allow => {
1288 if diagnostic.has_future_breakage() {
1290 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1292 self.suppressed_expected_diag = true;
1293 }
1294 return None;
1295 }
1296 Expect | ForceWarning => {
1297 self.fulfilled_expectations.insert(diagnostic.lint_id.unwrap());
1298 if let Expect = diagnostic.level {
1299 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1301 self.suppressed_expected_diag = true;
1302 return None;
1303 }
1304 }
1305 }
1306
1307 TRACK_DIAGNOSTIC(diagnostic, &mut |mut diagnostic| {
1308 if let Some(code) = diagnostic.code {
1309 self.emitted_diagnostic_codes.insert(code);
1310 }
1311
1312 let already_emitted = {
1313 let mut hasher = StableHasher::new();
1314 diagnostic.hash(&mut hasher);
1315 let diagnostic_hash = hasher.finish();
1316 !self.emitted_diagnostics.insert(diagnostic_hash)
1317 };
1318
1319 let is_error = diagnostic.is_error();
1320 let is_lint = diagnostic.is_lint.is_some();
1321
1322 if !(self.flags.deduplicate_diagnostics && already_emitted) {
1325 {
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:1325",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1325u32),
::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);
1326 {
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:1326",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1326u32),
::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);
1327
1328 let not_yet_emitted = |sub: &mut Subdiag| {
1329 {
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:1329",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1329u32),
::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);
1330 if sub.level != OnceNote && sub.level != OnceHelp {
1331 return true;
1332 }
1333 let mut hasher = StableHasher::new();
1334 sub.hash(&mut hasher);
1335 let diagnostic_hash = hasher.finish();
1336 {
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:1336",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1336u32),
::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);
1337 self.emitted_diagnostics.insert(diagnostic_hash)
1338 };
1339 diagnostic.children.retain_mut(not_yet_emitted);
1340 if already_emitted {
1341 let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
1342 diagnostic.sub(Note, msg, MultiSpan::new());
1343 }
1344
1345 if is_error {
1346 self.deduplicated_err_count += 1;
1347 } else if #[allow(non_exhaustive_omitted_patterns)] match diagnostic.level {
ForceWarning | Warning => true,
_ => false,
}matches!(diagnostic.level, ForceWarning | Warning) {
1348 self.deduplicated_warn_count += 1;
1349 }
1350 self.has_printed = true;
1351
1352 self.emitter.emit_diagnostic(diagnostic);
1353 }
1354
1355 if is_error {
1356 if !self.delayed_bugs.is_empty() {
1361 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);
1362 self.delayed_bugs.clear();
1363 self.delayed_bugs.shrink_to_fit();
1364 }
1365
1366 #[allow(deprecated)]
1369 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1370 if is_lint {
1371 self.lint_err_guars.push(guar);
1372 } else {
1373 if let Some(taint) = taint {
1374 taint.set(Some(guar));
1375 }
1376 self.err_guars.push(guar);
1377 }
1378 self.panic_if_treat_err_as_bug();
1379 Some(guar)
1380 } else {
1381 None
1382 }
1383 })
1384 }
1385
1386 fn treat_err_as_bug(&self) -> bool {
1387 self.flags
1388 .treat_err_as_bug
1389 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() >= c.get())
1390 }
1391
1392 fn treat_next_err_as_bug(&self) -> bool {
1394 self.flags
1395 .treat_err_as_bug
1396 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() + 1 >= c.get())
1397 }
1398
1399 fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
1400 self.err_guars.get(0).copied().or_else(|| {
1401 if let Some((_diag, guar)) = self
1402 .stashed_diagnostics
1403 .values()
1404 .flat_map(|stashed_diagnostics| stashed_diagnostics.values())
1405 .find(|(diag, guar)| guar.is_some() && diag.is_lint.is_none())
1406 {
1407 *guar
1408 } else {
1409 None
1410 }
1411 })
1412 }
1413
1414 fn has_errors(&self) -> Option<ErrorGuaranteed> {
1415 self.err_guars.get(0).copied().or_else(|| self.lint_err_guars.get(0).copied()).or_else(
1416 || {
1417 self.stashed_diagnostics.values().find_map(|stashed_diagnostics| {
1418 stashed_diagnostics.values().find_map(|(_, guar)| *guar)
1419 })
1420 },
1421 )
1422 }
1423
1424 fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
1425 self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
1426 }
1427
1428 fn eagerly_translate<'a>(
1430 &self,
1431 message: DiagMessage,
1432 args: impl Iterator<Item = DiagArg<'a>>,
1433 ) -> SubdiagMessage {
1434 SubdiagMessage::Str(Cow::from(self.eagerly_translate_to_string(message, args)))
1435 }
1436
1437 fn eagerly_translate_to_string<'a>(
1439 &self,
1440 message: DiagMessage,
1441 args: impl Iterator<Item = DiagArg<'a>>,
1442 ) -> String {
1443 let args = crate::translation::to_fluent_args(args);
1444 self.emitter
1445 .translator()
1446 .translate_message(&message, &args)
1447 .map_err(Report::new)
1448 .unwrap()
1449 .to_string()
1450 }
1451
1452 fn eagerly_translate_for_subdiag(
1453 &self,
1454 diag: &DiagInner,
1455 msg: impl Into<SubdiagMessage>,
1456 ) -> SubdiagMessage {
1457 let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
1458 self.eagerly_translate(msg, diag.args.iter())
1459 }
1460
1461 fn flush_delayed(&mut self) {
1462 if !self.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: self.stashed_diagnostics.is_empty()")
};assert!(self.stashed_diagnostics.is_empty());
1466
1467 if !self.err_guars.is_empty() {
1468 return;
1470 }
1471
1472 if self.delayed_bugs.is_empty() {
1473 return;
1475 }
1476
1477 let bugs: Vec<_> =
1478 std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();
1479
1480 let backtrace = std::env::var_os("RUST_BACKTRACE").as_deref() != Some(OsStr::new("0"));
1481 let decorate = backtrace || self.ice_file.is_none();
1482 let mut out = self
1483 .ice_file
1484 .as_ref()
1485 .and_then(|file| std::fs::File::options().create(true).append(true).open(file).ok());
1486
1487 let note1 = "no errors encountered even though delayed bugs were created";
1492 let note2 = "those delayed bugs will now be shown as internal compiler errors";
1493 self.emit_diagnostic(DiagInner::new(Note, note1), None);
1494 self.emit_diagnostic(DiagInner::new(Note, note2), None);
1495
1496 for bug in bugs {
1497 if let Some(out) = &mut out {
1498 _ = 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!(
1499 out,
1500 "delayed bug: {}\n{}\n",
1501 bug.inner
1502 .messages
1503 .iter()
1504 .filter_map(|(msg, _)| msg.as_str())
1505 .collect::<String>(),
1506 &bug.note
1507 );
1508 }
1509
1510 let mut bug = if decorate { bug.decorate(self) } else { bug.inner };
1511
1512 if bug.level != DelayedBug {
1514 bug.arg("level", bug.level);
1521 let msg = rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"))inline_fluent!(
1522 "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"
1523 );
1524 let msg = self.eagerly_translate_for_subdiag(&bug, msg); bug.sub(Note, msg, bug.span.primary_span().unwrap().into());
1526 }
1527 bug.level = Bug;
1528
1529 self.emit_diagnostic(bug, None);
1530 }
1531
1532 panic::panic_any(DelayedBugPanic);
1534 }
1535
1536 fn panic_if_treat_err_as_bug(&self) {
1537 if self.treat_err_as_bug() {
1538 let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
1539 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());
1540 if n == 1 {
1541 {
::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`");
1542 } else {
1543 {
::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}`");
1544 }
1545 }
1546 }
1547}
1548
1549struct DelayedDiagInner {
1550 inner: DiagInner,
1551 note: Backtrace,
1552}
1553
1554impl DelayedDiagInner {
1555 fn with_backtrace(diagnostic: DiagInner, backtrace: Backtrace) -> Self {
1556 DelayedDiagInner { inner: diagnostic, note: backtrace }
1557 }
1558
1559 fn decorate(self, dcx: &DiagCtxtInner) -> DiagInner {
1560 let mut diag = self.inner;
1564 let msg = match self.note.status() {
1565 BacktraceStatus::Captured => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at}
{$note}"))inline_fluent!(
1566 "delayed at {$emitted_at}
1567{$note}"
1568 ),
1569 _ => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at} - {$note}"))inline_fluent!("delayed at {$emitted_at} - {$note}"),
1572 };
1573 diag.arg("emitted_at", diag.emitted_at.clone());
1574 diag.arg("note", self.note);
1575 let msg = dcx.eagerly_translate_for_subdiag(&diag, msg); diag.sub(Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
1577 diag
1578 }
1579}
1580
1581#[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)]
1601pub enum Level {
1602 Bug,
1604
1605 Fatal,
1608
1609 Error,
1612
1613 DelayedBug,
1618
1619 ForceWarning,
1625
1626 Warning,
1629
1630 Note,
1632
1633 OnceNote,
1635
1636 Help,
1638
1639 OnceHelp,
1641
1642 FailureNote,
1645
1646 Allow,
1648
1649 Expect,
1651}
1652
1653impl fmt::Display for Level {
1654 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1655 self.to_str().fmt(f)
1656 }
1657}
1658
1659impl Level {
1660 fn color(self) -> anstyle::Style {
1661 match self {
1662 Bug | Fatal | Error | DelayedBug => AnsiColor::BrightRed.on_default(),
1663 ForceWarning | Warning => {
1664 if falsecfg!(windows) {
1665 AnsiColor::BrightYellow.on_default()
1666 } else {
1667 AnsiColor::Yellow.on_default()
1668 }
1669 }
1670 Note | OnceNote => AnsiColor::BrightGreen.on_default(),
1671 Help | OnceHelp => AnsiColor::BrightCyan.on_default(),
1672 FailureNote => anstyle::Style::new(),
1673 Allow | Expect => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1674 }
1675 }
1676
1677 pub fn to_str(self) -> &'static str {
1678 match self {
1679 Bug | DelayedBug => "error: internal compiler error",
1680 Fatal | Error => "error",
1681 ForceWarning | Warning => "warning",
1682 Note | OnceNote => "note",
1683 Help | OnceHelp => "help",
1684 FailureNote => "failure-note",
1685 Allow | Expect => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1686 }
1687 }
1688
1689 pub fn is_failure_note(&self) -> bool {
1690 #[allow(non_exhaustive_omitted_patterns)] match *self {
FailureNote => true,
_ => false,
}matches!(*self, FailureNote)
1691 }
1692}
1693
1694impl IntoDiagArg for Level {
1695 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
1696 DiagArgValue::Str(Cow::from(self.to_string()))
1697 }
1698}
1699
1700#[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)]
1701pub enum Style {
1702 MainHeaderMsg,
1703 HeaderMsg,
1704 LineAndColumn,
1705 LineNumber,
1706 Quotation,
1707 UnderlinePrimary,
1708 UnderlineSecondary,
1709 LabelPrimary,
1710 LabelSecondary,
1711 NoStyle,
1712 Level(Level),
1713 Highlight,
1714 Addition,
1715 Removal,
1716}
1717
1718pub fn elided_lifetime_in_path_suggestion(
1720 source_map: &SourceMap,
1721 n: usize,
1722 path_span: Span,
1723 incl_angl_brckt: bool,
1724 insertion_span: Span,
1725) -> ElidedLifetimeInPathSubdiag {
1726 let expected = ExpectedLifetimeParameter { span: path_span, count: n };
1727 let indicate = source_map.is_span_accessible(insertion_span).then(|| {
1729 let anon_lts = ::alloc::vec::from_elem("'_", n)vec!["'_"; n].join(", ");
1730 let suggestion =
1731 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}, ") };
1732
1733 IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }
1734 });
1735
1736 ElidedLifetimeInPathSubdiag { expected, indicate }
1737}
1738
1739pub fn a_or_an(s: &str) -> &'static str {
1743 let mut chars = s.chars();
1744 let Some(mut first_alpha_char) = chars.next() else {
1745 return "a";
1746 };
1747 if first_alpha_char == '`' {
1748 let Some(next) = chars.next() else {
1749 return "a";
1750 };
1751 first_alpha_char = next;
1752 }
1753 if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) {
1754 "an"
1755 } else {
1756 "a"
1757 }
1758}
1759
1760#[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)]
1761pub enum TerminalUrl {
1762 No,
1763 Yes,
1764 Auto,
1765}