1#![feature(default_field_values)]
7#![feature(macro_metavar_expr_concat)]
8#![feature(negative_impls)]
9extern crate self as rustc_errors;
12
13use std::backtrace::{Backtrace, BacktraceStatus};
14use std::borrow::Cow;
15use std::cell::Cell;
16use std::ffi::OsStr;
17use std::hash::Hash;
18use std::io::Write;
19use std::num::NonZero;
20use std::ops::DerefMut;
21use std::path::{Path, PathBuf};
22use std::thread::ThreadId;
23use std::{assert_matches, fmt, mem, panic};
24
25use Level::*;
26pub use anstream::{AutoStream, ColorChoice};
29pub use anstyle::{
30 Ansi256Color, AnsiColor, Color, EffectIter, Effects, Reset, RgbColor, Style as Anstyle,
31};
32pub use codes::*;
33pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer};
34pub use diagnostic::{
35 BugAbort, Diag, DiagDecorator, DiagInner, DiagLocation, DiagStyledString, Diagnostic,
36 FatalAbort, StringPart, Subdiag, Subdiagnostic,
37};
38pub use diagnostic_impls::{
39 DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,
40 IndicateAnonymousLifetime, SingleLabelManySpans,
41};
42pub use emitter::ColorConfig;
43use emitter::{DynEmitter, Emitter};
44use rustc_ast::attr::version::RustcVersion;
45use rustc_data_structures::AtomicRef;
46use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
47use rustc_data_structures::stable_hash::StableHasher;
48use rustc_data_structures::sync::{DynSend, Lock};
49pub use rustc_error_messages::{
50 DiagArg, DiagArgFromDisplay, DiagArgMap, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg,
51 LanguageIdentifier, MultiSpan, SpanLabel, fluent_bundle, into_diag_arg_using_display,
52};
53use rustc_hashes::Hash128;
54use rustc_lint_defs::LintExpectationId;
55pub use rustc_lint_defs::{Applicability, listify, pluralize};
56pub use rustc_macros::msg;
57use rustc_macros::{Decodable, Encodable};
58pub use rustc_span::ErrorGuaranteed;
59pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors};
60use rustc_span::source_map::SourceMap;
61use rustc_span::{DUMMY_SP, Span};
62use tracing::debug;
63
64use crate::emitter::TimingEvent;
65use crate::formatting::DiagMessageAddArg;
66pub use crate::formatting::format_diag_message;
67use crate::timings::TimingRecord;
68
69pub mod annotate_snippet_emitter_writer;
70pub mod codes;
71mod decorate_diag;
72mod diagnostic;
73mod diagnostic_impls;
74pub mod emitter;
75pub mod formatting;
76pub mod json;
77mod lock;
78pub mod markdown;
79pub mod timings;
80
81pub type PResult<'a, T> = Result<T, Diag<'a>>;
82
83#[cfg(target_pointer_width = "64")]
85const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, ()>>()];rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24);
86#[cfg(target_pointer_width = "64")]
87const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, bool>>()];rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
88
89#[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 { }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)]
90pub enum SuggestionStyle {
91 HideCodeInline,
93 HideCodeAlways,
95 CompletelyHidden,
97 ShowCode,
101 ShowAlways,
103}
104
105impl SuggestionStyle {
106 fn hide_inline(&self) -> bool {
107 !#[allow(non_exhaustive_omitted_patterns)] match *self {
SuggestionStyle::ShowCode => true,
_ => false,
}matches!(*self, SuggestionStyle::ShowCode)
108 }
109}
110
111#[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)]
113pub enum Suggestions {
114 Enabled(Vec<CodeSuggestion>),
119 Sealed(Box<[CodeSuggestion]>),
123 Disabled,
127}
128
129impl Suggestions {
130 pub fn unwrap_tag(self) -> Vec<CodeSuggestion> {
132 match self {
133 Suggestions::Enabled(suggestions) => suggestions,
134 Suggestions::Sealed(suggestions) => suggestions.into_vec(),
135 Suggestions::Disabled => Vec::new(),
136 }
137 }
138
139 pub fn len(&self) -> usize {
140 match self {
141 Suggestions::Enabled(suggestions) => suggestions.len(),
142 Suggestions::Sealed(suggestions) => suggestions.len(),
143 Suggestions::Disabled => 0,
144 }
145 }
146}
147
148impl Default for Suggestions {
149 fn default() -> Self {
150 Self::Enabled(::alloc::vec::Vec::new()vec![])
151 }
152}
153
154#[derive(#[automatically_derived]
impl ::core::clone::Clone for CodeSuggestion {
#[inline]
fn clone(&self) -> CodeSuggestion {
CodeSuggestion {
substitutions: ::core::clone::Clone::clone(&self.substitutions),
msg: ::core::clone::Clone::clone(&self.msg),
style: ::core::clone::Clone::clone(&self.style),
applicability: ::core::clone::Clone::clone(&self.applicability),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for CodeSuggestion {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"CodeSuggestion", "substitutions", &self.substitutions, "msg",
&self.msg, "style", &self.style, "applicability",
&&self.applicability)
}
}Debug, #[automatically_derived]
impl ::core::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)]
155pub struct CodeSuggestion {
156 pub substitutions: Vec<Substitution>,
178 pub msg: DiagMessage,
179 pub style: SuggestionStyle,
181 pub applicability: Applicability,
187}
188
189#[derive(#[automatically_derived]
impl ::core::clone::Clone for Substitution {
#[inline]
fn clone(&self) -> Substitution {
Substitution { parts: ::core::clone::Clone::clone(&self.parts) }
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Substitution {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "Substitution",
"parts", &&self.parts)
}
}Debug, #[automatically_derived]
impl ::core::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)]
190pub struct Substitution {
192 pub parts: Vec<SubstitutionPart>,
193}
194
195#[derive(#[automatically_derived]
impl ::core::clone::Clone for SubstitutionPart {
#[inline]
fn clone(&self) -> SubstitutionPart {
SubstitutionPart {
span: ::core::clone::Clone::clone(&self.span),
snippet: ::core::clone::Clone::clone(&self.snippet),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for SubstitutionPart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"SubstitutionPart", "span", &self.span, "snippet", &&self.snippet)
}
}Debug, #[automatically_derived]
impl ::core::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)]
196pub struct SubstitutionPart {
197 pub span: Span,
198 pub snippet: String,
199}
200
201#[derive(#[automatically_derived]
impl ::core::clone::Clone for TrimmedSubstitutionPart {
#[inline]
fn clone(&self) -> TrimmedSubstitutionPart {
TrimmedSubstitutionPart {
original_span: ::core::clone::Clone::clone(&self.original_span),
span: ::core::clone::Clone::clone(&self.span),
snippet: ::core::clone::Clone::clone(&self.snippet),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for TrimmedSubstitutionPart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"TrimmedSubstitutionPart", "original_span", &self.original_span,
"span", &self.span, "snippet", &&self.snippet)
}
}Debug, #[automatically_derived]
impl ::core::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)]
202pub struct TrimmedSubstitutionPart {
203 pub original_span: Span,
204 pub span: Span,
205 pub snippet: String,
206}
207
208impl TrimmedSubstitutionPart {
209 pub fn is_addition(&self, sm: &SourceMap) -> bool {
210 !self.snippet.is_empty() && !self.replaces_meaningful_content(sm)
211 }
212
213 pub fn is_deletion(&self, sm: &SourceMap) -> bool {
214 self.snippet.trim().is_empty() && self.replaces_meaningful_content(sm)
215 }
216
217 pub fn is_replacement(&self, sm: &SourceMap) -> bool {
218 !self.snippet.is_empty() && self.replaces_meaningful_content(sm)
219 }
220
221 pub fn is_destructive_replacement(&self, sm: &SourceMap) -> bool {
226 self.is_replacement(sm)
227 && !sm
228 .span_to_snippet(self.span)
229 .is_ok_and(|snippet| as_substr(snippet.trim(), self.snippet.trim()).is_some())
230 }
231
232 fn replaces_meaningful_content(&self, sm: &SourceMap) -> bool {
233 sm.span_to_snippet(self.span)
234 .map_or(!self.span.is_empty(), |snippet| !snippet.trim().is_empty())
235 }
236}
237
238fn as_substr<'a>(original: &'a str, suggestion: &'a str) -> Option<(usize, &'a str, usize)> {
243 let common_prefix = original
244 .chars()
245 .zip(suggestion.chars())
246 .take_while(|(c1, c2)| c1 == c2)
247 .map(|(c, _)| c.len_utf8())
248 .sum();
249 let original = &original[common_prefix..];
250 let suggestion = &suggestion[common_prefix..];
251 if suggestion.ends_with(original) {
252 let common_suffix = original.len();
253 Some((common_prefix, &suggestion[..suggestion.len() - original.len()], common_suffix))
254 } else {
255 None
256 }
257}
258
259pub struct ExplicitBug;
262
263pub struct DelayedBugPanic;
266
267pub struct DiagCtxt {
274 inner: Lock<DiagCtxtInner>,
275}
276
277#[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)]
278pub struct DiagCtxtHandle<'a> {
279 dcx: &'a DiagCtxt,
280 tainted_with_errors: Option<&'a Cell<Option<ErrorGuaranteed>>>,
283}
284
285struct DiagCtxtInner {
292 flags: DiagCtxtFlags,
293
294 err_guars: Vec<(ErrorGuaranteed, ThreadId)>,
297 lint_err_guars: Vec<(ErrorGuaranteed, ThreadId)>,
300 delayed_bugs: Vec<(DelayedDiagInner, ErrorGuaranteed)>,
302
303 deduplicated_err_count: usize,
305 deduplicated_warn_count: usize,
307
308 emitter: Box<DynEmitter>,
309
310 must_produce_diag: Option<Backtrace>,
313
314 has_printed: bool,
317
318 suppressed_expected_diag: bool,
321
322 taught_diagnostics: FxHashSet<ErrCode>,
326
327 emitted_diagnostic_codes: FxIndexSet<ErrCode>,
329
330 emitted_diagnostics: FxHashSet<Hash128>,
334
335 emitted_recursion_depth_exceeding_limit: bool,
343
344 stashed_diagnostics:
350 FxIndexMap<StashKey, FxIndexMap<Span, (DiagInner, Option<ErrorGuaranteed>, ThreadId)>>,
351
352 future_breakage_diagnostics: Vec<DiagInner>,
353
354 fulfilled_expectations: FxIndexSet<LintExpectationId>,
366
367 ice_file: Option<PathBuf>,
370
371 msrv: Option<RustcVersion>,
373}
374
375#[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 { }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)]
377pub enum StashKey {
378 ItemNoType,
379 UnderscoreForArrayLengths,
380 EarlySyntaxWarning,
381 CallIntoMethod,
382 LifetimeIsChar,
385 MaybeFruTypo,
388 CallAssocMethod,
389 AssociatedTypeSuggestion,
390 UndeterminedMacroResolution,
391 ExprInPat,
393 GenericInFieldExpr,
397 ReturnTypeNotation,
398}
399
400fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
401 (*f)(diag)
402}
403
404pub static TRACK_DIAGNOSTIC: AtomicRef<
407 fn(DiagInner, &mut dyn FnMut(DiagInner) -> Option<ErrorGuaranteed>) -> Option<ErrorGuaranteed>,
408> = AtomicRef::new(&(default_track_diagnostic as _));
409
410#[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)]
411pub struct DiagCtxtFlags {
412 pub can_emit_warnings: bool,
415 pub treat_err_as_bug: Option<NonZero<usize>>,
418 pub eagerly_emit_delayed_bugs: bool,
421 pub macro_backtrace: bool,
424 pub deduplicate_diagnostics: bool,
426 pub track_diagnostics: bool,
428}
429
430impl Drop for DiagCtxtInner {
431 fn drop(&mut self) {
432 self.emit_stashed_diagnostics();
440
441 self.flush_delayed();
445
446 if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
450 if let Some(backtrace) = &self.must_produce_diag {
451 let suggestion = match backtrace.status() {
452 BacktraceStatus::Disabled => String::from(
453 "Backtraces are currently disabled: set `RUST_BACKTRACE=1` and re-run \
454 to see where it happened.",
455 ),
456 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!(
457 "This happened in the following `must_produce_diag` call's backtrace:\n\
458 {backtrace}",
459 ),
460 _ => String::from("(impossible to capture backtrace where this happened)"),
461 };
462 {
::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!(
463 "`trimmed_def_paths` called, diagnostics were expected but none were emitted. \
464 Use `with_no_trimmed_paths` for debugging. {suggestion}"
465 );
466 }
467 }
468 }
469}
470
471impl DiagCtxt {
472 pub fn disable_warnings(mut self) -> Self {
473 self.inner.get_mut().flags.can_emit_warnings = false;
474 self
475 }
476
477 pub fn with_flags(mut self, flags: DiagCtxtFlags) -> Self {
478 self.inner.get_mut().flags = flags;
479 self
480 }
481
482 pub fn with_ice_file(mut self, ice_file: PathBuf) -> Self {
483 self.inner.get_mut().ice_file = Some(ice_file);
484 self
485 }
486
487 pub fn with_msrv(mut self, msrv: RustcVersion) -> Self {
488 self.inner.get_mut().msrv = Some(msrv);
489 self
490 }
491
492 pub fn new(emitter: Box<DynEmitter>) -> Self {
493 Self { inner: Lock::new(DiagCtxtInner::new(emitter)) }
494 }
495
496 pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> {
497 DiagCtxtHandle { dcx: self, tainted_with_errors: None }
498 }
499}
500
501impl<'a> DiagCtxtHandle<'a> {
502 pub fn make_silent(&self) {
503 let mut inner = self.dcx.inner.borrow_mut();
504 inner.emitter = Box::new(emitter::SilentEmitter {});
505 }
506
507 pub fn set_emitter(&self, emitter: Box<dyn Emitter + DynSend>) {
508 self.dcx.inner.borrow_mut().emitter = emitter;
509 }
510
511 pub fn can_emit_warnings(&self) -> bool {
514 self.dcx.inner.borrow().flags.can_emit_warnings
515 }
516
517 pub fn reset_err_count(&self) {
523 let mut inner = self.dcx.inner.borrow_mut();
526 let DiagCtxtInner {
527 flags: _,
528 err_guars,
529 lint_err_guars,
530 delayed_bugs,
531 deduplicated_err_count,
532 deduplicated_warn_count,
533 emitter: _,
534 must_produce_diag,
535 has_printed,
536 suppressed_expected_diag,
537 taught_diagnostics,
538 emitted_diagnostic_codes,
539 emitted_diagnostics,
540 emitted_recursion_depth_exceeding_limit,
541 stashed_diagnostics,
542 future_breakage_diagnostics,
543 fulfilled_expectations,
544 ice_file: _,
545 msrv: _,
546 } = inner.deref_mut();
547
548 *err_guars = Default::default();
551 *lint_err_guars = Default::default();
552 *delayed_bugs = Default::default();
553 *deduplicated_err_count = 0;
554 *deduplicated_warn_count = 0;
555 *must_produce_diag = None;
556 *has_printed = false;
557 *suppressed_expected_diag = false;
558 *taught_diagnostics = Default::default();
559 *emitted_diagnostic_codes = Default::default();
560 *emitted_diagnostics = Default::default();
561 *emitted_recursion_depth_exceeding_limit = false;
562 *stashed_diagnostics = Default::default();
563 *future_breakage_diagnostics = Default::default();
564 *fulfilled_expectations = Default::default();
565 }
566
567 pub fn into_taintable(
571 self,
572 tainted_with_errors: &'a Cell<Option<ErrorGuaranteed>>,
573 ) -> DiagCtxtHandle<'a> {
574 DiagCtxtHandle { dcx: self.dcx, tainted_with_errors: Some(tainted_with_errors) }
575 }
576
577 pub fn stash_diagnostic(
599 &self,
600 span: Span,
601 key: StashKey,
602 diag: DiagInner,
603 ) -> Option<ErrorGuaranteed> {
604 let guar = match diag.level {
605 Bug | Fatal => {
606 self.span_bug(
607 span,
608 ::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),
609 );
610 }
611 Error => Some(self.span_delayed_bug(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("stashing {0:?}", key))
})format!("stashing {key:?}"))),
615 DelayedBug => {
616 return self.dcx.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors);
617 }
618 ForceWarning | Warning | Note | Help | FailureNote | Allow | Expect => None,
619 };
620
621 self.dcx
625 .inner
626 .borrow_mut()
627 .stashed_diagnostics
628 .entry(key)
629 .or_default()
630 .insert(span.with_parent(None), (diag, guar, std::thread::current().id()));
631
632 guar
633 }
634
635 pub fn steal_non_err(self, span: Span, key: StashKey) -> Option<Diag<'a, ()>> {
639 let (diag, guar, _) =
641 self.dcx.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
642 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
643 )?;
644 if !!diag.is_error() {
::core::panicking::panic("assertion failed: !diag.is_error()")
};assert!(!diag.is_error());
645 if !guar.is_none() {
::core::panicking::panic("assertion failed: guar.is_none()")
};assert!(guar.is_none());
646 Some(Diag::new_diagnostic(self, diag))
647 }
648
649 pub fn try_steal_modify_and_emit_err<F>(
654 self,
655 span: Span,
656 key: StashKey,
657 mut modify_err: F,
658 ) -> Option<ErrorGuaranteed>
659 where
660 F: FnMut(&mut Diag<'_>),
661 {
662 let err = self.dcx.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
664 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
665 );
666 err.map(|(err, guar, _)| {
667 {
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);
669 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
670 let mut err = Diag::<ErrorGuaranteed>::new_diagnostic(self, err);
671 modify_err(&mut err);
672 {
match (&err.level, &Error) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(err.level, Error);
673 err.emit()
674 })
675 }
676
677 pub fn try_steal_replace_and_emit_err(
681 self,
682 span: Span,
683 key: StashKey,
684 new_err: Diag<'_>,
685 ) -> ErrorGuaranteed {
686 let old_err = self.dcx.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
688 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
689 );
690 match old_err {
691 Some((old_err, guar, _)) => {
692 {
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);
693 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
694 Diag::<ErrorGuaranteed>::new_diagnostic(self, old_err).cancel();
697 }
698 None => {}
699 };
700 new_err.emit()
701 }
702
703 pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool {
704 let inner = self.dcx.inner.borrow();
705 if let Some(stashed_diagnostics) = inner.stashed_diagnostics.get(&key)
706 && !stashed_diagnostics.is_empty()
707 {
708 stashed_diagnostics.contains_key(&span.with_parent(None))
709 } else {
710 false
711 }
712 }
713
714 pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
716 self.dcx.inner.borrow_mut().emit_stashed_diagnostics()
717 }
718
719 #[inline]
721 pub fn err_count(&self) -> usize {
722 let inner = self.dcx.inner.borrow();
723 inner.err_guars.len()
724 + inner.lint_err_guars.len()
725 + inner
726 .stashed_diagnostics
727 .values()
728 .map(|a| a.values().filter(|(_, guar, _)| guar.is_some()).count())
729 .sum::<usize>()
730 }
731
732 pub fn err_count_on_current_thread(&self) -> usize {
737 let inner = self.dcx.inner.borrow();
738 let current = std::thread::current().id();
739 inner.err_guars.iter().filter(|(_, thread)| *thread == current).count()
740 + inner.lint_err_guars.iter().filter(|(_, thread)| *thread == current).count()
741 + inner
742 .stashed_diagnostics
743 .values()
744 .map(|a| {
745 a.values()
746 .filter(|(_, guar, thread)| guar.is_some() && *thread == current)
747 .count()
748 })
749 .sum::<usize>()
750 }
751
752 pub fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
755 self.dcx.inner.borrow().has_errors_excluding_lint_errors()
756 }
757
758 pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
760 self.dcx.inner.borrow().has_errors()
761 }
762
763 pub fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
766 self.dcx.inner.borrow().has_errors_or_delayed_bugs()
767 }
768
769 pub fn print_error_count(&self) {
770 let mut inner = self.dcx.inner.borrow_mut();
771
772 if !inner.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: inner.stashed_diagnostics.is_empty()")
};assert!(inner.stashed_diagnostics.is_empty());
775
776 if inner.treat_err_as_bug() {
777 return;
778 }
779
780 let warnings = match inner.deduplicated_warn_count {
781 0 => Cow::from(""),
782 1 => Cow::from("1 warning emitted"),
783 count => Cow::from(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} warnings emitted", count))
})format!("{count} warnings emitted")),
784 };
785 let errors = match inner.deduplicated_err_count {
786 0 => Cow::from(""),
787 1 => Cow::from("aborting due to 1 previous error"),
788 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")),
789 };
790
791 match (errors.len(), warnings.len()) {
792 (0, 0) => return,
793 (0, _) => {
794 inner.emit_diagnostic(
797 DiagInner::new(ForceWarning, DiagMessage::Str(warnings)),
798 None,
799 );
800 }
801 (_, 0) => {
802 inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors);
803 }
804 (_, _) => {
805 inner.emit_diagnostic(
806 DiagInner::new(Error, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}; {1}", errors, warnings))
})format!("{errors}; {warnings}")),
807 self.tainted_with_errors,
808 );
809 }
810 }
811
812 let can_show_explain = inner.emitter.should_show_explain();
813 let are_there_diagnostics = !inner.emitted_diagnostic_codes.is_empty();
814 if can_show_explain && are_there_diagnostics {
815 let mut error_codes = inner
816 .emitted_diagnostic_codes
817 .iter()
818 .filter_map(|&code| {
819 if crate::codes::try_find_description(code).is_ok() {
820 Some(code.to_string())
821 } else {
822 None
823 }
824 })
825 .collect::<Vec<_>>();
826 if !error_codes.is_empty() {
827 error_codes.sort();
828 if error_codes.len() > 1 {
829 let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
830 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!(
831 "Some errors have detailed explanations: {}{}",
832 error_codes[..limit].join(", "),
833 if error_codes.len() > 9 { "..." } else { "." }
834 );
835 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!(
836 "For more information about an error, try `rustc --explain {}`.",
837 &error_codes[0]
838 );
839 inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None);
840 inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None);
841 } else {
842 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!(
843 "For more information about this error, try `rustc --explain {}`.",
844 &error_codes[0]
845 );
846 inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None);
847 }
848 }
849 }
850 }
851
852 pub fn abort_if_errors(&self) {
857 if let Some(guar) = self.has_errors() {
858 guar.raise_fatal();
859 }
860 }
861
862 pub fn must_teach(&self, code: ErrCode) -> bool {
868 self.dcx.inner.borrow_mut().taught_diagnostics.insert(code)
869 }
870
871 pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
872 self.dcx.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors)
873 }
874
875 pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
876 self.dcx.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type);
877 }
878
879 pub fn emit_timing_section_start(&self, record: TimingRecord) {
880 self.dcx.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start);
881 }
882
883 pub fn emit_timing_section_end(&self, record: TimingRecord) {
884 self.dcx.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::End);
885 }
886
887 pub fn emit_future_breakage_report(&self) {
888 let inner = &mut *self.dcx.inner.borrow_mut();
889 let diags = mem::take(&mut inner.future_breakage_diagnostics);
890 if !diags.is_empty() {
891 inner.emitter.emit_future_breakage_report(diags);
892 }
893 }
894
895 pub fn emit_unused_externs(
896 &self,
897 lint_level: rustc_lint_defs::Level,
898 loud: bool,
899 unused_externs: &[&str],
900 ) {
901 let mut inner = self.dcx.inner.borrow_mut();
902
903 if loud && lint_level.is_error() {
914 #[allow(deprecated)]
917 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
918 inner.lint_err_guars.push((guar, std::thread::current().id()));
919 inner.panic_if_treat_err_as_bug();
920 }
921
922 inner.emitter.emit_unused_externs(lint_level, unused_externs)
923 }
924
925 #[must_use]
928 pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet<LintExpectationId> {
929 mem::take(&mut self.dcx.inner.borrow_mut().fulfilled_expectations)
930 }
931
932 pub fn flush_delayed(&self) {
937 self.dcx.inner.borrow_mut().flush_delayed();
938 }
939
940 #[track_caller]
943 pub fn set_must_produce_diag(&self) {
944 if !self.dcx.inner.borrow().must_produce_diag.is_none() {
{
::core::panicking::panic_fmt(format_args!("should only need to collect a backtrace once"));
}
};assert!(
945 self.dcx.inner.borrow().must_produce_diag.is_none(),
946 "should only need to collect a backtrace once"
947 );
948 self.dcx.inner.borrow_mut().must_produce_diag = Some(Backtrace::capture());
949 }
950}
951
952impl<'a> DiagCtxtHandle<'a> {
957 #[track_caller]
958 pub fn struct_bug(self, msg: impl Into<Cow<'static, str>>) -> Diag<'a, BugAbort> {
959 Diag::new(self, Bug, msg.into())
960 }
961
962 #[track_caller]
963 pub fn bug(self, msg: impl Into<Cow<'static, str>>) -> ! {
964 self.struct_bug(msg).emit()
965 }
966
967 #[track_caller]
968 pub fn struct_span_bug(
969 self,
970 span: impl Into<MultiSpan>,
971 msg: impl Into<Cow<'static, str>>,
972 ) -> Diag<'a, BugAbort> {
973 self.struct_bug(msg).with_span(span)
974 }
975
976 #[track_caller]
977 pub fn span_bug(self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! {
978 self.struct_span_bug(span, msg.into()).emit()
979 }
980
981 #[track_caller]
982 pub fn create_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> Diag<'a, BugAbort> {
983 bug.into_diag(self, Bug)
984 }
985
986 #[track_caller]
987 pub fn emit_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> ! {
988 self.create_bug(bug).emit()
989 }
990
991 #[track_caller]
992 pub fn struct_fatal(self, msg: impl Into<DiagMessage>) -> Diag<'a, FatalAbort> {
993 Diag::new(self, Fatal, msg)
994 }
995
996 #[track_caller]
997 pub fn fatal(self, msg: impl Into<DiagMessage>) -> ! {
998 self.struct_fatal(msg).emit()
999 }
1000
1001 #[track_caller]
1002 pub fn struct_span_fatal(
1003 self,
1004 span: impl Into<MultiSpan>,
1005 msg: impl Into<DiagMessage>,
1006 ) -> Diag<'a, FatalAbort> {
1007 self.struct_fatal(msg).with_span(span)
1008 }
1009
1010 #[track_caller]
1011 pub fn span_fatal(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) -> ! {
1012 self.struct_span_fatal(span, msg).emit()
1013 }
1014
1015 #[track_caller]
1016 pub fn create_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> Diag<'a, FatalAbort> {
1017 fatal.into_diag(self, Fatal)
1018 }
1019
1020 #[track_caller]
1021 pub fn emit_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> ! {
1022 self.create_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 {
1173 fn new(emitter: Box<DynEmitter>) -> Self {
1174 Self {
1175 flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
1176 err_guars: Vec::new(),
1177 lint_err_guars: Vec::new(),
1178 delayed_bugs: Vec::new(),
1179 deduplicated_err_count: 0,
1180 deduplicated_warn_count: 0,
1181 emitter,
1182 must_produce_diag: None,
1183 has_printed: false,
1184 suppressed_expected_diag: false,
1185 taught_diagnostics: Default::default(),
1186 emitted_diagnostic_codes: Default::default(),
1187 emitted_diagnostics: Default::default(),
1188 emitted_recursion_depth_exceeding_limit: false,
1189 stashed_diagnostics: Default::default(),
1190 future_breakage_diagnostics: Vec::new(),
1191 fulfilled_expectations: Default::default(),
1192 ice_file: None,
1193 msrv: None,
1194 }
1195 }
1196
1197 fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
1199 let mut guar = None;
1200 let has_errors = !self.err_guars.is_empty();
1201 for (_, stashed_diagnostics) in mem::take(&mut self.stashed_diagnostics).into_iter() {
1202 for (_, (diag, _guar, _thread)) in stashed_diagnostics {
1203 if !diag.is_error() {
1204 if !diag.is_force_warn() && has_errors {
1208 continue;
1209 }
1210 }
1211 guar = guar.or(self.emit_diagnostic(diag, None));
1212 }
1213 }
1214 guar
1215 }
1216
1217 fn emit_diagnostic(
1219 &mut self,
1220 mut diagnostic: DiagInner,
1221 taint: Option<&Cell<Option<ErrorGuaranteed>>>,
1222 ) -> Option<ErrorGuaranteed> {
1223 if diagnostic.has_future_breakage() {
1224 {
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);
1228 self.future_breakage_diagnostics.push(diagnostic.clone());
1229 }
1230
1231 match diagnostic.level {
1235 Bug => {}
1236 Fatal | Error => {
1237 if self.treat_next_err_as_bug() {
1238 diagnostic.level = Bug;
1240 }
1241 }
1242 DelayedBug => {
1243 if self.flags.eagerly_emit_delayed_bugs {
1248 if self.treat_next_err_as_bug() {
1250 diagnostic.level = Bug;
1251 } else {
1252 diagnostic.level = Error;
1253 }
1254 } else {
1255 return if let Some(guar) = self.has_errors() {
1258 Some(guar)
1259 } else {
1260 let backtrace = std::backtrace::Backtrace::capture();
1264 #[allow(deprecated)]
1268 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1269 self.delayed_bugs
1270 .push((DelayedDiagInner::with_backtrace(diagnostic, backtrace), guar));
1271 Some(guar)
1272 };
1273 }
1274 }
1275 ForceWarning if diagnostic.lint_id.is_none() => {} Warning => {
1277 if !self.flags.can_emit_warnings {
1278 if diagnostic.has_future_breakage() {
1280 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1282 }
1283 return None;
1284 }
1285 }
1286 Note | Help | FailureNote => {}
1287 Allow => {
1288 if diagnostic.has_future_breakage() {
1290 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1292 self.suppressed_expected_diag = true;
1293 }
1294 return None;
1295 }
1296 Expect | ForceWarning => {
1297 self.fulfilled_expectations.insert(diagnostic.lint_id.unwrap());
1298 if let Expect = diagnostic.level {
1299 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1301 self.suppressed_expected_diag = true;
1302 return None;
1303 }
1304 }
1305 }
1306
1307 if let (Some(msrv), Some(diag_msrv)) = (self.msrv, diagnostic.rust_version())
1308 && diag_msrv > msrv
1309 {
1310 return None;
1311 }
1312
1313 TRACK_DIAGNOSTIC(diagnostic, &mut |mut diagnostic| {
1314 if let Some(code) = diagnostic.code {
1315 self.emitted_diagnostic_codes.insert(code);
1316 }
1317
1318 let already_emitted = {
1319 let mut hasher = StableHasher::new();
1320 diagnostic.hash(&mut hasher);
1321 let diagnostic_hash = hasher.finish();
1322 !self.emitted_diagnostics.insert(diagnostic_hash)
1323 };
1324
1325 let is_error = diagnostic.is_error();
1326 let is_lint = diagnostic.is_lint.is_some();
1327 let silence_recursion_depth_exceeded_limit =
1329 diagnostic.is_lint.as_ref().is_some_and(|lint| {
1330 lint.name.eq_ignore_ascii_case(
1331 rustc_lint_defs::builtin::RECURSION_DEPTH_EXCEEDING_LIMIT.name,
1332 ) && mem::replace(&mut self.emitted_recursion_depth_exceeding_limit, true)
1333 });
1334
1335 if !silence_recursion_depth_exceeded_limit
1338 && !(self.flags.deduplicate_diagnostics && already_emitted)
1339 {
1340 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_errors/src/lib.rs:1340",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1340u32),
::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);
1341 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_errors/src/lib.rs:1341",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1341u32),
::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);
1342
1343 let not_yet_emitted = |sub: &mut Subdiag| {
1344 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_errors/src/lib.rs:1344",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1344u32),
::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);
1345 match sub.level {
1346 Sublevel::Error | Sublevel::Warning | Sublevel::Note | Sublevel::Help => {
1347 return true;
1348 }
1349 Sublevel::OnceNote | Sublevel::OnceHelp => {}
1350 }
1351 let mut hasher = StableHasher::new();
1352 sub.hash(&mut hasher);
1353 let diagnostic_hash = hasher.finish();
1354 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_errors/src/lib.rs:1354",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1354u32),
::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);
1355 self.emitted_diagnostics.insert(diagnostic_hash)
1356 };
1357 diagnostic.children.retain_mut(not_yet_emitted);
1358 if already_emitted {
1359 let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
1360 diagnostic.sub(Sublevel::Note, msg, MultiSpan::new());
1361 }
1362
1363 if is_error {
1364 self.deduplicated_err_count += 1;
1365 } else if #[allow(non_exhaustive_omitted_patterns)] match diagnostic.level {
ForceWarning | Warning => true,
_ => false,
}matches!(diagnostic.level, ForceWarning | Warning) {
1366 self.deduplicated_warn_count += 1;
1367 }
1368 self.has_printed = true;
1369
1370 self.emitter.emit_diagnostic(diagnostic);
1371 }
1372
1373 if is_error {
1374 if !self.delayed_bugs.is_empty() {
1379 {
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);
1380 self.delayed_bugs.clear();
1381 self.delayed_bugs.shrink_to_fit();
1382 }
1383
1384 #[allow(deprecated)]
1387 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1388 let thread = std::thread::current().id();
1389 if is_lint {
1390 self.lint_err_guars.push((guar, thread));
1391 } else {
1392 if let Some(taint) = taint {
1393 taint.set(Some(guar));
1394 }
1395 self.err_guars.push((guar, thread));
1396 }
1397 self.panic_if_treat_err_as_bug();
1398 Some(guar)
1399 } else {
1400 None
1401 }
1402 })
1403 }
1404
1405 fn treat_err_as_bug(&self) -> bool {
1406 self.flags
1407 .treat_err_as_bug
1408 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() >= c.get())
1409 }
1410
1411 fn treat_next_err_as_bug(&self) -> bool {
1413 self.flags
1414 .treat_err_as_bug
1415 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() + 1 >= c.get())
1416 }
1417
1418 fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
1419 self.err_guars.get(0).map(|(guar, _)| *guar).or_else(|| {
1420 if let Some((_diag, guar, _)) = self
1421 .stashed_diagnostics
1422 .values()
1423 .flat_map(|stashed_diagnostics| stashed_diagnostics.values())
1424 .find(|(diag, guar, _)| guar.is_some() && diag.is_lint.is_none())
1425 {
1426 *guar
1427 } else {
1428 None
1429 }
1430 })
1431 }
1432
1433 fn has_errors(&self) -> Option<ErrorGuaranteed> {
1434 self.err_guars
1435 .get(0)
1436 .map(|(guar, _)| *guar)
1437 .or_else(|| self.lint_err_guars.get(0).map(|(guar, _)| *guar))
1438 .or_else(|| {
1439 self.stashed_diagnostics.values().find_map(|stashed_diagnostics| {
1440 stashed_diagnostics.values().find_map(|(_, guar, _)| *guar)
1441 })
1442 })
1443 }
1444
1445 fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
1446 self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
1447 }
1448
1449 fn flush_delayed(&mut self) {
1450 if !self.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: self.stashed_diagnostics.is_empty()")
};assert!(self.stashed_diagnostics.is_empty());
1454
1455 if !self.err_guars.is_empty() {
1456 return;
1458 }
1459
1460 if self.delayed_bugs.is_empty() {
1461 return;
1463 }
1464
1465 let bugs: Vec<_> = mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();
1466
1467 let backtrace = std::env::var_os("RUST_BACKTRACE").as_deref() != Some(OsStr::new("0"));
1468 let decorate = backtrace || self.ice_file.is_none();
1469 let mut out = self
1470 .ice_file
1471 .as_ref()
1472 .and_then(|file| std::fs::File::options().create(true).append(true).open(file).ok());
1473
1474 let note1 = "no errors encountered even though delayed bugs were created";
1479 let note2 = "those delayed bugs will now be shown as internal compiler errors";
1480 self.emit_diagnostic(DiagInner::new(Note, note1), None);
1481 self.emit_diagnostic(DiagInner::new(Note, note2), None);
1482
1483 for bug in bugs {
1484 if let Some(out) = &mut out {
1485 _ = 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!(
1486 out,
1487 "delayed bug: {}\n{}\n",
1488 bug.inner
1489 .messages
1490 .iter()
1491 .filter_map(|(msg, _)| msg.as_str())
1492 .collect::<String>(),
1493 &bug.note
1494 );
1495 }
1496
1497 let mut bug = if decorate { bug.decorate() } else { bug.inner };
1498
1499 if bug.level != DelayedBug {
1501 let msg = rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"))msg!(
1508 "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"
1509 ).arg("level", bug.level).format();
1510 bug.sub(Sublevel::Note, msg, bug.span.primary_span().unwrap().into());
1511 }
1512 bug.level = Bug;
1513
1514 self.emit_diagnostic(bug, None);
1515 }
1516
1517 panic::panic_any(DelayedBugPanic);
1519 }
1520
1521 fn panic_if_treat_err_as_bug(&self) {
1522 if self.treat_err_as_bug() {
1523 let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
1524 {
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());
1525 if n == 1 {
1526 {
::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`");
1527 } else {
1528 {
::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}`");
1529 }
1530 }
1531 }
1532}
1533
1534struct DelayedDiagInner {
1535 inner: DiagInner,
1536 note: Backtrace,
1537}
1538
1539impl DelayedDiagInner {
1540 fn with_backtrace(diagnostic: DiagInner, backtrace: Backtrace) -> Self {
1541 DelayedDiagInner { inner: diagnostic, note: backtrace }
1542 }
1543
1544 fn decorate(self) -> DiagInner {
1545 let mut diag = self.inner;
1549 let msg = match self.note.status() {
1550 BacktraceStatus::Captured => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at}\n {$note}"))msg!(
1551 "delayed at {$emitted_at}
1552 {$note}"
1553 ),
1554 _ => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at} - {$note}"))msg!("delayed at {$emitted_at} - {$note}"),
1557 }
1558 .arg("emitted_at", diag.emitted_at.clone())
1559 .arg("note", self.note)
1560 .format();
1561 diag.sub(Sublevel::Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
1562 diag
1563 }
1564}
1565
1566#[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 { }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::Help => "Help",
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::Help => { 7usize }
Level::FailureNote => { 8usize }
Level::Allow => { 9usize }
Level::Expect => { 10usize }
};
::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::Help }
8usize => { Level::FailureNote }
9usize => { Level::Allow }
10usize => { Level::Expect }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Level`, expected 0..11, actual {0}",
n));
}
}
}
}
};Decodable)]
1581pub enum Level {
1582 Bug,
1584
1585 Fatal,
1588
1589 Error,
1592
1593 DelayedBug,
1598
1599 ForceWarning,
1605
1606 Warning,
1609
1610 Note,
1612
1613 Help,
1615
1616 FailureNote,
1619
1620 Allow,
1622
1623 Expect,
1625}
1626
1627impl fmt::Display for Level {
1628 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1629 self.to_str().fmt(f)
1630 }
1631}
1632
1633impl Level {
1634 pub fn to_str(self) -> &'static str {
1635 match self {
1636 Bug | DelayedBug => "error: internal compiler error",
1637 Fatal | Error => "error",
1638 ForceWarning | Warning => "warning",
1639 Note => "note",
1640 Help => "help",
1641 FailureNote => "failure-note",
1642 Allow | Expect => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1643 }
1644 }
1645
1646 pub fn is_failure_note(&self) -> bool {
1647 #[allow(non_exhaustive_omitted_patterns)] match *self {
FailureNote => true,
_ => false,
}matches!(*self, FailureNote)
1648 }
1649}
1650
1651impl IntoDiagArg for Level {
1652 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
1653 DiagArgValue::Str(Cow::from(self.to_string()))
1654 }
1655}
1656
1657#[derive(#[automatically_derived]
impl ::core::marker::Copy for Sublevel { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Sublevel { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Sublevel {
#[inline]
fn eq(&self, other: &Sublevel) -> 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 Sublevel { }Eq, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Sublevel { }
#[automatically_derived]
impl ::core::clone::Clone for Sublevel {
#[inline]
fn clone(&self) -> Sublevel { *self }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for Sublevel {
#[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 Sublevel {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Sublevel::Error => "Error",
Sublevel::Warning => "Warning",
Sublevel::Note => "Note",
Sublevel::OnceNote => "OnceNote",
Sublevel::Help => "Help",
Sublevel::OnceHelp => "OnceHelp",
})
}
}Debug, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Sublevel {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
Sublevel::Error => { 0usize }
Sublevel::Warning => { 1usize }
Sublevel::Note => { 2usize }
Sublevel::OnceNote => { 3usize }
Sublevel::Help => { 4usize }
Sublevel::OnceHelp => { 5usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Sublevel {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { Sublevel::Error }
1usize => { Sublevel::Warning }
2usize => { Sublevel::Note }
3usize => { Sublevel::OnceNote }
4usize => { Sublevel::Help }
5usize => { Sublevel::OnceHelp }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Sublevel`, expected 0..6, actual {0}",
n));
}
}
}
}
};Decodable)]
1659pub enum Sublevel {
1660 Error,
1665
1666 Warning,
1668
1669 Note,
1671
1672 OnceNote,
1674
1675 Help,
1677
1678 OnceHelp,
1680}
1681
1682impl Sublevel {
1683 pub fn to_str(self) -> &'static str {
1684 match self {
1685 Sublevel::Error => "error",
1686 Sublevel::Warning => "warning",
1687 Sublevel::Note | Sublevel::OnceNote => "note",
1688 Sublevel::Help | Sublevel::OnceHelp => "help",
1689 }
1690 }
1691}
1692
1693#[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 { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Style {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Style::NoStyle => "NoStyle",
Style::Highlight => "Highlight",
})
}
}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
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Style { }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)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Style {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
Style::NoStyle => { 0usize }
Style::Highlight => { 1usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
}
}
};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::NoStyle }
1usize => { Style::Highlight }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Style`, expected 0..2, actual {0}",
n));
}
}
}
}
};Decodable)]
1694pub enum Style {
1695 NoStyle,
1696 Highlight,
1697}
1698
1699pub fn elided_lifetime_in_path_suggestion(
1701 source_map: &SourceMap,
1702 n: usize,
1703 path_span: Span,
1704 incl_angl_brckt: bool,
1705 insertion_span: Span,
1706) -> ElidedLifetimeInPathSubdiag {
1707 let expected = ExpectedLifetimeParameter { span: path_span, count: n };
1708 let indicate = source_map.is_span_accessible(insertion_span).then(|| {
1710 let anon_lts = ::alloc::vec::from_elem("'_", n)vec!["'_"; n].join(", ");
1711 let suggestion =
1712 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}, ") };
1713
1714 IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }
1715 });
1716
1717 ElidedLifetimeInPathSubdiag { expected, indicate }
1718}
1719
1720pub fn a_or_an(s: &str) -> &'static str {
1724 let mut chars = s.chars();
1725 let Some(mut first_alpha_char) = chars.next() else {
1726 return "a";
1727 };
1728 if first_alpha_char == '`' {
1729 let Some(next) = chars.next() else {
1730 return "a";
1731 };
1732 first_alpha_char = next;
1733 }
1734 if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) {
1735 "an"
1736 } else {
1737 "a"
1738 }
1739}
1740
1741#[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)]
1742pub enum TerminalUrl {
1743 No,
1744 Yes,
1745 Auto,
1746}