1#![allow(internal_features)]
7#![allow(rustc::direct_use_of_rustc_type_ir)]
8#![feature(associated_type_defaults)]
9#![feature(default_field_values)]
10#![feature(macro_metavar_expr_concat)]
11#![feature(negative_impls)]
12#![feature(never_type)]
13#![feature(rustc_attrs)]
14extern crate self as rustc_errors;
17
18use std::backtrace::{Backtrace, BacktraceStatus};
19use std::borrow::Cow;
20use std::cell::Cell;
21use std::ffi::OsStr;
22use std::hash::Hash;
23use std::io::Write;
24use std::num::NonZero;
25use std::ops::DerefMut;
26use std::path::{Path, PathBuf};
27use std::thread::ThreadId;
28use std::{assert_matches, fmt, panic};
29
30use Level::*;
31pub use anstream::{AutoStream, ColorChoice};
34pub use anstyle::{
35 Ansi256Color, AnsiColor, Color, EffectIter, Effects, Reset, RgbColor, Style as Anstyle,
36};
37pub use codes::*;
38pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer};
39pub use diagnostic::{
40 BugAbort, Diag, DiagDecorator, DiagInner, DiagLocation, DiagStyledString, Diagnostic,
41 EmissionGuarantee, FatalAbort, StringPart, Subdiag, Subdiagnostic,
42};
43pub use diagnostic_impls::{
44 DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,
45 IndicateAnonymousLifetime, SingleLabelManySpans,
46};
47pub use emitter::ColorConfig;
48use emitter::{DynEmitter, Emitter};
49use rustc_data_structures::AtomicRef;
50use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
51use rustc_data_structures::stable_hash::StableHasher;
52use rustc_data_structures::sync::{DynSend, Lock};
53pub use rustc_error_messages::{
54 DiagArg, DiagArgFromDisplay, DiagArgMap, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg,
55 LanguageIdentifier, MultiSpan, SpanLabel, fluent_bundle, into_diag_arg_using_display,
56};
57use rustc_hashes::Hash128;
58use rustc_lint_defs::LintExpectationId;
59pub use rustc_lint_defs::{Applicability, listify, pluralize};
60pub use rustc_macros::msg;
61use rustc_macros::{Decodable, Encodable};
62pub use rustc_span::ErrorGuaranteed;
63pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors};
64use rustc_span::source_map::SourceMap;
65use rustc_span::{DUMMY_SP, Span};
66use tracing::debug;
67
68use crate::emitter::TimingEvent;
69use crate::formatting::DiagMessageAddArg;
70pub use crate::formatting::format_diag_message;
71use crate::timings::TimingRecord;
72
73pub mod annotate_snippet_emitter_writer;
74pub mod codes;
75mod decorate_diag;
76mod diagnostic;
77mod diagnostic_impls;
78pub mod emitter;
79pub mod formatting;
80pub mod json;
81pub mod lints;
82mod lock;
83pub mod markdown;
84pub mod timings;
85
86pub type PResult<'a, T> = Result<T, Diag<'a>>;
87
88#[cfg(target_pointer_width = "64")]
90const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, ()>>()];rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24);
91#[cfg(target_pointer_width = "64")]
92const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, bool>>()];rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
93
94#[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_fields_are_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)]
95pub enum SuggestionStyle {
96 HideCodeInline,
98 HideCodeAlways,
100 CompletelyHidden,
102 ShowCode,
106 ShowAlways,
108}
109
110impl SuggestionStyle {
111 fn hide_inline(&self) -> bool {
112 !#[allow(non_exhaustive_omitted_patterns)] match *self {
SuggestionStyle::ShowCode => true,
_ => false,
}matches!(*self, SuggestionStyle::ShowCode)
113 }
114}
115
116#[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)]
118pub enum Suggestions {
119 Enabled(Vec<CodeSuggestion>),
124 Sealed(Box<[CodeSuggestion]>),
128 Disabled,
132}
133
134impl Suggestions {
135 pub fn unwrap_tag(self) -> Vec<CodeSuggestion> {
137 match self {
138 Suggestions::Enabled(suggestions) => suggestions,
139 Suggestions::Sealed(suggestions) => suggestions.into_vec(),
140 Suggestions::Disabled => Vec::new(),
141 }
142 }
143
144 pub fn len(&self) -> usize {
145 match self {
146 Suggestions::Enabled(suggestions) => suggestions.len(),
147 Suggestions::Sealed(suggestions) => suggestions.len(),
148 Suggestions::Disabled => 0,
149 }
150 }
151}
152
153impl Default for Suggestions {
154 fn default() -> Self {
155 Self::Enabled(::alloc::vec::Vec::new()vec![])
156 }
157}
158
159#[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)]
160pub struct CodeSuggestion {
161 pub substitutions: Vec<Substitution>,
183 pub msg: DiagMessage,
184 pub style: SuggestionStyle,
186 pub applicability: Applicability,
192}
193
194#[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)]
195pub struct Substitution {
197 pub parts: Vec<SubstitutionPart>,
198}
199
200#[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)]
201pub struct SubstitutionPart {
202 pub span: Span,
203 pub snippet: String,
204}
205
206#[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)]
207pub struct TrimmedSubstitutionPart {
208 pub original_span: Span,
209 pub span: Span,
210 pub snippet: String,
211}
212
213impl TrimmedSubstitutionPart {
214 pub fn is_addition(&self, sm: &SourceMap) -> bool {
215 !self.snippet.is_empty() && !self.replaces_meaningful_content(sm)
216 }
217
218 pub fn is_deletion(&self, sm: &SourceMap) -> bool {
219 self.snippet.trim().is_empty() && self.replaces_meaningful_content(sm)
220 }
221
222 pub fn is_replacement(&self, sm: &SourceMap) -> bool {
223 !self.snippet.is_empty() && self.replaces_meaningful_content(sm)
224 }
225
226 pub fn is_destructive_replacement(&self, sm: &SourceMap) -> bool {
231 self.is_replacement(sm)
232 && !sm
233 .span_to_snippet(self.span)
234 .is_ok_and(|snippet| as_substr(snippet.trim(), self.snippet.trim()).is_some())
235 }
236
237 fn replaces_meaningful_content(&self, sm: &SourceMap) -> bool {
238 sm.span_to_snippet(self.span)
239 .map_or(!self.span.is_empty(), |snippet| !snippet.trim().is_empty())
240 }
241}
242
243fn as_substr<'a>(original: &'a str, suggestion: &'a str) -> Option<(usize, &'a str, usize)> {
248 let common_prefix = original
249 .chars()
250 .zip(suggestion.chars())
251 .take_while(|(c1, c2)| c1 == c2)
252 .map(|(c, _)| c.len_utf8())
253 .sum();
254 let original = &original[common_prefix..];
255 let suggestion = &suggestion[common_prefix..];
256 if suggestion.ends_with(original) {
257 let common_suffix = original.len();
258 Some((common_prefix, &suggestion[..suggestion.len() - original.len()], common_suffix))
259 } else {
260 None
261 }
262}
263
264pub struct ExplicitBug;
267
268pub struct DelayedBugPanic;
271
272pub struct DiagCtxt {
276 inner: Lock<DiagCtxtInner>,
277}
278
279#[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)]
280pub struct DiagCtxtHandle<'a> {
281 dcx: &'a DiagCtxt,
282 tainted_with_errors: Option<&'a Cell<Option<ErrorGuaranteed>>>,
285}
286
287impl<'a> std::ops::Deref for DiagCtxtHandle<'a> {
288 type Target = &'a DiagCtxt;
289
290 fn deref(&self) -> &Self::Target {
291 &self.dcx
292 }
293}
294
295struct DiagCtxtInner {
299 flags: DiagCtxtFlags,
300
301 err_guars: Vec<(ErrorGuaranteed, ThreadId)>,
304 lint_err_guars: Vec<(ErrorGuaranteed, ThreadId)>,
307 delayed_bugs: Vec<(DelayedDiagInner, ErrorGuaranteed)>,
309
310 deduplicated_err_count: usize,
312 deduplicated_warn_count: usize,
314
315 emitter: Box<DynEmitter>,
316
317 must_produce_diag: Option<Backtrace>,
320
321 has_printed: bool,
324
325 suppressed_expected_diag: bool,
328
329 taught_diagnostics: FxHashSet<ErrCode>,
333
334 emitted_diagnostic_codes: FxIndexSet<ErrCode>,
336
337 emitted_diagnostics: FxHashSet<Hash128>,
341
342 stashed_diagnostics:
348 FxIndexMap<StashKey, FxIndexMap<Span, (DiagInner, Option<ErrorGuaranteed>, ThreadId)>>,
349
350 future_breakage_diagnostics: Vec<DiagInner>,
351
352 fulfilled_expectations: FxIndexSet<LintExpectationId>,
364
365 ice_file: Option<PathBuf>,
368}
369
370#[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_fields_are_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::UndeterminedMacroResolution =>
"UndeterminedMacroResolution",
StashKey::ExprInPat => "ExprInPat",
StashKey::GenericInFieldExpr => "GenericInFieldExpr",
StashKey::ReturnTypeNotation => "ReturnTypeNotation",
})
}
}Debug)]
372pub enum StashKey {
373 ItemNoType,
374 UnderscoreForArrayLengths,
375 EarlySyntaxWarning,
376 CallIntoMethod,
377 LifetimeIsChar,
380 MaybeFruTypo,
383 CallAssocMethod,
384 AssociatedTypeSuggestion,
385 UndeterminedMacroResolution,
386 ExprInPat,
388 GenericInFieldExpr,
392 ReturnTypeNotation,
393}
394
395fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
396 (*f)(diag)
397}
398
399pub static TRACK_DIAGNOSTIC: AtomicRef<
402 fn(DiagInner, &mut dyn FnMut(DiagInner) -> Option<ErrorGuaranteed>) -> Option<ErrorGuaranteed>,
403> = AtomicRef::new(&(default_track_diagnostic as _));
404
405#[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)]
406pub struct DiagCtxtFlags {
407 pub can_emit_warnings: bool,
410 pub treat_err_as_bug: Option<NonZero<usize>>,
413 pub eagerly_emit_delayed_bugs: bool,
416 pub macro_backtrace: bool,
419 pub deduplicate_diagnostics: bool,
421 pub track_diagnostics: bool,
423}
424
425impl Drop for DiagCtxtInner {
426 fn drop(&mut self) {
427 self.emit_stashed_diagnostics();
435
436 self.flush_delayed();
440
441 if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
445 if let Some(backtrace) = &self.must_produce_diag {
446 let suggestion = match backtrace.status() {
447 BacktraceStatus::Disabled => String::from(
448 "Backtraces are currently disabled: set `RUST_BACKTRACE=1` and re-run \
449 to see where it happened.",
450 ),
451 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!(
452 "This happened in the following `must_produce_diag` call's backtrace:\n\
453 {backtrace}",
454 ),
455 _ => String::from("(impossible to capture backtrace where this happened)"),
456 };
457 {
::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!(
458 "`trimmed_def_paths` called, diagnostics were expected but none were emitted. \
459 Use `with_no_trimmed_paths` for debugging. {suggestion}"
460 );
461 }
462 }
463 }
464}
465
466impl DiagCtxt {
467 pub fn disable_warnings(mut self) -> Self {
468 self.inner.get_mut().flags.can_emit_warnings = false;
469 self
470 }
471
472 pub fn with_flags(mut self, flags: DiagCtxtFlags) -> Self {
473 self.inner.get_mut().flags = flags;
474 self
475 }
476
477 pub fn with_ice_file(mut self, ice_file: PathBuf) -> Self {
478 self.inner.get_mut().ice_file = Some(ice_file);
479 self
480 }
481
482 pub fn new(emitter: Box<DynEmitter>) -> Self {
483 Self { inner: Lock::new(DiagCtxtInner::new(emitter)) }
484 }
485
486 pub fn make_silent(&self) {
487 let mut inner = self.inner.borrow_mut();
488 inner.emitter = Box::new(emitter::SilentEmitter {});
489 }
490
491 pub fn set_emitter(&self, emitter: Box<dyn Emitter + DynSend>) {
492 self.inner.borrow_mut().emitter = emitter;
493 }
494
495 pub fn can_emit_warnings(&self) -> bool {
499 self.inner.borrow_mut().flags.can_emit_warnings
500 }
501
502 pub fn reset_err_count(&self) {
508 let mut inner = self.inner.borrow_mut();
511 let DiagCtxtInner {
512 flags: _,
513 err_guars,
514 lint_err_guars,
515 delayed_bugs,
516 deduplicated_err_count,
517 deduplicated_warn_count,
518 emitter: _,
519 must_produce_diag,
520 has_printed,
521 suppressed_expected_diag,
522 taught_diagnostics,
523 emitted_diagnostic_codes,
524 emitted_diagnostics,
525 stashed_diagnostics,
526 future_breakage_diagnostics,
527 fulfilled_expectations,
528 ice_file: _,
529 } = inner.deref_mut();
530
531 *err_guars = Default::default();
534 *lint_err_guars = Default::default();
535 *delayed_bugs = Default::default();
536 *deduplicated_err_count = 0;
537 *deduplicated_warn_count = 0;
538 *must_produce_diag = None;
539 *has_printed = false;
540 *suppressed_expected_diag = false;
541 *taught_diagnostics = Default::default();
542 *emitted_diagnostic_codes = Default::default();
543 *emitted_diagnostics = Default::default();
544 *stashed_diagnostics = Default::default();
545 *future_breakage_diagnostics = Default::default();
546 *fulfilled_expectations = Default::default();
547 }
548
549 pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> {
550 DiagCtxtHandle { dcx: self, tainted_with_errors: None }
551 }
552
553 pub fn taintable_handle<'a>(
557 &'a self,
558 tainted_with_errors: &'a Cell<Option<ErrorGuaranteed>>,
559 ) -> DiagCtxtHandle<'a> {
560 DiagCtxtHandle { dcx: self, tainted_with_errors: Some(tainted_with_errors) }
561 }
562}
563
564impl<'a> DiagCtxtHandle<'a> {
565 pub fn stash_diagnostic(
587 &self,
588 span: Span,
589 key: StashKey,
590 diag: DiagInner,
591 ) -> Option<ErrorGuaranteed> {
592 let guar = match diag.level {
593 Bug | Fatal => {
594 self.span_bug(
595 span,
596 ::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),
597 );
598 }
599 Error => Some(self.span_delayed_bug(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("stashing {0:?}", key))
})format!("stashing {key:?}"))),
603 DelayedBug => {
604 return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors);
605 }
606 ForceWarning | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow
607 | Expect => None,
608 };
609
610 self.inner
614 .borrow_mut()
615 .stashed_diagnostics
616 .entry(key)
617 .or_default()
618 .insert(span.with_parent(None), (diag, guar, std::thread::current().id()));
619
620 guar
621 }
622
623 pub fn steal_non_err(self, span: Span, key: StashKey) -> Option<Diag<'a, ()>> {
627 let (diag, guar, _) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
629 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
630 )?;
631 if !!diag.is_error() {
::core::panicking::panic("assertion failed: !diag.is_error()")
};assert!(!diag.is_error());
632 if !guar.is_none() {
::core::panicking::panic("assertion failed: guar.is_none()")
};assert!(guar.is_none());
633 Some(Diag::new_diagnostic(self, diag))
634 }
635
636 pub fn try_steal_modify_and_emit_err<F>(
641 self,
642 span: Span,
643 key: StashKey,
644 mut modify_err: F,
645 ) -> Option<ErrorGuaranteed>
646 where
647 F: FnMut(&mut Diag<'_>),
648 {
649 let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
651 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
652 );
653 err.map(|(err, guar, _)| {
654 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);
656 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
657 let mut err = Diag::<ErrorGuaranteed>::new_diagnostic(self, err);
658 modify_err(&mut err);
659 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);
660 err.emit()
661 })
662 }
663
664 pub fn try_steal_replace_and_emit_err(
668 self,
669 span: Span,
670 key: StashKey,
671 new_err: Diag<'_>,
672 ) -> ErrorGuaranteed {
673 let old_err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
675 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
676 );
677 match old_err {
678 Some((old_err, guar, _)) => {
679 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);
680 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
681 Diag::<ErrorGuaranteed>::new_diagnostic(self, old_err).cancel();
684 }
685 None => {}
686 };
687 new_err.emit()
688 }
689
690 pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool {
691 let inner = self.inner.borrow();
692 if let Some(stashed_diagnostics) = inner.stashed_diagnostics.get(&key)
693 && !stashed_diagnostics.is_empty()
694 {
695 stashed_diagnostics.contains_key(&span.with_parent(None))
696 } else {
697 false
698 }
699 }
700
701 pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
703 self.inner.borrow_mut().emit_stashed_diagnostics()
704 }
705
706 #[inline]
708 pub fn err_count(&self) -> usize {
709 let inner = self.inner.borrow();
710 inner.err_guars.len()
711 + inner.lint_err_guars.len()
712 + inner
713 .stashed_diagnostics
714 .values()
715 .map(|a| a.values().filter(|(_, guar, _)| guar.is_some()).count())
716 .sum::<usize>()
717 }
718
719 pub fn err_count_on_current_thread(&self) -> usize {
724 let inner = self.inner.borrow();
725 let current = std::thread::current().id();
726 inner.err_guars.iter().filter(|(_, thread)| *thread == current).count()
727 + inner.lint_err_guars.iter().filter(|(_, thread)| *thread == current).count()
728 + inner
729 .stashed_diagnostics
730 .values()
731 .map(|a| {
732 a.values()
733 .filter(|(_, guar, thread)| guar.is_some() && *thread == current)
734 .count()
735 })
736 .sum::<usize>()
737 }
738
739 pub fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
742 self.inner.borrow().has_errors_excluding_lint_errors()
743 }
744
745 pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
747 self.inner.borrow().has_errors()
748 }
749
750 pub fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
753 self.inner.borrow().has_errors_or_delayed_bugs()
754 }
755
756 pub fn print_error_count(&self) {
757 let mut inner = self.inner.borrow_mut();
758
759 if !inner.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: inner.stashed_diagnostics.is_empty()")
};assert!(inner.stashed_diagnostics.is_empty());
762
763 if inner.treat_err_as_bug() {
764 return;
765 }
766
767 let warnings = match inner.deduplicated_warn_count {
768 0 => Cow::from(""),
769 1 => Cow::from("1 warning emitted"),
770 count => Cow::from(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} warnings emitted", count))
})format!("{count} warnings emitted")),
771 };
772 let errors = match inner.deduplicated_err_count {
773 0 => Cow::from(""),
774 1 => Cow::from("aborting due to 1 previous error"),
775 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")),
776 };
777
778 match (errors.len(), warnings.len()) {
779 (0, 0) => return,
780 (0, _) => {
781 inner.emit_diagnostic(
784 DiagInner::new(ForceWarning, DiagMessage::Str(warnings)),
785 None,
786 );
787 }
788 (_, 0) => {
789 inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors);
790 }
791 (_, _) => {
792 inner.emit_diagnostic(
793 DiagInner::new(Error, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}; {1}", errors, warnings))
})format!("{errors}; {warnings}")),
794 self.tainted_with_errors,
795 );
796 }
797 }
798
799 let can_show_explain = inner.emitter.should_show_explain();
800 let are_there_diagnostics = !inner.emitted_diagnostic_codes.is_empty();
801 if can_show_explain && are_there_diagnostics {
802 let mut error_codes = inner
803 .emitted_diagnostic_codes
804 .iter()
805 .filter_map(|&code| {
806 if crate::codes::try_find_description(code).is_ok() {
807 Some(code.to_string())
808 } else {
809 None
810 }
811 })
812 .collect::<Vec<_>>();
813 if !error_codes.is_empty() {
814 error_codes.sort();
815 if error_codes.len() > 1 {
816 let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
817 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!(
818 "Some errors have detailed explanations: {}{}",
819 error_codes[..limit].join(", "),
820 if error_codes.len() > 9 { "..." } else { "." }
821 );
822 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!(
823 "For more information about an error, try `rustc --explain {}`.",
824 &error_codes[0]
825 );
826 inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None);
827 inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None);
828 } else {
829 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!(
830 "For more information about this error, try `rustc --explain {}`.",
831 &error_codes[0]
832 );
833 inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None);
834 }
835 }
836 }
837 }
838
839 pub fn abort_if_errors(&self) {
844 if let Some(guar) = self.has_errors() {
845 guar.raise_fatal();
846 }
847 }
848
849 pub fn must_teach(&self, code: ErrCode) -> bool {
855 self.inner.borrow_mut().taught_diagnostics.insert(code)
856 }
857
858 pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
859 self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors)
860 }
861
862 pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
863 self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type);
864 }
865
866 pub fn emit_timing_section_start(&self, record: TimingRecord) {
867 self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start);
868 }
869
870 pub fn emit_timing_section_end(&self, record: TimingRecord) {
871 self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::End);
872 }
873
874 pub fn emit_future_breakage_report(&self) {
875 let inner = &mut *self.inner.borrow_mut();
876 let diags = std::mem::take(&mut inner.future_breakage_diagnostics);
877 if !diags.is_empty() {
878 inner.emitter.emit_future_breakage_report(diags);
879 }
880 }
881
882 pub fn emit_unused_externs(
883 &self,
884 lint_level: rustc_lint_defs::Level,
885 loud: bool,
886 unused_externs: &[&str],
887 ) {
888 let mut inner = self.inner.borrow_mut();
889
890 if loud && lint_level.is_error() {
901 #[allow(deprecated)]
904 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
905 inner.lint_err_guars.push((guar, std::thread::current().id()));
906 inner.panic_if_treat_err_as_bug();
907 }
908
909 inner.emitter.emit_unused_externs(lint_level, unused_externs)
910 }
911
912 #[must_use]
915 pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet<LintExpectationId> {
916 std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations)
917 }
918
919 pub fn flush_delayed(&self) {
924 self.inner.borrow_mut().flush_delayed();
925 }
926
927 #[track_caller]
930 pub fn set_must_produce_diag(&self) {
931 if !self.inner.borrow().must_produce_diag.is_none() {
{
::core::panicking::panic_fmt(format_args!("should only need to collect a backtrace once"));
}
};assert!(
932 self.inner.borrow().must_produce_diag.is_none(),
933 "should only need to collect a backtrace once"
934 );
935 self.inner.borrow_mut().must_produce_diag = Some(Backtrace::capture());
936 }
937}
938
939impl<'a> DiagCtxtHandle<'a> {
944 #[track_caller]
945 pub fn struct_bug(self, msg: impl Into<Cow<'static, str>>) -> Diag<'a, BugAbort> {
946 Diag::new(self, Bug, msg.into())
947 }
948
949 #[track_caller]
950 pub fn bug(self, msg: impl Into<Cow<'static, str>>) -> ! {
951 self.struct_bug(msg).emit()
952 }
953
954 #[track_caller]
955 pub fn struct_span_bug(
956 self,
957 span: impl Into<MultiSpan>,
958 msg: impl Into<Cow<'static, str>>,
959 ) -> Diag<'a, BugAbort> {
960 self.struct_bug(msg).with_span(span)
961 }
962
963 #[track_caller]
964 pub fn span_bug(self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! {
965 self.struct_span_bug(span, msg.into()).emit()
966 }
967
968 #[track_caller]
969 pub fn create_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> Diag<'a, BugAbort> {
970 bug.into_diag(self, Bug)
971 }
972
973 #[track_caller]
974 pub fn emit_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> ! {
975 self.create_bug(bug).emit()
976 }
977
978 #[track_caller]
979 pub fn struct_fatal(self, msg: impl Into<DiagMessage>) -> Diag<'a, FatalAbort> {
980 Diag::new(self, Fatal, msg)
981 }
982
983 #[track_caller]
984 pub fn fatal(self, msg: impl Into<DiagMessage>) -> ! {
985 self.struct_fatal(msg).emit()
986 }
987
988 #[track_caller]
989 pub fn struct_span_fatal(
990 self,
991 span: impl Into<MultiSpan>,
992 msg: impl Into<DiagMessage>,
993 ) -> Diag<'a, FatalAbort> {
994 self.struct_fatal(msg).with_span(span)
995 }
996
997 #[track_caller]
998 pub fn span_fatal(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) -> ! {
999 self.struct_span_fatal(span, msg).emit()
1000 }
1001
1002 #[track_caller]
1003 pub fn create_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> Diag<'a, FatalAbort> {
1004 fatal.into_diag(self, Fatal)
1005 }
1006
1007 #[track_caller]
1008 pub fn emit_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> ! {
1009 self.create_fatal(fatal).emit()
1010 }
1011
1012 #[track_caller]
1013 pub fn create_almost_fatal(
1014 self,
1015 fatal: impl Diagnostic<'a, FatalError>,
1016 ) -> Diag<'a, FatalError> {
1017 fatal.into_diag(self, Fatal)
1018 }
1019
1020 #[track_caller]
1021 pub fn emit_almost_fatal(self, fatal: impl Diagnostic<'a, FatalError>) -> FatalError {
1022 self.create_almost_fatal(fatal).emit()
1023 }
1024
1025 #[track_caller]
1027 pub fn struct_err(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
1028 Diag::new(self, Error, msg)
1029 }
1030
1031 #[track_caller]
1032 pub fn err(self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed {
1033 self.struct_err(msg).emit()
1034 }
1035
1036 #[track_caller]
1037 pub fn struct_span_err(
1038 self,
1039 span: impl Into<MultiSpan>,
1040 msg: impl Into<DiagMessage>,
1041 ) -> Diag<'a> {
1042 self.struct_err(msg).with_span(span)
1043 }
1044
1045 #[track_caller]
1046 pub fn span_err(
1047 self,
1048 span: impl Into<MultiSpan>,
1049 msg: impl Into<DiagMessage>,
1050 ) -> ErrorGuaranteed {
1051 self.struct_span_err(span, msg).emit()
1052 }
1053
1054 #[track_caller]
1055 pub fn create_err(self, err: impl Diagnostic<'a>) -> Diag<'a> {
1056 err.into_diag(self, Error)
1057 }
1058
1059 #[track_caller]
1060 pub fn emit_err(self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
1061 self.create_err(err).emit()
1062 }
1063
1064 #[track_caller]
1066 pub fn delayed_bug(self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed {
1067 Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).emit()
1068 }
1069
1070 #[track_caller]
1075 pub fn span_delayed_bug(
1076 self,
1077 sp: impl Into<MultiSpan>,
1078 msg: impl Into<Cow<'static, str>>,
1079 ) -> ErrorGuaranteed {
1080 Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).with_span(sp).emit()
1081 }
1082
1083 #[track_caller]
1084 pub fn struct_warn(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1085 Diag::new(self, Warning, msg)
1086 }
1087
1088 #[track_caller]
1089 pub fn warn(self, msg: impl Into<DiagMessage>) {
1090 self.struct_warn(msg).emit()
1091 }
1092
1093 #[track_caller]
1094 pub fn struct_span_warn(
1095 self,
1096 span: impl Into<MultiSpan>,
1097 msg: impl Into<DiagMessage>,
1098 ) -> Diag<'a, ()> {
1099 self.struct_warn(msg).with_span(span)
1100 }
1101
1102 #[track_caller]
1103 pub fn span_warn(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1104 self.struct_span_warn(span, msg).emit()
1105 }
1106
1107 #[track_caller]
1108 pub fn create_warn(self, warning: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
1109 warning.into_diag(self, Warning)
1110 }
1111
1112 #[track_caller]
1113 pub fn emit_warn(self, warning: impl Diagnostic<'a, ()>) {
1114 self.create_warn(warning).emit()
1115 }
1116
1117 #[track_caller]
1118 pub fn struct_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1119 Diag::new(self, Note, msg)
1120 }
1121
1122 #[track_caller]
1123 pub fn note(&self, msg: impl Into<DiagMessage>) {
1124 self.struct_note(msg).emit()
1125 }
1126
1127 #[track_caller]
1128 pub fn struct_span_note(
1129 self,
1130 span: impl Into<MultiSpan>,
1131 msg: impl Into<DiagMessage>,
1132 ) -> Diag<'a, ()> {
1133 self.struct_note(msg).with_span(span)
1134 }
1135
1136 #[track_caller]
1137 pub fn span_note(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1138 self.struct_span_note(span, msg).emit()
1139 }
1140
1141 #[track_caller]
1142 pub fn create_note(self, note: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
1143 note.into_diag(self, Note)
1144 }
1145
1146 #[track_caller]
1147 pub fn emit_note(self, note: impl Diagnostic<'a, ()>) {
1148 self.create_note(note).emit()
1149 }
1150
1151 #[track_caller]
1152 pub fn struct_help(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1153 Diag::new(self, Help, msg)
1154 }
1155
1156 #[track_caller]
1157 pub fn struct_failure_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1158 Diag::new(self, FailureNote, msg)
1159 }
1160
1161 #[track_caller]
1162 pub fn struct_allow(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1163 Diag::new(self, Allow, msg)
1164 }
1165
1166 #[track_caller]
1167 pub fn struct_expect(self, msg: impl Into<DiagMessage>, id: LintExpectationId) -> Diag<'a, ()> {
1168 Diag::new(self, Expect, msg).with_lint_id(id)
1169 }
1170}
1171
1172impl DiagCtxtInner {
1177 fn new(emitter: Box<DynEmitter>) -> Self {
1178 Self {
1179 flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
1180 err_guars: Vec::new(),
1181 lint_err_guars: Vec::new(),
1182 delayed_bugs: Vec::new(),
1183 deduplicated_err_count: 0,
1184 deduplicated_warn_count: 0,
1185 emitter,
1186 must_produce_diag: None,
1187 has_printed: false,
1188 suppressed_expected_diag: false,
1189 taught_diagnostics: Default::default(),
1190 emitted_diagnostic_codes: Default::default(),
1191 emitted_diagnostics: Default::default(),
1192 stashed_diagnostics: Default::default(),
1193 future_breakage_diagnostics: Vec::new(),
1194 fulfilled_expectations: Default::default(),
1195 ice_file: None,
1196 }
1197 }
1198
1199 fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
1201 let mut guar = None;
1202 let has_errors = !self.err_guars.is_empty();
1203 for (_, stashed_diagnostics) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
1204 for (_, (diag, _guar, _thread)) in stashed_diagnostics {
1205 if !diag.is_error() {
1206 if !diag.is_force_warn() && has_errors {
1210 continue;
1211 }
1212 }
1213 guar = guar.or(self.emit_diagnostic(diag, None));
1214 }
1215 }
1216 guar
1217 }
1218
1219 fn emit_diagnostic(
1221 &mut self,
1222 mut diagnostic: DiagInner,
1223 taint: Option<&Cell<Option<ErrorGuaranteed>>>,
1224 ) -> Option<ErrorGuaranteed> {
1225 if diagnostic.has_future_breakage() {
1226 {
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);
1230 self.future_breakage_diagnostics.push(diagnostic.clone());
1231 }
1232
1233 match diagnostic.level {
1237 Bug => {}
1238 Fatal | Error => {
1239 if self.treat_next_err_as_bug() {
1240 diagnostic.level = Bug;
1242 }
1243 }
1244 DelayedBug => {
1245 if self.flags.eagerly_emit_delayed_bugs {
1250 if self.treat_next_err_as_bug() {
1252 diagnostic.level = Bug;
1253 } else {
1254 diagnostic.level = Error;
1255 }
1256 } else {
1257 return if let Some(guar) = self.has_errors() {
1260 Some(guar)
1261 } else {
1262 let backtrace = std::backtrace::Backtrace::capture();
1266 #[allow(deprecated)]
1270 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1271 self.delayed_bugs
1272 .push((DelayedDiagInner::with_backtrace(diagnostic, backtrace), guar));
1273 Some(guar)
1274 };
1275 }
1276 }
1277 ForceWarning if diagnostic.lint_id.is_none() => {} Warning => {
1279 if !self.flags.can_emit_warnings {
1280 if diagnostic.has_future_breakage() {
1282 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1284 }
1285 return None;
1286 }
1287 }
1288 Note | Help | FailureNote => {}
1289 OnceNote | OnceHelp => {
::core::panicking::panic_fmt(format_args!("bad level: {0:?}",
diagnostic.level));
}panic!("bad level: {:?}", diagnostic.level),
1290 Allow => {
1291 if diagnostic.has_future_breakage() {
1293 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1295 self.suppressed_expected_diag = true;
1296 }
1297 return None;
1298 }
1299 Expect | ForceWarning => {
1300 self.fulfilled_expectations.insert(diagnostic.lint_id.unwrap());
1301 if let Expect = diagnostic.level {
1302 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1304 self.suppressed_expected_diag = true;
1305 return None;
1306 }
1307 }
1308 }
1309
1310 TRACK_DIAGNOSTIC(diagnostic, &mut |mut diagnostic| {
1311 if let Some(code) = diagnostic.code {
1312 self.emitted_diagnostic_codes.insert(code);
1313 }
1314
1315 let already_emitted = {
1316 let mut hasher = StableHasher::new();
1317 diagnostic.hash(&mut hasher);
1318 let diagnostic_hash = hasher.finish();
1319 !self.emitted_diagnostics.insert(diagnostic_hash)
1320 };
1321
1322 let is_error = diagnostic.is_error();
1323 let is_lint = diagnostic.is_lint.is_some();
1324
1325 if !(self.flags.deduplicate_diagnostics && already_emitted) {
1328 {
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:1328",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1328u32),
::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);
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(&["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);
1330
1331 let not_yet_emitted = |sub: &mut Subdiag| {
1332 {
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:1332",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1332u32),
::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);
1333 if sub.level != OnceNote && sub.level != OnceHelp {
1334 return true;
1335 }
1336 let mut hasher = StableHasher::new();
1337 sub.hash(&mut hasher);
1338 let diagnostic_hash = hasher.finish();
1339 {
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:1339",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1339u32),
::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);
1340 self.emitted_diagnostics.insert(diagnostic_hash)
1341 };
1342 diagnostic.children.retain_mut(not_yet_emitted);
1343 if already_emitted {
1344 let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
1345 diagnostic.sub(Note, msg, MultiSpan::new());
1346 }
1347
1348 if is_error {
1349 self.deduplicated_err_count += 1;
1350 } else if #[allow(non_exhaustive_omitted_patterns)] match diagnostic.level {
ForceWarning | Warning => true,
_ => false,
}matches!(diagnostic.level, ForceWarning | Warning) {
1351 self.deduplicated_warn_count += 1;
1352 }
1353 self.has_printed = true;
1354
1355 self.emitter.emit_diagnostic(diagnostic);
1356 }
1357
1358 if is_error {
1359 if !self.delayed_bugs.is_empty() {
1364 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);
1365 self.delayed_bugs.clear();
1366 self.delayed_bugs.shrink_to_fit();
1367 }
1368
1369 #[allow(deprecated)]
1372 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1373 let thread = std::thread::current().id();
1374 if is_lint {
1375 self.lint_err_guars.push((guar, thread));
1376 } else {
1377 if let Some(taint) = taint {
1378 taint.set(Some(guar));
1379 }
1380 self.err_guars.push((guar, thread));
1381 }
1382 self.panic_if_treat_err_as_bug();
1383 Some(guar)
1384 } else {
1385 None
1386 }
1387 })
1388 }
1389
1390 fn treat_err_as_bug(&self) -> bool {
1391 self.flags
1392 .treat_err_as_bug
1393 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() >= c.get())
1394 }
1395
1396 fn treat_next_err_as_bug(&self) -> bool {
1398 self.flags
1399 .treat_err_as_bug
1400 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() + 1 >= c.get())
1401 }
1402
1403 fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
1404 self.err_guars.get(0).map(|(guar, _)| *guar).or_else(|| {
1405 if let Some((_diag, guar, _)) = self
1406 .stashed_diagnostics
1407 .values()
1408 .flat_map(|stashed_diagnostics| stashed_diagnostics.values())
1409 .find(|(diag, guar, _)| guar.is_some() && diag.is_lint.is_none())
1410 {
1411 *guar
1412 } else {
1413 None
1414 }
1415 })
1416 }
1417
1418 fn has_errors(&self) -> Option<ErrorGuaranteed> {
1419 self.err_guars
1420 .get(0)
1421 .map(|(guar, _)| *guar)
1422 .or_else(|| self.lint_err_guars.get(0).map(|(guar, _)| *guar))
1423 .or_else(|| {
1424 self.stashed_diagnostics.values().find_map(|stashed_diagnostics| {
1425 stashed_diagnostics.values().find_map(|(_, guar, _)| *guar)
1426 })
1427 })
1428 }
1429
1430 fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
1431 self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
1432 }
1433
1434 fn flush_delayed(&mut self) {
1435 if !self.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: self.stashed_diagnostics.is_empty()")
};assert!(self.stashed_diagnostics.is_empty());
1439
1440 if !self.err_guars.is_empty() {
1441 return;
1443 }
1444
1445 if self.delayed_bugs.is_empty() {
1446 return;
1448 }
1449
1450 let bugs: Vec<_> =
1451 std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();
1452
1453 let backtrace = std::env::var_os("RUST_BACKTRACE").as_deref() != Some(OsStr::new("0"));
1454 let decorate = backtrace || self.ice_file.is_none();
1455 let mut out = self
1456 .ice_file
1457 .as_ref()
1458 .and_then(|file| std::fs::File::options().create(true).append(true).open(file).ok());
1459
1460 let note1 = "no errors encountered even though delayed bugs were created";
1465 let note2 = "those delayed bugs will now be shown as internal compiler errors";
1466 self.emit_diagnostic(DiagInner::new(Note, note1), None);
1467 self.emit_diagnostic(DiagInner::new(Note, note2), None);
1468
1469 for bug in bugs {
1470 if let Some(out) = &mut out {
1471 _ = 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!(
1472 out,
1473 "delayed bug: {}\n{}\n",
1474 bug.inner
1475 .messages
1476 .iter()
1477 .filter_map(|(msg, _)| msg.as_str())
1478 .collect::<String>(),
1479 &bug.note
1480 );
1481 }
1482
1483 let mut bug = if decorate { bug.decorate() } else { bug.inner };
1484
1485 if bug.level != DelayedBug {
1487 let msg = rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"))msg!(
1494 "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"
1495 ).arg("level", bug.level).format();
1496 bug.sub(Note, msg, bug.span.primary_span().unwrap().into());
1497 }
1498 bug.level = Bug;
1499
1500 self.emit_diagnostic(bug, None);
1501 }
1502
1503 panic::panic_any(DelayedBugPanic);
1505 }
1506
1507 fn panic_if_treat_err_as_bug(&self) {
1508 if self.treat_err_as_bug() {
1509 let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
1510 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());
1511 if n == 1 {
1512 {
::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`");
1513 } else {
1514 {
::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}`");
1515 }
1516 }
1517 }
1518}
1519
1520struct DelayedDiagInner {
1521 inner: DiagInner,
1522 note: Backtrace,
1523}
1524
1525impl DelayedDiagInner {
1526 fn with_backtrace(diagnostic: DiagInner, backtrace: Backtrace) -> Self {
1527 DelayedDiagInner { inner: diagnostic, note: backtrace }
1528 }
1529
1530 fn decorate(self) -> DiagInner {
1531 let mut diag = self.inner;
1535 let msg = match self.note.status() {
1536 BacktraceStatus::Captured => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at}\n {$note}"))msg!(
1537 "delayed at {$emitted_at}
1538 {$note}"
1539 ),
1540 _ => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at} - {$note}"))msg!("delayed at {$emitted_at} - {$note}"),
1543 }
1544 .arg("emitted_at", diag.emitted_at.clone())
1545 .arg("note", self.note)
1546 .format();
1547 diag.sub(Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
1548 diag
1549 }
1550}
1551
1552#[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_fields_are_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)]
1572pub enum Level {
1573 Bug,
1575
1576 Fatal,
1579
1580 Error,
1583
1584 DelayedBug,
1589
1590 ForceWarning,
1596
1597 Warning,
1600
1601 Note,
1603
1604 OnceNote,
1606
1607 Help,
1609
1610 OnceHelp,
1612
1613 FailureNote,
1616
1617 Allow,
1619
1620 Expect,
1622}
1623
1624impl fmt::Display for Level {
1625 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1626 self.to_str().fmt(f)
1627 }
1628}
1629
1630impl Level {
1631 fn color(self) -> anstyle::Style {
1632 match self {
1633 Bug | Fatal | Error | DelayedBug => AnsiColor::BrightRed.on_default(),
1634 ForceWarning | Warning => {
1635 if falsecfg!(windows) {
1636 AnsiColor::BrightYellow.on_default()
1637 } else {
1638 AnsiColor::Yellow.on_default()
1639 }
1640 }
1641 Note | OnceNote => AnsiColor::BrightGreen.on_default(),
1642 Help | OnceHelp => AnsiColor::BrightCyan.on_default(),
1643 FailureNote => anstyle::Style::new(),
1644 Allow | Expect => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1645 }
1646 }
1647
1648 pub fn to_str(self) -> &'static str {
1649 match self {
1650 Bug | DelayedBug => "error: internal compiler error",
1651 Fatal | Error => "error",
1652 ForceWarning | Warning => "warning",
1653 Note | OnceNote => "note",
1654 Help | OnceHelp => "help",
1655 FailureNote => "failure-note",
1656 Allow | Expect => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1657 }
1658 }
1659
1660 pub fn is_failure_note(&self) -> bool {
1661 #[allow(non_exhaustive_omitted_patterns)] match *self {
FailureNote => true,
_ => false,
}matches!(*self, FailureNote)
1662 }
1663}
1664
1665impl IntoDiagArg for Level {
1666 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
1667 DiagArgValue::Str(Cow::from(self.to_string()))
1668 }
1669}
1670
1671#[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_fields_are_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)]
1672pub enum Style {
1673 MainHeaderMsg,
1674 HeaderMsg,
1675 LineAndColumn,
1676 LineNumber,
1677 Quotation,
1678 UnderlinePrimary,
1679 UnderlineSecondary,
1680 LabelPrimary,
1681 LabelSecondary,
1682 NoStyle,
1683 Level(Level),
1684 Highlight,
1685 Addition,
1686 Removal,
1687}
1688
1689pub fn elided_lifetime_in_path_suggestion(
1691 source_map: &SourceMap,
1692 n: usize,
1693 path_span: Span,
1694 incl_angl_brckt: bool,
1695 insertion_span: Span,
1696) -> ElidedLifetimeInPathSubdiag {
1697 let expected = ExpectedLifetimeParameter { span: path_span, count: n };
1698 let indicate = source_map.is_span_accessible(insertion_span).then(|| {
1700 let anon_lts = ::alloc::vec::from_elem("'_", n)vec!["'_"; n].join(", ");
1701 let suggestion =
1702 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}, ") };
1703
1704 IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }
1705 });
1706
1707 ElidedLifetimeInPathSubdiag { expected, indicate }
1708}
1709
1710pub fn a_or_an(s: &str) -> &'static str {
1714 let mut chars = s.chars();
1715 let Some(mut first_alpha_char) = chars.next() else {
1716 return "a";
1717 };
1718 if first_alpha_char == '`' {
1719 let Some(next) = chars.next() else {
1720 return "a";
1721 };
1722 first_alpha_char = next;
1723 }
1724 if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) {
1725 "an"
1726 } else {
1727 "a"
1728 }
1729}
1730
1731#[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)]
1732pub enum TerminalUrl {
1733 No,
1734 Yes,
1735 Auto,
1736}