1#![cfg_attr(bootstrap, feature(never_type))]
7#![feature(associated_type_defaults)]
8#![feature(default_field_values)]
9#![feature(macro_metavar_expr_concat)]
10#![feature(negative_impls)]
11extern crate self as rustc_errors;
14
15use std::backtrace::{Backtrace, BacktraceStatus};
16use std::borrow::Cow;
17use std::cell::Cell;
18use std::ffi::OsStr;
19use std::hash::Hash;
20use std::io::Write;
21use std::num::NonZero;
22use std::ops::DerefMut;
23use std::path::{Path, PathBuf};
24use std::thread::ThreadId;
25use std::{assert_matches, fmt, mem, panic};
26
27use Level::*;
28pub use anstream::{AutoStream, ColorChoice};
31pub use anstyle::{
32 Ansi256Color, AnsiColor, Color, EffectIter, Effects, Reset, RgbColor, Style as Anstyle,
33};
34pub use codes::*;
35pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer};
36pub use diagnostic::{
37 BugAbort, Diag, DiagDecorator, DiagInner, DiagLocation, DiagStyledString, Diagnostic,
38 EmissionGuarantee, FatalAbort, StringPart, Subdiag, Subdiagnostic,
39};
40pub use diagnostic_impls::{
41 DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,
42 IndicateAnonymousLifetime, SingleLabelManySpans,
43};
44pub use emitter::ColorConfig;
45use emitter::{DynEmitter, Emitter};
46use rustc_ast::attr::version::RustcVersion;
47use rustc_data_structures::AtomicRef;
48use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
49use rustc_data_structures::stable_hash::StableHasher;
50use rustc_data_structures::sync::{DynSend, Lock};
51pub use rustc_error_messages::{
52 DiagArg, DiagArgFromDisplay, DiagArgMap, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg,
53 LanguageIdentifier, MultiSpan, SpanLabel, fluent_bundle, into_diag_arg_using_display,
54};
55use rustc_hashes::Hash128;
56use rustc_lint_defs::LintExpectationId;
57pub use rustc_lint_defs::{Applicability, listify, pluralize};
58pub use rustc_macros::msg;
59use rustc_macros::{Decodable, Encodable};
60pub use rustc_span::ErrorGuaranteed;
61pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors};
62use rustc_span::source_map::SourceMap;
63use rustc_span::{DUMMY_SP, Span};
64use tracing::debug;
65
66use crate::emitter::TimingEvent;
67use crate::formatting::DiagMessageAddArg;
68pub use crate::formatting::format_diag_message;
69use crate::timings::TimingRecord;
70
71pub mod annotate_snippet_emitter_writer;
72pub mod codes;
73mod decorate_diag;
74mod diagnostic;
75mod diagnostic_impls;
76pub mod emitter;
77pub mod formatting;
78pub mod json;
79mod lock;
80pub mod markdown;
81pub mod timings;
82
83pub type PResult<'a, T> = Result<T, Diag<'a>>;
84
85#[cfg(target_pointer_width = "64")]
87const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, ()>>()];rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24);
88#[cfg(target_pointer_width = "64")]
89const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, bool>>()];rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
90
91#[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::marker::StructuralPartialEq for SuggestionStyle { }
#[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]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for SuggestionStyle { }
#[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);
}
}
};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)]
92pub enum SuggestionStyle {
93 HideCodeInline,
95 HideCodeAlways,
97 CompletelyHidden,
99 ShowCode,
103 ShowAlways,
105}
106
107impl SuggestionStyle {
108 fn hide_inline(&self) -> bool {
109 !#[allow(non_exhaustive_omitted_patterns)] match *self {
SuggestionStyle::ShowCode => true,
_ => false,
}matches!(*self, SuggestionStyle::ShowCode)
110 }
111}
112
113#[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::marker::StructuralPartialEq for Suggestions { }
#[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)]
115pub enum Suggestions {
116 Enabled(Vec<CodeSuggestion>),
121 Sealed(Box<[CodeSuggestion]>),
125 Disabled,
129}
130
131impl Suggestions {
132 pub fn unwrap_tag(self) -> Vec<CodeSuggestion> {
134 match self {
135 Suggestions::Enabled(suggestions) => suggestions,
136 Suggestions::Sealed(suggestions) => suggestions.into_vec(),
137 Suggestions::Disabled => Vec::new(),
138 }
139 }
140
141 pub fn len(&self) -> usize {
142 match self {
143 Suggestions::Enabled(suggestions) => suggestions.len(),
144 Suggestions::Sealed(suggestions) => suggestions.len(),
145 Suggestions::Disabled => 0,
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::marker::StructuralPartialEq for CodeSuggestion { }
#[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) {
let CodeSuggestion {
substitutions: ref __binding_0,
msg: ref __binding_1,
style: ref __binding_2,
applicability: ref __binding_3 } = *self;
::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::marker::StructuralPartialEq for Substitution { }
#[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) {
let Substitution { parts: ref __binding_0 } = *self;
::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::marker::StructuralPartialEq for SubstitutionPart { }
#[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) {
let SubstitutionPart {
span: ref __binding_0, snippet: ref __binding_1 } = *self;
::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::marker::StructuralPartialEq for TrimmedSubstitutionPart { }
#[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) {
let TrimmedSubstitutionPart {
original_span: ref __binding_0,
span: ref __binding_1,
snippet: ref __binding_2 } = *self;
::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]
#[doc(hidden)]
unsafe impl<'a> ::core::clone::TrivialClone for DiagCtxtHandle<'a> { }
#[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, ThreadId)>,
301 lint_err_guars: Vec<(ErrorGuaranteed, ThreadId)>,
304 delayed_bugs: Vec<(DelayedDiagInner, ErrorGuaranteed)>,
306
307 deduplicated_err_count: usize,
309 deduplicated_warn_count: usize,
311
312 emitter: Box<DynEmitter>,
313
314 must_produce_diag: Option<Backtrace>,
317
318 has_printed: bool,
321
322 suppressed_expected_diag: bool,
325
326 taught_diagnostics: FxHashSet<ErrCode>,
330
331 emitted_diagnostic_codes: FxIndexSet<ErrCode>,
333
334 emitted_diagnostics: FxHashSet<Hash128>,
338
339 emitted_recursion_depth_exceeding_limit: bool,
347
348 stashed_diagnostics:
354 FxIndexMap<StashKey, FxIndexMap<Span, (DiagInner, Option<ErrorGuaranteed>, ThreadId)>>,
355
356 future_breakage_diagnostics: Vec<DiagInner>,
357
358 fulfilled_expectations: FxIndexSet<LintExpectationId>,
370
371 ice_file: Option<PathBuf>,
374
375 msrv: Option<RustcVersion>,
377}
378
379#[derive(#[automatically_derived]
impl ::core::marker::Copy for StashKey { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for StashKey { }
#[automatically_derived]
impl ::core::clone::Clone for StashKey {
#[inline]
fn clone(&self) -> StashKey { *self }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for StashKey { }
#[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)]
381pub enum StashKey {
382 ItemNoType,
383 UnderscoreForArrayLengths,
384 EarlySyntaxWarning,
385 CallIntoMethod,
386 LifetimeIsChar,
389 MaybeFruTypo,
392 CallAssocMethod,
393 AssociatedTypeSuggestion,
394 UndeterminedMacroResolution,
395 ExprInPat,
397 GenericInFieldExpr,
401 ReturnTypeNotation,
402}
403
404fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
405 (*f)(diag)
406}
407
408pub static TRACK_DIAGNOSTIC: AtomicRef<
411 fn(DiagInner, &mut dyn FnMut(DiagInner) -> Option<ErrorGuaranteed>) -> Option<ErrorGuaranteed>,
412> = AtomicRef::new(&(default_track_diagnostic as _));
413
414#[derive(#[automatically_derived]
impl ::core::marker::Copy for DiagCtxtFlags { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for DiagCtxtFlags { }
#[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)]
415pub struct DiagCtxtFlags {
416 pub can_emit_warnings: bool,
419 pub treat_err_as_bug: Option<NonZero<usize>>,
422 pub eagerly_emit_delayed_bugs: bool,
425 pub macro_backtrace: bool,
428 pub deduplicate_diagnostics: bool,
430 pub track_diagnostics: bool,
432}
433
434impl Drop for DiagCtxtInner {
435 fn drop(&mut self) {
436 self.emit_stashed_diagnostics();
444
445 self.flush_delayed();
449
450 if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
454 if let Some(backtrace) = &self.must_produce_diag {
455 let suggestion = match backtrace.status() {
456 BacktraceStatus::Disabled => String::from(
457 "Backtraces are currently disabled: set `RUST_BACKTRACE=1` and re-run \
458 to see where it happened.",
459 ),
460 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!(
461 "This happened in the following `must_produce_diag` call's backtrace:\n\
462 {backtrace}",
463 ),
464 _ => String::from("(impossible to capture backtrace where this happened)"),
465 };
466 {
::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!(
467 "`trimmed_def_paths` called, diagnostics were expected but none were emitted. \
468 Use `with_no_trimmed_paths` for debugging. {suggestion}"
469 );
470 }
471 }
472 }
473}
474
475impl DiagCtxt {
476 pub fn disable_warnings(mut self) -> Self {
477 self.inner.get_mut().flags.can_emit_warnings = false;
478 self
479 }
480
481 pub fn with_flags(mut self, flags: DiagCtxtFlags) -> Self {
482 self.inner.get_mut().flags = flags;
483 self
484 }
485
486 pub fn with_ice_file(mut self, ice_file: PathBuf) -> Self {
487 self.inner.get_mut().ice_file = Some(ice_file);
488 self
489 }
490
491 pub fn with_msrv(mut self, msrv: RustcVersion) -> Self {
492 self.inner.get_mut().msrv = Some(msrv);
493 self
494 }
495
496 pub fn new(emitter: Box<DynEmitter>) -> Self {
497 Self { inner: Lock::new(DiagCtxtInner::new(emitter)) }
498 }
499
500 pub fn make_silent(&self) {
501 let mut inner = self.inner.borrow_mut();
502 inner.emitter = Box::new(emitter::SilentEmitter {});
503 }
504
505 pub fn set_emitter(&self, emitter: Box<dyn Emitter + DynSend>) {
506 self.inner.borrow_mut().emitter = emitter;
507 }
508
509 pub fn can_emit_warnings(&self) -> bool {
513 self.inner.borrow_mut().flags.can_emit_warnings
514 }
515
516 pub fn reset_err_count(&self) {
522 let mut inner = self.inner.borrow_mut();
525 let DiagCtxtInner {
526 flags: _,
527 err_guars,
528 lint_err_guars,
529 delayed_bugs,
530 deduplicated_err_count,
531 deduplicated_warn_count,
532 emitter: _,
533 must_produce_diag,
534 has_printed,
535 suppressed_expected_diag,
536 taught_diagnostics,
537 emitted_diagnostic_codes,
538 emitted_diagnostics,
539 emitted_recursion_depth_exceeding_limit,
540 stashed_diagnostics,
541 future_breakage_diagnostics,
542 fulfilled_expectations,
543 ice_file: _,
544 msrv: _,
545 } = inner.deref_mut();
546
547 *err_guars = Default::default();
550 *lint_err_guars = Default::default();
551 *delayed_bugs = Default::default();
552 *deduplicated_err_count = 0;
553 *deduplicated_warn_count = 0;
554 *must_produce_diag = None;
555 *has_printed = false;
556 *suppressed_expected_diag = false;
557 *taught_diagnostics = Default::default();
558 *emitted_diagnostic_codes = Default::default();
559 *emitted_diagnostics = Default::default();
560 *emitted_recursion_depth_exceeding_limit = false;
561 *stashed_diagnostics = Default::default();
562 *future_breakage_diagnostics = Default::default();
563 *fulfilled_expectations = Default::default();
564 }
565
566 pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> {
567 DiagCtxtHandle { dcx: self, tainted_with_errors: None }
568 }
569
570 pub fn taintable_handle<'a>(
574 &'a self,
575 tainted_with_errors: &'a Cell<Option<ErrorGuaranteed>>,
576 ) -> DiagCtxtHandle<'a> {
577 DiagCtxtHandle { dcx: self, tainted_with_errors: Some(tainted_with_errors) }
578 }
579}
580
581impl<'a> DiagCtxtHandle<'a> {
582 pub fn stash_diagnostic(
604 &self,
605 span: Span,
606 key: StashKey,
607 diag: DiagInner,
608 ) -> Option<ErrorGuaranteed> {
609 let guar = match diag.level {
610 Bug | Fatal => {
611 self.span_bug(
612 span,
613 ::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),
614 );
615 }
616 Error => Some(self.span_delayed_bug(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("stashing {0:?}", key))
})format!("stashing {key:?}"))),
620 DelayedBug => {
621 return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors);
622 }
623 ForceWarning | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow
624 | Expect => None,
625 };
626
627 self.inner
631 .borrow_mut()
632 .stashed_diagnostics
633 .entry(key)
634 .or_default()
635 .insert(span.with_parent(None), (diag, guar, std::thread::current().id()));
636
637 guar
638 }
639
640 pub fn steal_non_err(self, span: Span, key: StashKey) -> Option<Diag<'a, ()>> {
644 let (diag, guar, _) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
646 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
647 )?;
648 if !!diag.is_error() {
::core::panicking::panic("assertion failed: !diag.is_error()")
};assert!(!diag.is_error());
649 if !guar.is_none() {
::core::panicking::panic("assertion failed: guar.is_none()")
};assert!(guar.is_none());
650 Some(Diag::new_diagnostic(self, diag))
651 }
652
653 pub fn try_steal_modify_and_emit_err<F>(
658 self,
659 span: Span,
660 key: StashKey,
661 mut modify_err: F,
662 ) -> Option<ErrorGuaranteed>
663 where
664 F: FnMut(&mut Diag<'_>),
665 {
666 let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
668 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
669 );
670 err.map(|(err, guar, _)| {
671 {
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);
673 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
674 let mut err = Diag::<ErrorGuaranteed>::new_diagnostic(self, err);
675 modify_err(&mut err);
676 {
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);
677 err.emit()
678 })
679 }
680
681 pub fn try_steal_replace_and_emit_err(
685 self,
686 span: Span,
687 key: StashKey,
688 new_err: Diag<'_>,
689 ) -> ErrorGuaranteed {
690 let old_err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
692 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
693 );
694 match old_err {
695 Some((old_err, guar, _)) => {
696 {
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);
697 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
698 Diag::<ErrorGuaranteed>::new_diagnostic(self, old_err).cancel();
701 }
702 None => {}
703 };
704 new_err.emit()
705 }
706
707 pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool {
708 let inner = self.inner.borrow();
709 if let Some(stashed_diagnostics) = inner.stashed_diagnostics.get(&key)
710 && !stashed_diagnostics.is_empty()
711 {
712 stashed_diagnostics.contains_key(&span.with_parent(None))
713 } else {
714 false
715 }
716 }
717
718 pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
720 self.inner.borrow_mut().emit_stashed_diagnostics()
721 }
722
723 #[inline]
725 pub fn err_count(&self) -> usize {
726 let inner = self.inner.borrow();
727 inner.err_guars.len()
728 + inner.lint_err_guars.len()
729 + inner
730 .stashed_diagnostics
731 .values()
732 .map(|a| a.values().filter(|(_, guar, _)| guar.is_some()).count())
733 .sum::<usize>()
734 }
735
736 pub fn err_count_on_current_thread(&self) -> usize {
741 let inner = self.inner.borrow();
742 let current = std::thread::current().id();
743 inner.err_guars.iter().filter(|(_, thread)| *thread == current).count()
744 + inner.lint_err_guars.iter().filter(|(_, thread)| *thread == current).count()
745 + inner
746 .stashed_diagnostics
747 .values()
748 .map(|a| {
749 a.values()
750 .filter(|(_, guar, thread)| guar.is_some() && *thread == current)
751 .count()
752 })
753 .sum::<usize>()
754 }
755
756 pub fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
759 self.inner.borrow().has_errors_excluding_lint_errors()
760 }
761
762 pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
764 self.inner.borrow().has_errors()
765 }
766
767 pub fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
770 self.inner.borrow().has_errors_or_delayed_bugs()
771 }
772
773 pub fn print_error_count(&self) {
774 let mut inner = self.inner.borrow_mut();
775
776 if !inner.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: inner.stashed_diagnostics.is_empty()")
};assert!(inner.stashed_diagnostics.is_empty());
779
780 if inner.treat_err_as_bug() {
781 return;
782 }
783
784 let warnings = match inner.deduplicated_warn_count {
785 0 => Cow::from(""),
786 1 => Cow::from("1 warning emitted"),
787 count => Cow::from(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} warnings emitted", count))
})format!("{count} warnings emitted")),
788 };
789 let errors = match inner.deduplicated_err_count {
790 0 => Cow::from(""),
791 1 => Cow::from("aborting due to 1 previous error"),
792 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")),
793 };
794
795 match (errors.len(), warnings.len()) {
796 (0, 0) => return,
797 (0, _) => {
798 inner.emit_diagnostic(
801 DiagInner::new(ForceWarning, DiagMessage::Str(warnings)),
802 None,
803 );
804 }
805 (_, 0) => {
806 inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors);
807 }
808 (_, _) => {
809 inner.emit_diagnostic(
810 DiagInner::new(Error, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}; {1}", errors, warnings))
})format!("{errors}; {warnings}")),
811 self.tainted_with_errors,
812 );
813 }
814 }
815
816 let can_show_explain = inner.emitter.should_show_explain();
817 let are_there_diagnostics = !inner.emitted_diagnostic_codes.is_empty();
818 if can_show_explain && are_there_diagnostics {
819 let mut error_codes = inner
820 .emitted_diagnostic_codes
821 .iter()
822 .filter_map(|&code| {
823 if crate::codes::try_find_description(code).is_ok() {
824 Some(code.to_string())
825 } else {
826 None
827 }
828 })
829 .collect::<Vec<_>>();
830 if !error_codes.is_empty() {
831 error_codes.sort();
832 if error_codes.len() > 1 {
833 let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
834 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!(
835 "Some errors have detailed explanations: {}{}",
836 error_codes[..limit].join(", "),
837 if error_codes.len() > 9 { "..." } else { "." }
838 );
839 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!(
840 "For more information about an error, try `rustc --explain {}`.",
841 &error_codes[0]
842 );
843 inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None);
844 inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None);
845 } else {
846 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!(
847 "For more information about this error, try `rustc --explain {}`.",
848 &error_codes[0]
849 );
850 inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None);
851 }
852 }
853 }
854 }
855
856 pub fn abort_if_errors(&self) {
861 if let Some(guar) = self.has_errors() {
862 guar.raise_fatal();
863 }
864 }
865
866 pub fn must_teach(&self, code: ErrCode) -> bool {
872 self.inner.borrow_mut().taught_diagnostics.insert(code)
873 }
874
875 pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
876 self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors)
877 }
878
879 pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
880 self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type);
881 }
882
883 pub fn emit_timing_section_start(&self, record: TimingRecord) {
884 self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start);
885 }
886
887 pub fn emit_timing_section_end(&self, record: TimingRecord) {
888 self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::End);
889 }
890
891 pub fn emit_future_breakage_report(&self) {
892 let inner = &mut *self.inner.borrow_mut();
893 let diags = mem::take(&mut inner.future_breakage_diagnostics);
894 if !diags.is_empty() {
895 inner.emitter.emit_future_breakage_report(diags);
896 }
897 }
898
899 pub fn emit_unused_externs(
900 &self,
901 lint_level: rustc_lint_defs::Level,
902 loud: bool,
903 unused_externs: &[&str],
904 ) {
905 let mut inner = self.inner.borrow_mut();
906
907 if loud && lint_level.is_error() {
918 #[allow(deprecated)]
921 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
922 inner.lint_err_guars.push((guar, std::thread::current().id()));
923 inner.panic_if_treat_err_as_bug();
924 }
925
926 inner.emitter.emit_unused_externs(lint_level, unused_externs)
927 }
928
929 #[must_use]
932 pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet<LintExpectationId> {
933 mem::take(&mut self.inner.borrow_mut().fulfilled_expectations)
934 }
935
936 pub fn flush_delayed(&self) {
941 self.inner.borrow_mut().flush_delayed();
942 }
943
944 #[track_caller]
947 pub fn set_must_produce_diag(&self) {
948 if !self.inner.borrow().must_produce_diag.is_none() {
{
::core::panicking::panic_fmt(format_args!("should only need to collect a backtrace once"));
}
};assert!(
949 self.inner.borrow().must_produce_diag.is_none(),
950 "should only need to collect a backtrace once"
951 );
952 self.inner.borrow_mut().must_produce_diag = Some(Backtrace::capture());
953 }
954}
955
956impl<'a> DiagCtxtHandle<'a> {
961 #[track_caller]
962 pub fn struct_bug(self, msg: impl Into<Cow<'static, str>>) -> Diag<'a, BugAbort> {
963 Diag::new(self, Bug, msg.into())
964 }
965
966 #[track_caller]
967 pub fn bug(self, msg: impl Into<Cow<'static, str>>) -> ! {
968 self.struct_bug(msg).emit()
969 }
970
971 #[track_caller]
972 pub fn struct_span_bug(
973 self,
974 span: impl Into<MultiSpan>,
975 msg: impl Into<Cow<'static, str>>,
976 ) -> Diag<'a, BugAbort> {
977 self.struct_bug(msg).with_span(span)
978 }
979
980 #[track_caller]
981 pub fn span_bug(self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! {
982 self.struct_span_bug(span, msg.into()).emit()
983 }
984
985 #[track_caller]
986 pub fn create_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> Diag<'a, BugAbort> {
987 bug.into_diag(self, Bug)
988 }
989
990 #[track_caller]
991 pub fn emit_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> ! {
992 self.create_bug(bug).emit()
993 }
994
995 #[track_caller]
996 pub fn struct_fatal(self, msg: impl Into<DiagMessage>) -> Diag<'a, FatalAbort> {
997 Diag::new(self, Fatal, msg)
998 }
999
1000 #[track_caller]
1001 pub fn fatal(self, msg: impl Into<DiagMessage>) -> ! {
1002 self.struct_fatal(msg).emit()
1003 }
1004
1005 #[track_caller]
1006 pub fn struct_span_fatal(
1007 self,
1008 span: impl Into<MultiSpan>,
1009 msg: impl Into<DiagMessage>,
1010 ) -> Diag<'a, FatalAbort> {
1011 self.struct_fatal(msg).with_span(span)
1012 }
1013
1014 #[track_caller]
1015 pub fn span_fatal(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) -> ! {
1016 self.struct_span_fatal(span, msg).emit()
1017 }
1018
1019 #[track_caller]
1020 pub fn create_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> Diag<'a, FatalAbort> {
1021 fatal.into_diag(self, Fatal)
1022 }
1023
1024 #[track_caller]
1025 pub fn emit_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> ! {
1026 self.create_fatal(fatal).emit()
1027 }
1028
1029 #[track_caller]
1030 pub fn create_almost_fatal(
1031 self,
1032 fatal: impl Diagnostic<'a, FatalError>,
1033 ) -> Diag<'a, FatalError> {
1034 fatal.into_diag(self, Fatal)
1035 }
1036
1037 #[track_caller]
1038 pub fn emit_almost_fatal(self, fatal: impl Diagnostic<'a, FatalError>) -> FatalError {
1039 self.create_almost_fatal(fatal).emit()
1040 }
1041
1042 #[track_caller]
1044 pub fn struct_err(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
1045 Diag::new(self, Error, msg)
1046 }
1047
1048 #[track_caller]
1049 pub fn err(self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed {
1050 self.struct_err(msg).emit()
1051 }
1052
1053 #[track_caller]
1054 pub fn struct_span_err(
1055 self,
1056 span: impl Into<MultiSpan>,
1057 msg: impl Into<DiagMessage>,
1058 ) -> Diag<'a> {
1059 self.struct_err(msg).with_span(span)
1060 }
1061
1062 #[track_caller]
1063 pub fn span_err(
1064 self,
1065 span: impl Into<MultiSpan>,
1066 msg: impl Into<DiagMessage>,
1067 ) -> ErrorGuaranteed {
1068 self.struct_span_err(span, msg).emit()
1069 }
1070
1071 #[track_caller]
1072 pub fn create_err(self, err: impl Diagnostic<'a>) -> Diag<'a> {
1073 err.into_diag(self, Error)
1074 }
1075
1076 #[track_caller]
1077 pub fn emit_err(self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
1078 self.create_err(err).emit()
1079 }
1080
1081 #[track_caller]
1083 pub fn delayed_bug(self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed {
1084 Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).emit()
1085 }
1086
1087 #[track_caller]
1092 pub fn span_delayed_bug(
1093 self,
1094 sp: impl Into<MultiSpan>,
1095 msg: impl Into<Cow<'static, str>>,
1096 ) -> ErrorGuaranteed {
1097 Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).with_span(sp).emit()
1098 }
1099
1100 #[track_caller]
1101 pub fn struct_warn(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1102 Diag::new(self, Warning, msg)
1103 }
1104
1105 #[track_caller]
1106 pub fn warn(self, msg: impl Into<DiagMessage>) {
1107 self.struct_warn(msg).emit()
1108 }
1109
1110 #[track_caller]
1111 pub fn struct_span_warn(
1112 self,
1113 span: impl Into<MultiSpan>,
1114 msg: impl Into<DiagMessage>,
1115 ) -> Diag<'a, ()> {
1116 self.struct_warn(msg).with_span(span)
1117 }
1118
1119 #[track_caller]
1120 pub fn span_warn(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1121 self.struct_span_warn(span, msg).emit()
1122 }
1123
1124 #[track_caller]
1125 pub fn create_warn(self, warning: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
1126 warning.into_diag(self, Warning)
1127 }
1128
1129 #[track_caller]
1130 pub fn emit_warn(self, warning: impl Diagnostic<'a, ()>) {
1131 self.create_warn(warning).emit()
1132 }
1133
1134 #[track_caller]
1135 pub fn struct_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1136 Diag::new(self, Note, msg)
1137 }
1138
1139 #[track_caller]
1140 pub fn note(&self, msg: impl Into<DiagMessage>) {
1141 self.struct_note(msg).emit()
1142 }
1143
1144 #[track_caller]
1145 pub fn struct_span_note(
1146 self,
1147 span: impl Into<MultiSpan>,
1148 msg: impl Into<DiagMessage>,
1149 ) -> Diag<'a, ()> {
1150 self.struct_note(msg).with_span(span)
1151 }
1152
1153 #[track_caller]
1154 pub fn span_note(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1155 self.struct_span_note(span, msg).emit()
1156 }
1157
1158 #[track_caller]
1159 pub fn create_note(self, note: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
1160 note.into_diag(self, Note)
1161 }
1162
1163 #[track_caller]
1164 pub fn emit_note(self, note: impl Diagnostic<'a, ()>) {
1165 self.create_note(note).emit()
1166 }
1167
1168 #[track_caller]
1169 pub fn struct_help(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1170 Diag::new(self, Help, msg)
1171 }
1172
1173 #[track_caller]
1174 pub fn struct_failure_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1175 Diag::new(self, FailureNote, msg)
1176 }
1177
1178 #[track_caller]
1179 pub fn struct_allow(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1180 Diag::new(self, Allow, msg)
1181 }
1182
1183 #[track_caller]
1184 pub fn struct_expect(self, msg: impl Into<DiagMessage>, id: LintExpectationId) -> Diag<'a, ()> {
1185 Diag::new(self, Expect, msg).with_lint_id(id)
1186 }
1187}
1188
1189impl DiagCtxtInner {
1194 fn new(emitter: Box<DynEmitter>) -> Self {
1195 Self {
1196 flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
1197 err_guars: Vec::new(),
1198 lint_err_guars: Vec::new(),
1199 delayed_bugs: Vec::new(),
1200 deduplicated_err_count: 0,
1201 deduplicated_warn_count: 0,
1202 emitter,
1203 must_produce_diag: None,
1204 has_printed: false,
1205 suppressed_expected_diag: false,
1206 taught_diagnostics: Default::default(),
1207 emitted_diagnostic_codes: Default::default(),
1208 emitted_diagnostics: Default::default(),
1209 emitted_recursion_depth_exceeding_limit: false,
1210 stashed_diagnostics: Default::default(),
1211 future_breakage_diagnostics: Vec::new(),
1212 fulfilled_expectations: Default::default(),
1213 ice_file: None,
1214 msrv: None,
1215 }
1216 }
1217
1218 fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
1220 let mut guar = None;
1221 let has_errors = !self.err_guars.is_empty();
1222 for (_, stashed_diagnostics) in mem::take(&mut self.stashed_diagnostics).into_iter() {
1223 for (_, (diag, _guar, _thread)) in stashed_diagnostics {
1224 if !diag.is_error() {
1225 if !diag.is_force_warn() && has_errors {
1229 continue;
1230 }
1231 }
1232 guar = guar.or(self.emit_diagnostic(diag, None));
1233 }
1234 }
1235 guar
1236 }
1237
1238 fn emit_diagnostic(
1240 &mut self,
1241 mut diagnostic: DiagInner,
1242 taint: Option<&Cell<Option<ErrorGuaranteed>>>,
1243 ) -> Option<ErrorGuaranteed> {
1244 if diagnostic.has_future_breakage() {
1245 {
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);
1249 self.future_breakage_diagnostics.push(diagnostic.clone());
1250 }
1251
1252 match diagnostic.level {
1256 Bug => {}
1257 Fatal | Error => {
1258 if self.treat_next_err_as_bug() {
1259 diagnostic.level = Bug;
1261 }
1262 }
1263 DelayedBug => {
1264 if self.flags.eagerly_emit_delayed_bugs {
1269 if self.treat_next_err_as_bug() {
1271 diagnostic.level = Bug;
1272 } else {
1273 diagnostic.level = Error;
1274 }
1275 } else {
1276 return if let Some(guar) = self.has_errors() {
1279 Some(guar)
1280 } else {
1281 let backtrace = std::backtrace::Backtrace::capture();
1285 #[allow(deprecated)]
1289 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1290 self.delayed_bugs
1291 .push((DelayedDiagInner::with_backtrace(diagnostic, backtrace), guar));
1292 Some(guar)
1293 };
1294 }
1295 }
1296 ForceWarning if diagnostic.lint_id.is_none() => {} Warning => {
1298 if !self.flags.can_emit_warnings {
1299 if diagnostic.has_future_breakage() {
1301 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1303 }
1304 return None;
1305 }
1306 }
1307 Note | Help | FailureNote => {}
1308 OnceNote | OnceHelp => {
::core::panicking::panic_fmt(format_args!("bad level: {0:?}",
diagnostic.level));
}panic!("bad level: {:?}", diagnostic.level),
1309 Allow => {
1310 if diagnostic.has_future_breakage() {
1312 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1314 self.suppressed_expected_diag = true;
1315 }
1316 return None;
1317 }
1318 Expect | ForceWarning => {
1319 self.fulfilled_expectations.insert(diagnostic.lint_id.unwrap());
1320 if let Expect = diagnostic.level {
1321 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1323 self.suppressed_expected_diag = true;
1324 return None;
1325 }
1326 }
1327 }
1328
1329 if let (Some(msrv), Some(diag_msrv)) = (self.msrv, diagnostic.rust_version())
1330 && diag_msrv > msrv
1331 {
1332 return None;
1333 }
1334
1335 TRACK_DIAGNOSTIC(diagnostic, &mut |mut diagnostic| {
1336 if let Some(code) = diagnostic.code {
1337 self.emitted_diagnostic_codes.insert(code);
1338 }
1339
1340 let already_emitted = {
1341 let mut hasher = StableHasher::new();
1342 diagnostic.hash(&mut hasher);
1343 let diagnostic_hash = hasher.finish();
1344 !self.emitted_diagnostics.insert(diagnostic_hash)
1345 };
1346
1347 let is_error = diagnostic.is_error();
1348 let is_lint = diagnostic.is_lint.is_some();
1349 let silence_recursion_depth_exceeded_limit =
1351 diagnostic.is_lint.as_ref().is_some_and(|lint| {
1352 lint.name.eq_ignore_ascii_case(
1353 rustc_lint_defs::builtin::RECURSION_DEPTH_EXCEEDING_LIMIT.name,
1354 ) && mem::replace(&mut self.emitted_recursion_depth_exceeding_limit, true)
1355 });
1356
1357 if !silence_recursion_depth_exceeded_limit
1360 && !(self.flags.deduplicate_diagnostics && already_emitted)
1361 {
1362 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/0ed41eb4142dda2df61eb1145a312c1a9d62eb56/compiler/rustc_errors/src/lib.rs:1362",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0ed41eb4142dda2df61eb1145a312c1a9d62eb56/compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1362u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("diagnostic")
}> =
::tracing::__macro_support::FieldName::new("diagnostic");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&diagnostic)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?diagnostic);
1363 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/0ed41eb4142dda2df61eb1145a312c1a9d62eb56/compiler/rustc_errors/src/lib.rs:1363",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0ed41eb4142dda2df61eb1145a312c1a9d62eb56/compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1363u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("self.emitted_diagnostics")
}> =
::tracing::__macro_support::FieldName::new("self.emitted_diagnostics");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.emitted_diagnostics)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?self.emitted_diagnostics);
1364
1365 let not_yet_emitted = |sub: &mut Subdiag| {
1366 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/0ed41eb4142dda2df61eb1145a312c1a9d62eb56/compiler/rustc_errors/src/lib.rs:1366",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0ed41eb4142dda2df61eb1145a312c1a9d62eb56/compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1366u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("sub")
}> =
::tracing::__macro_support::FieldName::new("sub");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sub)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?sub);
1367 if sub.level != OnceNote && sub.level != OnceHelp {
1368 return true;
1369 }
1370 let mut hasher = StableHasher::new();
1371 sub.hash(&mut hasher);
1372 let diagnostic_hash = hasher.finish();
1373 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/0ed41eb4142dda2df61eb1145a312c1a9d62eb56/compiler/rustc_errors/src/lib.rs:1373",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0ed41eb4142dda2df61eb1145a312c1a9d62eb56/compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1373u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("diagnostic_hash")
}> =
::tracing::__macro_support::FieldName::new("diagnostic_hash");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&diagnostic_hash)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?diagnostic_hash);
1374 self.emitted_diagnostics.insert(diagnostic_hash)
1375 };
1376 diagnostic.children.retain_mut(not_yet_emitted);
1377 if already_emitted {
1378 let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
1379 diagnostic.sub(Note, msg, MultiSpan::new());
1380 }
1381
1382 if is_error {
1383 self.deduplicated_err_count += 1;
1384 } else if #[allow(non_exhaustive_omitted_patterns)] match diagnostic.level {
ForceWarning | Warning => true,
_ => false,
}matches!(diagnostic.level, ForceWarning | Warning) {
1385 self.deduplicated_warn_count += 1;
1386 }
1387 self.has_printed = true;
1388
1389 self.emitter.emit_diagnostic(diagnostic);
1390 }
1391
1392 if is_error {
1393 if !self.delayed_bugs.is_empty() {
1398 {
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);
1399 self.delayed_bugs.clear();
1400 self.delayed_bugs.shrink_to_fit();
1401 }
1402
1403 #[allow(deprecated)]
1406 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1407 let thread = std::thread::current().id();
1408 if is_lint {
1409 self.lint_err_guars.push((guar, thread));
1410 } else {
1411 if let Some(taint) = taint {
1412 taint.set(Some(guar));
1413 }
1414 self.err_guars.push((guar, thread));
1415 }
1416 self.panic_if_treat_err_as_bug();
1417 Some(guar)
1418 } else {
1419 None
1420 }
1421 })
1422 }
1423
1424 fn treat_err_as_bug(&self) -> bool {
1425 self.flags
1426 .treat_err_as_bug
1427 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() >= c.get())
1428 }
1429
1430 fn treat_next_err_as_bug(&self) -> bool {
1432 self.flags
1433 .treat_err_as_bug
1434 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() + 1 >= c.get())
1435 }
1436
1437 fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
1438 self.err_guars.get(0).map(|(guar, _)| *guar).or_else(|| {
1439 if let Some((_diag, guar, _)) = self
1440 .stashed_diagnostics
1441 .values()
1442 .flat_map(|stashed_diagnostics| stashed_diagnostics.values())
1443 .find(|(diag, guar, _)| guar.is_some() && diag.is_lint.is_none())
1444 {
1445 *guar
1446 } else {
1447 None
1448 }
1449 })
1450 }
1451
1452 fn has_errors(&self) -> Option<ErrorGuaranteed> {
1453 self.err_guars
1454 .get(0)
1455 .map(|(guar, _)| *guar)
1456 .or_else(|| self.lint_err_guars.get(0).map(|(guar, _)| *guar))
1457 .or_else(|| {
1458 self.stashed_diagnostics.values().find_map(|stashed_diagnostics| {
1459 stashed_diagnostics.values().find_map(|(_, guar, _)| *guar)
1460 })
1461 })
1462 }
1463
1464 fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
1465 self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
1466 }
1467
1468 fn flush_delayed(&mut self) {
1469 if !self.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: self.stashed_diagnostics.is_empty()")
};assert!(self.stashed_diagnostics.is_empty());
1473
1474 if !self.err_guars.is_empty() {
1475 return;
1477 }
1478
1479 if self.delayed_bugs.is_empty() {
1480 return;
1482 }
1483
1484 let bugs: Vec<_> = mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();
1485
1486 let backtrace = std::env::var_os("RUST_BACKTRACE").as_deref() != Some(OsStr::new("0"));
1487 let decorate = backtrace || self.ice_file.is_none();
1488 let mut out = self
1489 .ice_file
1490 .as_ref()
1491 .and_then(|file| std::fs::File::options().create(true).append(true).open(file).ok());
1492
1493 let note1 = "no errors encountered even though delayed bugs were created";
1498 let note2 = "those delayed bugs will now be shown as internal compiler errors";
1499 self.emit_diagnostic(DiagInner::new(Note, note1), None);
1500 self.emit_diagnostic(DiagInner::new(Note, note2), None);
1501
1502 for bug in bugs {
1503 if let Some(out) = &mut out {
1504 _ = 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!(
1505 out,
1506 "delayed bug: {}\n{}\n",
1507 bug.inner
1508 .messages
1509 .iter()
1510 .filter_map(|(msg, _)| msg.as_str())
1511 .collect::<String>(),
1512 &bug.note
1513 );
1514 }
1515
1516 let mut bug = if decorate { bug.decorate() } else { bug.inner };
1517
1518 if bug.level != DelayedBug {
1520 let msg = rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"))msg!(
1527 "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"
1528 ).arg("level", bug.level).format();
1529 bug.sub(Note, msg, bug.span.primary_span().unwrap().into());
1530 }
1531 bug.level = Bug;
1532
1533 self.emit_diagnostic(bug, None);
1534 }
1535
1536 panic::panic_any(DelayedBugPanic);
1538 }
1539
1540 fn panic_if_treat_err_as_bug(&self) {
1541 if self.treat_err_as_bug() {
1542 let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
1543 {
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());
1544 if n == 1 {
1545 {
::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`");
1546 } else {
1547 {
::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}`");
1548 }
1549 }
1550 }
1551}
1552
1553struct DelayedDiagInner {
1554 inner: DiagInner,
1555 note: Backtrace,
1556}
1557
1558impl DelayedDiagInner {
1559 fn with_backtrace(diagnostic: DiagInner, backtrace: Backtrace) -> Self {
1560 DelayedDiagInner { inner: diagnostic, note: backtrace }
1561 }
1562
1563 fn decorate(self) -> DiagInner {
1564 let mut diag = self.inner;
1568 let msg = match self.note.status() {
1569 BacktraceStatus::Captured => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at}\n {$note}"))msg!(
1570 "delayed at {$emitted_at}
1571 {$note}"
1572 ),
1573 _ => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at} - {$note}"))msg!("delayed at {$emitted_at} - {$note}"),
1576 }
1577 .arg("emitted_at", diag.emitted_at.clone())
1578 .arg("note", self.note)
1579 .format();
1580 diag.sub(Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
1581 diag
1582 }
1583}
1584
1585#[derive(#[automatically_derived]
impl ::core::marker::Copy for Level { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Level { }
#[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]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Level { }
#[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);
}
}
};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)]
1605pub enum Level {
1606 Bug,
1608
1609 Fatal,
1612
1613 Error,
1616
1617 DelayedBug,
1622
1623 ForceWarning,
1629
1630 Warning,
1633
1634 Note,
1636
1637 OnceNote,
1639
1640 Help,
1642
1643 OnceHelp,
1645
1646 FailureNote,
1649
1650 Allow,
1652
1653 Expect,
1655}
1656
1657impl fmt::Display for Level {
1658 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1659 self.to_str().fmt(f)
1660 }
1661}
1662
1663impl Level {
1664 fn color(self) -> anstyle::Style {
1665 match self {
1666 Bug | Fatal | Error | DelayedBug => AnsiColor::BrightRed.on_default(),
1667 ForceWarning | Warning => {
1668 if falsecfg!(windows) {
1669 AnsiColor::BrightYellow.on_default()
1670 } else {
1671 AnsiColor::Yellow.on_default()
1672 }
1673 }
1674 Note | OnceNote => AnsiColor::BrightGreen.on_default(),
1675 Help | OnceHelp => AnsiColor::BrightCyan.on_default(),
1676 FailureNote => anstyle::Style::new(),
1677 Allow | Expect => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1678 }
1679 }
1680
1681 pub fn to_str(self) -> &'static str {
1682 match self {
1683 Bug | DelayedBug => "error: internal compiler error",
1684 Fatal | Error => "error",
1685 ForceWarning | Warning => "warning",
1686 Note | OnceNote => "note",
1687 Help | OnceHelp => "help",
1688 FailureNote => "failure-note",
1689 Allow | Expect => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1690 }
1691 }
1692
1693 pub fn is_failure_note(&self) -> bool {
1694 #[allow(non_exhaustive_omitted_patterns)] match *self {
FailureNote => true,
_ => false,
}matches!(*self, FailureNote)
1695 }
1696}
1697
1698impl IntoDiagArg for Level {
1699 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
1700 DiagArgValue::Str(Cow::from(self.to_string()))
1701 }
1702}
1703
1704#[derive(#[automatically_derived]
impl ::core::marker::Copy for Style { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Style { }
#[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::marker::StructuralPartialEq for Style { }
#[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)]
1705pub enum Style {
1706 MainHeaderMsg,
1707 HeaderMsg,
1708 LineAndColumn,
1709 LineNumber,
1710 Quotation,
1711 UnderlinePrimary,
1712 UnderlineSecondary,
1713 LabelPrimary,
1714 LabelSecondary,
1715 NoStyle,
1716 Level(Level),
1717 Highlight,
1718 Addition,
1719 Removal,
1720}
1721
1722pub fn elided_lifetime_in_path_suggestion(
1724 source_map: &SourceMap,
1725 n: usize,
1726 path_span: Span,
1727 incl_angl_brckt: bool,
1728 insertion_span: Span,
1729) -> ElidedLifetimeInPathSubdiag {
1730 let expected = ExpectedLifetimeParameter { span: path_span, count: n };
1731 let indicate = source_map.is_span_accessible(insertion_span).then(|| {
1733 let anon_lts = ::alloc::vec::from_elem("'_", n)vec!["'_"; n].join(", ");
1734 let suggestion =
1735 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}, ") };
1736
1737 IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }
1738 });
1739
1740 ElidedLifetimeInPathSubdiag { expected, indicate }
1741}
1742
1743pub fn a_or_an(s: &str) -> &'static str {
1747 let mut chars = s.chars();
1748 let Some(mut first_alpha_char) = chars.next() else {
1749 return "a";
1750 };
1751 if first_alpha_char == '`' {
1752 let Some(next) = chars.next() else {
1753 return "a";
1754 };
1755 first_alpha_char = next;
1756 }
1757 if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) {
1758 "an"
1759 } else {
1760 "a"
1761 }
1762}
1763
1764#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for TerminalUrl { }
#[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::marker::StructuralPartialEq for TerminalUrl { }
#[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)]
1765pub enum TerminalUrl {
1766 No,
1767 Yes,
1768 Auto,
1769}