1#![allow(internal_features)]
7#![allow(rustc::direct_use_of_rustc_type_ir)]
8#![feature(associated_type_defaults)]
9#![feature(default_field_values)]
10#![feature(macro_metavar_expr_concat)]
11#![feature(negative_impls)]
12#![feature(never_type)]
13#![feature(rustc_attrs)]
14extern crate self as rustc_errors;
17
18use std::backtrace::{Backtrace, BacktraceStatus};
19use std::borrow::Cow;
20use std::cell::Cell;
21use std::ffi::OsStr;
22use std::hash::Hash;
23use std::io::Write;
24use std::num::NonZero;
25use std::ops::DerefMut;
26use std::path::{Path, PathBuf};
27use std::thread::ThreadId;
28use std::{assert_matches, fmt, panic};
29
30use Level::*;
31pub use anstream::{AutoStream, ColorChoice};
34pub use anstyle::{
35 Ansi256Color, AnsiColor, Color, EffectIter, Effects, Reset, RgbColor, Style as Anstyle,
36};
37pub use codes::*;
38pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer};
39pub use diagnostic::{
40 BugAbort, Diag, DiagDecorator, DiagInner, DiagLocation, DiagStyledString, Diagnostic,
41 EmissionGuarantee, FatalAbort, StringPart, Subdiag, Subdiagnostic,
42};
43pub use diagnostic_impls::{
44 DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,
45 IndicateAnonymousLifetime, SingleLabelManySpans,
46};
47pub use emitter::ColorConfig;
48use emitter::{DynEmitter, Emitter};
49use rustc_ast::attr::version::RustcVersion;
50use rustc_data_structures::AtomicRef;
51use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
52use rustc_data_structures::stable_hash::StableHasher;
53use rustc_data_structures::sync::{DynSend, Lock};
54pub use rustc_error_messages::{
55 DiagArg, DiagArgFromDisplay, DiagArgMap, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg,
56 LanguageIdentifier, MultiSpan, SpanLabel, fluent_bundle, into_diag_arg_using_display,
57};
58use rustc_hashes::Hash128;
59use rustc_lint_defs::LintExpectationId;
60pub use rustc_lint_defs::{Applicability, listify, pluralize};
61pub use rustc_macros::msg;
62use rustc_macros::{Decodable, Encodable};
63pub use rustc_span::ErrorGuaranteed;
64pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors};
65use rustc_span::source_map::SourceMap;
66use rustc_span::{DUMMY_SP, Span};
67use tracing::debug;
68
69use crate::emitter::TimingEvent;
70use crate::formatting::DiagMessageAddArg;
71pub use crate::formatting::format_diag_message;
72use crate::timings::TimingRecord;
73
74pub mod annotate_snippet_emitter_writer;
75pub mod codes;
76mod decorate_diag;
77mod diagnostic;
78mod diagnostic_impls;
79pub mod emitter;
80pub mod formatting;
81pub mod json;
82pub mod lints;
83mod lock;
84pub mod markdown;
85pub mod timings;
86
87pub type PResult<'a, T> = Result<T, Diag<'a>>;
88
89#[cfg(target_pointer_width = "64")]
91const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, ()>>()];rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24);
92#[cfg(target_pointer_width = "64")]
93const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, bool>>()];rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
94
95#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SuggestionStyle {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
SuggestionStyle::HideCodeInline => "HideCodeInline",
SuggestionStyle::HideCodeAlways => "HideCodeAlways",
SuggestionStyle::CompletelyHidden => "CompletelyHidden",
SuggestionStyle::ShowCode => "ShowCode",
SuggestionStyle::ShowAlways => "ShowAlways",
})
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for SuggestionStyle {
#[inline]
fn eq(&self, other: &SuggestionStyle) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SuggestionStyle {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::clone::Clone for SuggestionStyle {
#[inline]
fn clone(&self) -> SuggestionStyle { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for SuggestionStyle { }Copy, #[automatically_derived]
impl ::core::hash::Hash for SuggestionStyle {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for SuggestionStyle {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
SuggestionStyle::HideCodeInline => { 0usize }
SuggestionStyle::HideCodeAlways => { 1usize }
SuggestionStyle::CompletelyHidden => { 2usize }
SuggestionStyle::ShowCode => { 3usize }
SuggestionStyle::ShowAlways => { 4usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
SuggestionStyle::HideCodeInline => {}
SuggestionStyle::HideCodeAlways => {}
SuggestionStyle::CompletelyHidden => {}
SuggestionStyle::ShowCode => {}
SuggestionStyle::ShowAlways => {}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for SuggestionStyle {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { SuggestionStyle::HideCodeInline }
1usize => { SuggestionStyle::HideCodeAlways }
2usize => { SuggestionStyle::CompletelyHidden }
3usize => { SuggestionStyle::ShowCode }
4usize => { SuggestionStyle::ShowAlways }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `SuggestionStyle`, expected 0..5, actual {0}",
n));
}
}
}
}
};Decodable)]
96pub enum SuggestionStyle {
97 HideCodeInline,
99 HideCodeAlways,
101 CompletelyHidden,
103 ShowCode,
107 ShowAlways,
109}
110
111impl SuggestionStyle {
112 fn hide_inline(&self) -> bool {
113 !#[allow(non_exhaustive_omitted_patterns)] match *self {
SuggestionStyle::ShowCode => true,
_ => false,
}matches!(*self, SuggestionStyle::ShowCode)
114 }
115}
116
117#[derive(#[automatically_derived]
impl ::core::clone::Clone for Suggestions {
#[inline]
fn clone(&self) -> Suggestions {
match self {
Suggestions::Enabled(__self_0) =>
Suggestions::Enabled(::core::clone::Clone::clone(__self_0)),
Suggestions::Sealed(__self_0) =>
Suggestions::Sealed(::core::clone::Clone::clone(__self_0)),
Suggestions::Disabled => Suggestions::Disabled,
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Suggestions {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Suggestions::Enabled(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Enabled", &__self_0),
Suggestions::Sealed(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Sealed",
&__self_0),
Suggestions::Disabled =>
::core::fmt::Formatter::write_str(f, "Disabled"),
}
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Suggestions {
#[inline]
fn eq(&self, other: &Suggestions) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Suggestions::Enabled(__self_0),
Suggestions::Enabled(__arg1_0)) => __self_0 == __arg1_0,
(Suggestions::Sealed(__self_0), Suggestions::Sealed(__arg1_0))
=> __self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for Suggestions {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
Suggestions::Enabled(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Suggestions::Sealed(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
_ => {}
}
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Suggestions {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
Suggestions::Enabled(ref __binding_0) => { 0usize }
Suggestions::Sealed(ref __binding_0) => { 1usize }
Suggestions::Disabled => { 2usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
Suggestions::Enabled(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
Suggestions::Sealed(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
Suggestions::Disabled => {}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Suggestions {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => {
Suggestions::Enabled(::rustc_serialize::Decodable::decode(__decoder))
}
1usize => {
Suggestions::Sealed(::rustc_serialize::Decodable::decode(__decoder))
}
2usize => { Suggestions::Disabled }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Suggestions`, expected 0..3, actual {0}",
n));
}
}
}
}
};Decodable)]
119pub enum Suggestions {
120 Enabled(Vec<CodeSuggestion>),
125 Sealed(Box<[CodeSuggestion]>),
129 Disabled,
133}
134
135impl Suggestions {
136 pub fn unwrap_tag(self) -> Vec<CodeSuggestion> {
138 match self {
139 Suggestions::Enabled(suggestions) => suggestions,
140 Suggestions::Sealed(suggestions) => suggestions.into_vec(),
141 Suggestions::Disabled => Vec::new(),
142 }
143 }
144
145 pub fn len(&self) -> usize {
146 match self {
147 Suggestions::Enabled(suggestions) => suggestions.len(),
148 Suggestions::Sealed(suggestions) => suggestions.len(),
149 Suggestions::Disabled => 0,
150 }
151 }
152}
153
154impl Default for Suggestions {
155 fn default() -> Self {
156 Self::Enabled(::alloc::vec::Vec::new()vec![])
157 }
158}
159
160#[derive(#[automatically_derived]
impl ::core::clone::Clone for CodeSuggestion {
#[inline]
fn clone(&self) -> CodeSuggestion {
CodeSuggestion {
substitutions: ::core::clone::Clone::clone(&self.substitutions),
msg: ::core::clone::Clone::clone(&self.msg),
style: ::core::clone::Clone::clone(&self.style),
applicability: ::core::clone::Clone::clone(&self.applicability),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for CodeSuggestion {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"CodeSuggestion", "substitutions", &self.substitutions, "msg",
&self.msg, "style", &self.style, "applicability",
&&self.applicability)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for CodeSuggestion {
#[inline]
fn eq(&self, other: &CodeSuggestion) -> bool {
self.substitutions == other.substitutions && self.msg == other.msg &&
self.style == other.style &&
self.applicability == other.applicability
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for CodeSuggestion {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.substitutions, state);
::core::hash::Hash::hash(&self.msg, state);
::core::hash::Hash::hash(&self.style, state);
::core::hash::Hash::hash(&self.applicability, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for CodeSuggestion {
fn encode(&self, __encoder: &mut __E) {
match *self {
CodeSuggestion {
substitutions: ref __binding_0,
msg: ref __binding_1,
style: ref __binding_2,
applicability: ref __binding_3 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_2,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_3,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for CodeSuggestion {
fn decode(__decoder: &mut __D) -> Self {
CodeSuggestion {
substitutions: ::rustc_serialize::Decodable::decode(__decoder),
msg: ::rustc_serialize::Decodable::decode(__decoder),
style: ::rustc_serialize::Decodable::decode(__decoder),
applicability: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
161pub struct CodeSuggestion {
162 pub substitutions: Vec<Substitution>,
184 pub msg: DiagMessage,
185 pub style: SuggestionStyle,
187 pub applicability: Applicability,
193}
194
195#[derive(#[automatically_derived]
impl ::core::clone::Clone for Substitution {
#[inline]
fn clone(&self) -> Substitution {
Substitution { parts: ::core::clone::Clone::clone(&self.parts) }
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Substitution {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "Substitution",
"parts", &&self.parts)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Substitution {
#[inline]
fn eq(&self, other: &Substitution) -> bool { self.parts == other.parts }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for Substitution {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.parts, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Substitution {
fn encode(&self, __encoder: &mut __E) {
match *self {
Substitution { parts: ref __binding_0 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Substitution {
fn decode(__decoder: &mut __D) -> Self {
Substitution {
parts: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
196pub struct Substitution {
198 pub parts: Vec<SubstitutionPart>,
199}
200
201#[derive(#[automatically_derived]
impl ::core::clone::Clone for SubstitutionPart {
#[inline]
fn clone(&self) -> SubstitutionPart {
SubstitutionPart {
span: ::core::clone::Clone::clone(&self.span),
snippet: ::core::clone::Clone::clone(&self.snippet),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for SubstitutionPart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"SubstitutionPart", "span", &self.span, "snippet", &&self.snippet)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for SubstitutionPart {
#[inline]
fn eq(&self, other: &SubstitutionPart) -> bool {
self.span == other.span && self.snippet == other.snippet
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for SubstitutionPart {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.span, state);
::core::hash::Hash::hash(&self.snippet, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for SubstitutionPart {
fn encode(&self, __encoder: &mut __E) {
match *self {
SubstitutionPart {
span: ref __binding_0, snippet: ref __binding_1 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for SubstitutionPart {
fn decode(__decoder: &mut __D) -> Self {
SubstitutionPart {
span: ::rustc_serialize::Decodable::decode(__decoder),
snippet: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
202pub struct SubstitutionPart {
203 pub span: Span,
204 pub snippet: String,
205}
206
207#[derive(#[automatically_derived]
impl ::core::clone::Clone for TrimmedSubstitutionPart {
#[inline]
fn clone(&self) -> TrimmedSubstitutionPart {
TrimmedSubstitutionPart {
original_span: ::core::clone::Clone::clone(&self.original_span),
span: ::core::clone::Clone::clone(&self.span),
snippet: ::core::clone::Clone::clone(&self.snippet),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for TrimmedSubstitutionPart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"TrimmedSubstitutionPart", "original_span", &self.original_span,
"span", &self.span, "snippet", &&self.snippet)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for TrimmedSubstitutionPart {
#[inline]
fn eq(&self, other: &TrimmedSubstitutionPart) -> bool {
self.original_span == other.original_span && self.span == other.span
&& self.snippet == other.snippet
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for TrimmedSubstitutionPart {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.original_span, state);
::core::hash::Hash::hash(&self.span, state);
::core::hash::Hash::hash(&self.snippet, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for TrimmedSubstitutionPart {
fn encode(&self, __encoder: &mut __E) {
match *self {
TrimmedSubstitutionPart {
original_span: ref __binding_0,
span: ref __binding_1,
snippet: ref __binding_2 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_2,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for TrimmedSubstitutionPart {
fn decode(__decoder: &mut __D) -> Self {
TrimmedSubstitutionPart {
original_span: ::rustc_serialize::Decodable::decode(__decoder),
span: ::rustc_serialize::Decodable::decode(__decoder),
snippet: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
208pub struct TrimmedSubstitutionPart {
209 pub original_span: Span,
210 pub span: Span,
211 pub snippet: String,
212}
213
214impl TrimmedSubstitutionPart {
215 pub fn is_addition(&self, sm: &SourceMap) -> bool {
216 !self.snippet.is_empty() && !self.replaces_meaningful_content(sm)
217 }
218
219 pub fn is_deletion(&self, sm: &SourceMap) -> bool {
220 self.snippet.trim().is_empty() && self.replaces_meaningful_content(sm)
221 }
222
223 pub fn is_replacement(&self, sm: &SourceMap) -> bool {
224 !self.snippet.is_empty() && self.replaces_meaningful_content(sm)
225 }
226
227 pub fn is_destructive_replacement(&self, sm: &SourceMap) -> bool {
232 self.is_replacement(sm)
233 && !sm
234 .span_to_snippet(self.span)
235 .is_ok_and(|snippet| as_substr(snippet.trim(), self.snippet.trim()).is_some())
236 }
237
238 fn replaces_meaningful_content(&self, sm: &SourceMap) -> bool {
239 sm.span_to_snippet(self.span)
240 .map_or(!self.span.is_empty(), |snippet| !snippet.trim().is_empty())
241 }
242}
243
244fn as_substr<'a>(original: &'a str, suggestion: &'a str) -> Option<(usize, &'a str, usize)> {
249 let common_prefix = original
250 .chars()
251 .zip(suggestion.chars())
252 .take_while(|(c1, c2)| c1 == c2)
253 .map(|(c, _)| c.len_utf8())
254 .sum();
255 let original = &original[common_prefix..];
256 let suggestion = &suggestion[common_prefix..];
257 if suggestion.ends_with(original) {
258 let common_suffix = original.len();
259 Some((common_prefix, &suggestion[..suggestion.len() - original.len()], common_suffix))
260 } else {
261 None
262 }
263}
264
265pub struct ExplicitBug;
268
269pub struct DelayedBugPanic;
272
273pub struct DiagCtxt {
277 inner: Lock<DiagCtxtInner>,
278}
279
280#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for DiagCtxtHandle<'a> { }Copy, #[automatically_derived]
impl<'a> ::core::clone::Clone for DiagCtxtHandle<'a> {
#[inline]
fn clone(&self) -> DiagCtxtHandle<'a> {
let _: ::core::clone::AssertParamIsClone<&'a DiagCtxt>;
let _:
::core::clone::AssertParamIsClone<Option<&'a Cell<Option<ErrorGuaranteed>>>>;
*self
}
}Clone)]
281pub struct DiagCtxtHandle<'a> {
282 dcx: &'a DiagCtxt,
283 tainted_with_errors: Option<&'a Cell<Option<ErrorGuaranteed>>>,
286}
287
288impl<'a> std::ops::Deref for DiagCtxtHandle<'a> {
289 type Target = &'a DiagCtxt;
290
291 fn deref(&self) -> &Self::Target {
292 &self.dcx
293 }
294}
295
296struct DiagCtxtInner {
300 flags: DiagCtxtFlags,
301
302 err_guars: Vec<(ErrorGuaranteed, ThreadId)>,
305 lint_err_guars: Vec<(ErrorGuaranteed, ThreadId)>,
308 delayed_bugs: Vec<(DelayedDiagInner, ErrorGuaranteed)>,
310
311 deduplicated_err_count: usize,
313 deduplicated_warn_count: usize,
315
316 emitter: Box<DynEmitter>,
317
318 must_produce_diag: Option<Backtrace>,
321
322 has_printed: bool,
325
326 suppressed_expected_diag: bool,
329
330 taught_diagnostics: FxHashSet<ErrCode>,
334
335 emitted_diagnostic_codes: FxIndexSet<ErrCode>,
337
338 emitted_diagnostics: FxHashSet<Hash128>,
342
343 stashed_diagnostics:
349 FxIndexMap<StashKey, FxIndexMap<Span, (DiagInner, Option<ErrorGuaranteed>, ThreadId)>>,
350
351 future_breakage_diagnostics: Vec<DiagInner>,
352
353 fulfilled_expectations: FxIndexSet<LintExpectationId>,
365
366 ice_file: Option<PathBuf>,
369
370 msrv: Option<RustcVersion>,
372}
373
374#[derive(#[automatically_derived]
impl ::core::marker::Copy for StashKey { }Copy, #[automatically_derived]
impl ::core::clone::Clone for StashKey {
#[inline]
fn clone(&self) -> StashKey { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for StashKey {
#[inline]
fn eq(&self, other: &StashKey) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for StashKey {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for StashKey {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for StashKey {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
StashKey::ItemNoType => "ItemNoType",
StashKey::UnderscoreForArrayLengths =>
"UnderscoreForArrayLengths",
StashKey::EarlySyntaxWarning => "EarlySyntaxWarning",
StashKey::CallIntoMethod => "CallIntoMethod",
StashKey::LifetimeIsChar => "LifetimeIsChar",
StashKey::MaybeFruTypo => "MaybeFruTypo",
StashKey::CallAssocMethod => "CallAssocMethod",
StashKey::AssociatedTypeSuggestion =>
"AssociatedTypeSuggestion",
StashKey::UndeterminedMacroResolution =>
"UndeterminedMacroResolution",
StashKey::ExprInPat => "ExprInPat",
StashKey::GenericInFieldExpr => "GenericInFieldExpr",
StashKey::ReturnTypeNotation => "ReturnTypeNotation",
})
}
}Debug)]
376pub enum StashKey {
377 ItemNoType,
378 UnderscoreForArrayLengths,
379 EarlySyntaxWarning,
380 CallIntoMethod,
381 LifetimeIsChar,
384 MaybeFruTypo,
387 CallAssocMethod,
388 AssociatedTypeSuggestion,
389 UndeterminedMacroResolution,
390 ExprInPat,
392 GenericInFieldExpr,
396 ReturnTypeNotation,
397}
398
399fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
400 (*f)(diag)
401}
402
403pub static TRACK_DIAGNOSTIC: AtomicRef<
406 fn(DiagInner, &mut dyn FnMut(DiagInner) -> Option<ErrorGuaranteed>) -> Option<ErrorGuaranteed>,
407> = AtomicRef::new(&(default_track_diagnostic as _));
408
409#[derive(#[automatically_derived]
impl ::core::marker::Copy for DiagCtxtFlags { }Copy, #[automatically_derived]
impl ::core::clone::Clone for DiagCtxtFlags {
#[inline]
fn clone(&self) -> DiagCtxtFlags {
let _: ::core::clone::AssertParamIsClone<bool>;
let _: ::core::clone::AssertParamIsClone<Option<NonZero<usize>>>;
*self
}
}Clone, #[automatically_derived]
impl ::core::default::Default for DiagCtxtFlags {
#[inline]
fn default() -> DiagCtxtFlags {
DiagCtxtFlags {
can_emit_warnings: ::core::default::Default::default(),
treat_err_as_bug: ::core::default::Default::default(),
eagerly_emit_delayed_bugs: ::core::default::Default::default(),
macro_backtrace: ::core::default::Default::default(),
deduplicate_diagnostics: ::core::default::Default::default(),
track_diagnostics: ::core::default::Default::default(),
}
}
}Default)]
410pub struct DiagCtxtFlags {
411 pub can_emit_warnings: bool,
414 pub treat_err_as_bug: Option<NonZero<usize>>,
417 pub eagerly_emit_delayed_bugs: bool,
420 pub macro_backtrace: bool,
423 pub deduplicate_diagnostics: bool,
425 pub track_diagnostics: bool,
427}
428
429impl Drop for DiagCtxtInner {
430 fn drop(&mut self) {
431 self.emit_stashed_diagnostics();
439
440 self.flush_delayed();
444
445 if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
449 if let Some(backtrace) = &self.must_produce_diag {
450 let suggestion = match backtrace.status() {
451 BacktraceStatus::Disabled => String::from(
452 "Backtraces are currently disabled: set `RUST_BACKTRACE=1` and re-run \
453 to see where it happened.",
454 ),
455 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!(
456 "This happened in the following `must_produce_diag` call's backtrace:\n\
457 {backtrace}",
458 ),
459 _ => String::from("(impossible to capture backtrace where this happened)"),
460 };
461 {
::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!(
462 "`trimmed_def_paths` called, diagnostics were expected but none were emitted. \
463 Use `with_no_trimmed_paths` for debugging. {suggestion}"
464 );
465 }
466 }
467 }
468}
469
470impl DiagCtxt {
471 pub fn disable_warnings(mut self) -> Self {
472 self.inner.get_mut().flags.can_emit_warnings = false;
473 self
474 }
475
476 pub fn with_flags(mut self, flags: DiagCtxtFlags) -> Self {
477 self.inner.get_mut().flags = flags;
478 self
479 }
480
481 pub fn with_ice_file(mut self, ice_file: PathBuf) -> Self {
482 self.inner.get_mut().ice_file = Some(ice_file);
483 self
484 }
485
486 pub fn with_msrv(mut self, msrv: RustcVersion) -> Self {
487 self.inner.get_mut().msrv = Some(msrv);
488 self
489 }
490
491 pub fn new(emitter: Box<DynEmitter>) -> Self {
492 Self { inner: Lock::new(DiagCtxtInner::new(emitter)) }
493 }
494
495 pub fn make_silent(&self) {
496 let mut inner = self.inner.borrow_mut();
497 inner.emitter = Box::new(emitter::SilentEmitter {});
498 }
499
500 pub fn set_emitter(&self, emitter: Box<dyn Emitter + DynSend>) {
501 self.inner.borrow_mut().emitter = emitter;
502 }
503
504 pub fn can_emit_warnings(&self) -> bool {
508 self.inner.borrow_mut().flags.can_emit_warnings
509 }
510
511 pub fn reset_err_count(&self) {
517 let mut inner = self.inner.borrow_mut();
520 let DiagCtxtInner {
521 flags: _,
522 err_guars,
523 lint_err_guars,
524 delayed_bugs,
525 deduplicated_err_count,
526 deduplicated_warn_count,
527 emitter: _,
528 must_produce_diag,
529 has_printed,
530 suppressed_expected_diag,
531 taught_diagnostics,
532 emitted_diagnostic_codes,
533 emitted_diagnostics,
534 stashed_diagnostics,
535 future_breakage_diagnostics,
536 fulfilled_expectations,
537 ice_file: _,
538 msrv: _,
539 } = inner.deref_mut();
540
541 *err_guars = Default::default();
544 *lint_err_guars = Default::default();
545 *delayed_bugs = Default::default();
546 *deduplicated_err_count = 0;
547 *deduplicated_warn_count = 0;
548 *must_produce_diag = None;
549 *has_printed = false;
550 *suppressed_expected_diag = false;
551 *taught_diagnostics = Default::default();
552 *emitted_diagnostic_codes = Default::default();
553 *emitted_diagnostics = Default::default();
554 *stashed_diagnostics = Default::default();
555 *future_breakage_diagnostics = Default::default();
556 *fulfilled_expectations = Default::default();
557 }
558
559 pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> {
560 DiagCtxtHandle { dcx: self, tainted_with_errors: None }
561 }
562
563 pub fn taintable_handle<'a>(
567 &'a self,
568 tainted_with_errors: &'a Cell<Option<ErrorGuaranteed>>,
569 ) -> DiagCtxtHandle<'a> {
570 DiagCtxtHandle { dcx: self, tainted_with_errors: Some(tainted_with_errors) }
571 }
572}
573
574impl<'a> DiagCtxtHandle<'a> {
575 pub fn stash_diagnostic(
597 &self,
598 span: Span,
599 key: StashKey,
600 diag: DiagInner,
601 ) -> Option<ErrorGuaranteed> {
602 let guar = match diag.level {
603 Bug | Fatal => {
604 self.span_bug(
605 span,
606 ::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),
607 );
608 }
609 Error => Some(self.span_delayed_bug(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("stashing {0:?}", key))
})format!("stashing {key:?}"))),
613 DelayedBug => {
614 return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors);
615 }
616 ForceWarning | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow
617 | Expect => None,
618 };
619
620 self.inner
624 .borrow_mut()
625 .stashed_diagnostics
626 .entry(key)
627 .or_default()
628 .insert(span.with_parent(None), (diag, guar, std::thread::current().id()));
629
630 guar
631 }
632
633 pub fn steal_non_err(self, span: Span, key: StashKey) -> Option<Diag<'a, ()>> {
637 let (diag, guar, _) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
639 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
640 )?;
641 if !!diag.is_error() {
::core::panicking::panic("assertion failed: !diag.is_error()")
};assert!(!diag.is_error());
642 if !guar.is_none() {
::core::panicking::panic("assertion failed: guar.is_none()")
};assert!(guar.is_none());
643 Some(Diag::new_diagnostic(self, diag))
644 }
645
646 pub fn try_steal_modify_and_emit_err<F>(
651 self,
652 span: Span,
653 key: StashKey,
654 mut modify_err: F,
655 ) -> Option<ErrorGuaranteed>
656 where
657 F: FnMut(&mut Diag<'_>),
658 {
659 let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
661 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
662 );
663 err.map(|(err, guar, _)| {
664 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);
666 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
667 let mut err = Diag::<ErrorGuaranteed>::new_diagnostic(self, err);
668 modify_err(&mut err);
669 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);
670 err.emit()
671 })
672 }
673
674 pub fn try_steal_replace_and_emit_err(
678 self,
679 span: Span,
680 key: StashKey,
681 new_err: Diag<'_>,
682 ) -> ErrorGuaranteed {
683 let old_err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
685 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
686 );
687 match old_err {
688 Some((old_err, guar, _)) => {
689 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);
690 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
691 Diag::<ErrorGuaranteed>::new_diagnostic(self, old_err).cancel();
694 }
695 None => {}
696 };
697 new_err.emit()
698 }
699
700 pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool {
701 let inner = self.inner.borrow();
702 if let Some(stashed_diagnostics) = inner.stashed_diagnostics.get(&key)
703 && !stashed_diagnostics.is_empty()
704 {
705 stashed_diagnostics.contains_key(&span.with_parent(None))
706 } else {
707 false
708 }
709 }
710
711 pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
713 self.inner.borrow_mut().emit_stashed_diagnostics()
714 }
715
716 #[inline]
718 pub fn err_count(&self) -> usize {
719 let inner = self.inner.borrow();
720 inner.err_guars.len()
721 + inner.lint_err_guars.len()
722 + inner
723 .stashed_diagnostics
724 .values()
725 .map(|a| a.values().filter(|(_, guar, _)| guar.is_some()).count())
726 .sum::<usize>()
727 }
728
729 pub fn err_count_on_current_thread(&self) -> usize {
734 let inner = self.inner.borrow();
735 let current = std::thread::current().id();
736 inner.err_guars.iter().filter(|(_, thread)| *thread == current).count()
737 + inner.lint_err_guars.iter().filter(|(_, thread)| *thread == current).count()
738 + inner
739 .stashed_diagnostics
740 .values()
741 .map(|a| {
742 a.values()
743 .filter(|(_, guar, thread)| guar.is_some() && *thread == current)
744 .count()
745 })
746 .sum::<usize>()
747 }
748
749 pub fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
752 self.inner.borrow().has_errors_excluding_lint_errors()
753 }
754
755 pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
757 self.inner.borrow().has_errors()
758 }
759
760 pub fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
763 self.inner.borrow().has_errors_or_delayed_bugs()
764 }
765
766 pub fn print_error_count(&self) {
767 let mut inner = self.inner.borrow_mut();
768
769 if !inner.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: inner.stashed_diagnostics.is_empty()")
};assert!(inner.stashed_diagnostics.is_empty());
772
773 if inner.treat_err_as_bug() {
774 return;
775 }
776
777 let warnings = match inner.deduplicated_warn_count {
778 0 => Cow::from(""),
779 1 => Cow::from("1 warning emitted"),
780 count => Cow::from(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} warnings emitted", count))
})format!("{count} warnings emitted")),
781 };
782 let errors = match inner.deduplicated_err_count {
783 0 => Cow::from(""),
784 1 => Cow::from("aborting due to 1 previous error"),
785 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")),
786 };
787
788 match (errors.len(), warnings.len()) {
789 (0, 0) => return,
790 (0, _) => {
791 inner.emit_diagnostic(
794 DiagInner::new(ForceWarning, DiagMessage::Str(warnings)),
795 None,
796 );
797 }
798 (_, 0) => {
799 inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors);
800 }
801 (_, _) => {
802 inner.emit_diagnostic(
803 DiagInner::new(Error, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}; {1}", errors, warnings))
})format!("{errors}; {warnings}")),
804 self.tainted_with_errors,
805 );
806 }
807 }
808
809 let can_show_explain = inner.emitter.should_show_explain();
810 let are_there_diagnostics = !inner.emitted_diagnostic_codes.is_empty();
811 if can_show_explain && are_there_diagnostics {
812 let mut error_codes = inner
813 .emitted_diagnostic_codes
814 .iter()
815 .filter_map(|&code| {
816 if crate::codes::try_find_description(code).is_ok() {
817 Some(code.to_string())
818 } else {
819 None
820 }
821 })
822 .collect::<Vec<_>>();
823 if !error_codes.is_empty() {
824 error_codes.sort();
825 if error_codes.len() > 1 {
826 let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
827 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!(
828 "Some errors have detailed explanations: {}{}",
829 error_codes[..limit].join(", "),
830 if error_codes.len() > 9 { "..." } else { "." }
831 );
832 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!(
833 "For more information about an error, try `rustc --explain {}`.",
834 &error_codes[0]
835 );
836 inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None);
837 inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None);
838 } else {
839 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!(
840 "For more information about this error, try `rustc --explain {}`.",
841 &error_codes[0]
842 );
843 inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None);
844 }
845 }
846 }
847 }
848
849 pub fn abort_if_errors(&self) {
854 if let Some(guar) = self.has_errors() {
855 guar.raise_fatal();
856 }
857 }
858
859 pub fn must_teach(&self, code: ErrCode) -> bool {
865 self.inner.borrow_mut().taught_diagnostics.insert(code)
866 }
867
868 pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
869 self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors)
870 }
871
872 pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
873 self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type);
874 }
875
876 pub fn emit_timing_section_start(&self, record: TimingRecord) {
877 self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start);
878 }
879
880 pub fn emit_timing_section_end(&self, record: TimingRecord) {
881 self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::End);
882 }
883
884 pub fn emit_future_breakage_report(&self) {
885 let inner = &mut *self.inner.borrow_mut();
886 let diags = std::mem::take(&mut inner.future_breakage_diagnostics);
887 if !diags.is_empty() {
888 inner.emitter.emit_future_breakage_report(diags);
889 }
890 }
891
892 pub fn emit_unused_externs(
893 &self,
894 lint_level: rustc_lint_defs::Level,
895 loud: bool,
896 unused_externs: &[&str],
897 ) {
898 let mut inner = self.inner.borrow_mut();
899
900 if loud && lint_level.is_error() {
911 #[allow(deprecated)]
914 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
915 inner.lint_err_guars.push((guar, std::thread::current().id()));
916 inner.panic_if_treat_err_as_bug();
917 }
918
919 inner.emitter.emit_unused_externs(lint_level, unused_externs)
920 }
921
922 #[must_use]
925 pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet<LintExpectationId> {
926 std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations)
927 }
928
929 pub fn flush_delayed(&self) {
934 self.inner.borrow_mut().flush_delayed();
935 }
936
937 #[track_caller]
940 pub fn set_must_produce_diag(&self) {
941 if !self.inner.borrow().must_produce_diag.is_none() {
{
::core::panicking::panic_fmt(format_args!("should only need to collect a backtrace once"));
}
};assert!(
942 self.inner.borrow().must_produce_diag.is_none(),
943 "should only need to collect a backtrace once"
944 );
945 self.inner.borrow_mut().must_produce_diag = Some(Backtrace::capture());
946 }
947}
948
949impl<'a> DiagCtxtHandle<'a> {
954 #[track_caller]
955 pub fn struct_bug(self, msg: impl Into<Cow<'static, str>>) -> Diag<'a, BugAbort> {
956 Diag::new(self, Bug, msg.into())
957 }
958
959 #[track_caller]
960 pub fn bug(self, msg: impl Into<Cow<'static, str>>) -> ! {
961 self.struct_bug(msg).emit()
962 }
963
964 #[track_caller]
965 pub fn struct_span_bug(
966 self,
967 span: impl Into<MultiSpan>,
968 msg: impl Into<Cow<'static, str>>,
969 ) -> Diag<'a, BugAbort> {
970 self.struct_bug(msg).with_span(span)
971 }
972
973 #[track_caller]
974 pub fn span_bug(self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! {
975 self.struct_span_bug(span, msg.into()).emit()
976 }
977
978 #[track_caller]
979 pub fn create_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> Diag<'a, BugAbort> {
980 bug.into_diag(self, Bug)
981 }
982
983 #[track_caller]
984 pub fn emit_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> ! {
985 self.create_bug(bug).emit()
986 }
987
988 #[track_caller]
989 pub fn struct_fatal(self, msg: impl Into<DiagMessage>) -> Diag<'a, FatalAbort> {
990 Diag::new(self, Fatal, msg)
991 }
992
993 #[track_caller]
994 pub fn fatal(self, msg: impl Into<DiagMessage>) -> ! {
995 self.struct_fatal(msg).emit()
996 }
997
998 #[track_caller]
999 pub fn struct_span_fatal(
1000 self,
1001 span: impl Into<MultiSpan>,
1002 msg: impl Into<DiagMessage>,
1003 ) -> Diag<'a, FatalAbort> {
1004 self.struct_fatal(msg).with_span(span)
1005 }
1006
1007 #[track_caller]
1008 pub fn span_fatal(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) -> ! {
1009 self.struct_span_fatal(span, msg).emit()
1010 }
1011
1012 #[track_caller]
1013 pub fn create_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> Diag<'a, FatalAbort> {
1014 fatal.into_diag(self, Fatal)
1015 }
1016
1017 #[track_caller]
1018 pub fn emit_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> ! {
1019 self.create_fatal(fatal).emit()
1020 }
1021
1022 #[track_caller]
1023 pub fn create_almost_fatal(
1024 self,
1025 fatal: impl Diagnostic<'a, FatalError>,
1026 ) -> Diag<'a, FatalError> {
1027 fatal.into_diag(self, Fatal)
1028 }
1029
1030 #[track_caller]
1031 pub fn emit_almost_fatal(self, fatal: impl Diagnostic<'a, FatalError>) -> FatalError {
1032 self.create_almost_fatal(fatal).emit()
1033 }
1034
1035 #[track_caller]
1037 pub fn struct_err(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
1038 Diag::new(self, Error, msg)
1039 }
1040
1041 #[track_caller]
1042 pub fn err(self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed {
1043 self.struct_err(msg).emit()
1044 }
1045
1046 #[track_caller]
1047 pub fn struct_span_err(
1048 self,
1049 span: impl Into<MultiSpan>,
1050 msg: impl Into<DiagMessage>,
1051 ) -> Diag<'a> {
1052 self.struct_err(msg).with_span(span)
1053 }
1054
1055 #[track_caller]
1056 pub fn span_err(
1057 self,
1058 span: impl Into<MultiSpan>,
1059 msg: impl Into<DiagMessage>,
1060 ) -> ErrorGuaranteed {
1061 self.struct_span_err(span, msg).emit()
1062 }
1063
1064 #[track_caller]
1065 pub fn create_err(self, err: impl Diagnostic<'a>) -> Diag<'a> {
1066 err.into_diag(self, Error)
1067 }
1068
1069 #[track_caller]
1070 pub fn emit_err(self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
1071 self.create_err(err).emit()
1072 }
1073
1074 #[track_caller]
1076 pub fn delayed_bug(self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed {
1077 Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).emit()
1078 }
1079
1080 #[track_caller]
1085 pub fn span_delayed_bug(
1086 self,
1087 sp: impl Into<MultiSpan>,
1088 msg: impl Into<Cow<'static, str>>,
1089 ) -> ErrorGuaranteed {
1090 Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).with_span(sp).emit()
1091 }
1092
1093 #[track_caller]
1094 pub fn struct_warn(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1095 Diag::new(self, Warning, msg)
1096 }
1097
1098 #[track_caller]
1099 pub fn warn(self, msg: impl Into<DiagMessage>) {
1100 self.struct_warn(msg).emit()
1101 }
1102
1103 #[track_caller]
1104 pub fn struct_span_warn(
1105 self,
1106 span: impl Into<MultiSpan>,
1107 msg: impl Into<DiagMessage>,
1108 ) -> Diag<'a, ()> {
1109 self.struct_warn(msg).with_span(span)
1110 }
1111
1112 #[track_caller]
1113 pub fn span_warn(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1114 self.struct_span_warn(span, msg).emit()
1115 }
1116
1117 #[track_caller]
1118 pub fn create_warn(self, warning: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
1119 warning.into_diag(self, Warning)
1120 }
1121
1122 #[track_caller]
1123 pub fn emit_warn(self, warning: impl Diagnostic<'a, ()>) {
1124 self.create_warn(warning).emit()
1125 }
1126
1127 #[track_caller]
1128 pub fn struct_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1129 Diag::new(self, Note, msg)
1130 }
1131
1132 #[track_caller]
1133 pub fn note(&self, msg: impl Into<DiagMessage>) {
1134 self.struct_note(msg).emit()
1135 }
1136
1137 #[track_caller]
1138 pub fn struct_span_note(
1139 self,
1140 span: impl Into<MultiSpan>,
1141 msg: impl Into<DiagMessage>,
1142 ) -> Diag<'a, ()> {
1143 self.struct_note(msg).with_span(span)
1144 }
1145
1146 #[track_caller]
1147 pub fn span_note(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1148 self.struct_span_note(span, msg).emit()
1149 }
1150
1151 #[track_caller]
1152 pub fn create_note(self, note: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
1153 note.into_diag(self, Note)
1154 }
1155
1156 #[track_caller]
1157 pub fn emit_note(self, note: impl Diagnostic<'a, ()>) {
1158 self.create_note(note).emit()
1159 }
1160
1161 #[track_caller]
1162 pub fn struct_help(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1163 Diag::new(self, Help, msg)
1164 }
1165
1166 #[track_caller]
1167 pub fn struct_failure_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1168 Diag::new(self, FailureNote, msg)
1169 }
1170
1171 #[track_caller]
1172 pub fn struct_allow(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
1173 Diag::new(self, Allow, msg)
1174 }
1175
1176 #[track_caller]
1177 pub fn struct_expect(self, msg: impl Into<DiagMessage>, id: LintExpectationId) -> Diag<'a, ()> {
1178 Diag::new(self, Expect, msg).with_lint_id(id)
1179 }
1180}
1181
1182impl DiagCtxtInner {
1187 fn new(emitter: Box<DynEmitter>) -> Self {
1188 Self {
1189 flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
1190 err_guars: Vec::new(),
1191 lint_err_guars: Vec::new(),
1192 delayed_bugs: Vec::new(),
1193 deduplicated_err_count: 0,
1194 deduplicated_warn_count: 0,
1195 emitter,
1196 must_produce_diag: None,
1197 has_printed: false,
1198 suppressed_expected_diag: false,
1199 taught_diagnostics: Default::default(),
1200 emitted_diagnostic_codes: Default::default(),
1201 emitted_diagnostics: Default::default(),
1202 stashed_diagnostics: Default::default(),
1203 future_breakage_diagnostics: Vec::new(),
1204 fulfilled_expectations: Default::default(),
1205 ice_file: None,
1206 msrv: None,
1207 }
1208 }
1209
1210 fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
1212 let mut guar = None;
1213 let has_errors = !self.err_guars.is_empty();
1214 for (_, stashed_diagnostics) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
1215 for (_, (diag, _guar, _thread)) in stashed_diagnostics {
1216 if !diag.is_error() {
1217 if !diag.is_force_warn() && has_errors {
1221 continue;
1222 }
1223 }
1224 guar = guar.or(self.emit_diagnostic(diag, None));
1225 }
1226 }
1227 guar
1228 }
1229
1230 fn emit_diagnostic(
1232 &mut self,
1233 mut diagnostic: DiagInner,
1234 taint: Option<&Cell<Option<ErrorGuaranteed>>>,
1235 ) -> Option<ErrorGuaranteed> {
1236 if diagnostic.has_future_breakage() {
1237 {
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);
1241 self.future_breakage_diagnostics.push(diagnostic.clone());
1242 }
1243
1244 match diagnostic.level {
1248 Bug => {}
1249 Fatal | Error => {
1250 if self.treat_next_err_as_bug() {
1251 diagnostic.level = Bug;
1253 }
1254 }
1255 DelayedBug => {
1256 if self.flags.eagerly_emit_delayed_bugs {
1261 if self.treat_next_err_as_bug() {
1263 diagnostic.level = Bug;
1264 } else {
1265 diagnostic.level = Error;
1266 }
1267 } else {
1268 return if let Some(guar) = self.has_errors() {
1271 Some(guar)
1272 } else {
1273 let backtrace = std::backtrace::Backtrace::capture();
1277 #[allow(deprecated)]
1281 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1282 self.delayed_bugs
1283 .push((DelayedDiagInner::with_backtrace(diagnostic, backtrace), guar));
1284 Some(guar)
1285 };
1286 }
1287 }
1288 ForceWarning if diagnostic.lint_id.is_none() => {} Warning => {
1290 if !self.flags.can_emit_warnings {
1291 if diagnostic.has_future_breakage() {
1293 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1295 }
1296 return None;
1297 }
1298 }
1299 Note | Help | FailureNote => {}
1300 OnceNote | OnceHelp => {
::core::panicking::panic_fmt(format_args!("bad level: {0:?}",
diagnostic.level));
}panic!("bad level: {:?}", diagnostic.level),
1301 Allow => {
1302 if diagnostic.has_future_breakage() {
1304 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1306 self.suppressed_expected_diag = true;
1307 }
1308 return None;
1309 }
1310 Expect | ForceWarning => {
1311 self.fulfilled_expectations.insert(diagnostic.lint_id.unwrap());
1312 if let Expect = diagnostic.level {
1313 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1315 self.suppressed_expected_diag = true;
1316 return None;
1317 }
1318 }
1319 }
1320
1321 if let (Some(msrv), Some(diag_msrv)) = (self.msrv, diagnostic.rust_version())
1322 && diag_msrv > msrv
1323 {
1324 return None;
1325 }
1326
1327 TRACK_DIAGNOSTIC(diagnostic, &mut |mut diagnostic| {
1328 if let Some(code) = diagnostic.code {
1329 self.emitted_diagnostic_codes.insert(code);
1330 }
1331
1332 let already_emitted = {
1333 let mut hasher = StableHasher::new();
1334 diagnostic.hash(&mut hasher);
1335 let diagnostic_hash = hasher.finish();
1336 !self.emitted_diagnostics.insert(diagnostic_hash)
1337 };
1338
1339 let is_error = diagnostic.is_error();
1340 let is_lint = diagnostic.is_lint.is_some();
1341
1342 if !(self.flags.deduplicate_diagnostics && already_emitted) {
1345 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/lib.rs:1345",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1345u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&["diagnostic"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&diagnostic)
as &dyn Value))])
});
} else { ; }
};debug!(?diagnostic);
1346 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/lib.rs:1346",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1346u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&["self.emitted_diagnostics"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&self.emitted_diagnostics)
as &dyn Value))])
});
} else { ; }
};debug!(?self.emitted_diagnostics);
1347
1348 let not_yet_emitted = |sub: &mut Subdiag| {
1349 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/lib.rs:1349",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1349u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&["sub"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&sub) as
&dyn Value))])
});
} else { ; }
};debug!(?sub);
1350 if sub.level != OnceNote && sub.level != OnceHelp {
1351 return true;
1352 }
1353 let mut hasher = StableHasher::new();
1354 sub.hash(&mut hasher);
1355 let diagnostic_hash = hasher.finish();
1356 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/lib.rs:1356",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1356u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&["diagnostic_hash"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&diagnostic_hash)
as &dyn Value))])
});
} else { ; }
};debug!(?diagnostic_hash);
1357 self.emitted_diagnostics.insert(diagnostic_hash)
1358 };
1359 diagnostic.children.retain_mut(not_yet_emitted);
1360 if already_emitted {
1361 let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
1362 diagnostic.sub(Note, msg, MultiSpan::new());
1363 }
1364
1365 if is_error {
1366 self.deduplicated_err_count += 1;
1367 } else if #[allow(non_exhaustive_omitted_patterns)] match diagnostic.level {
ForceWarning | Warning => true,
_ => false,
}matches!(diagnostic.level, ForceWarning | Warning) {
1368 self.deduplicated_warn_count += 1;
1369 }
1370 self.has_printed = true;
1371
1372 self.emitter.emit_diagnostic(diagnostic);
1373 }
1374
1375 if is_error {
1376 if !self.delayed_bugs.is_empty() {
1381 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);
1382 self.delayed_bugs.clear();
1383 self.delayed_bugs.shrink_to_fit();
1384 }
1385
1386 #[allow(deprecated)]
1389 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1390 let thread = std::thread::current().id();
1391 if is_lint {
1392 self.lint_err_guars.push((guar, thread));
1393 } else {
1394 if let Some(taint) = taint {
1395 taint.set(Some(guar));
1396 }
1397 self.err_guars.push((guar, thread));
1398 }
1399 self.panic_if_treat_err_as_bug();
1400 Some(guar)
1401 } else {
1402 None
1403 }
1404 })
1405 }
1406
1407 fn treat_err_as_bug(&self) -> bool {
1408 self.flags
1409 .treat_err_as_bug
1410 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() >= c.get())
1411 }
1412
1413 fn treat_next_err_as_bug(&self) -> bool {
1415 self.flags
1416 .treat_err_as_bug
1417 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() + 1 >= c.get())
1418 }
1419
1420 fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
1421 self.err_guars.get(0).map(|(guar, _)| *guar).or_else(|| {
1422 if let Some((_diag, guar, _)) = self
1423 .stashed_diagnostics
1424 .values()
1425 .flat_map(|stashed_diagnostics| stashed_diagnostics.values())
1426 .find(|(diag, guar, _)| guar.is_some() && diag.is_lint.is_none())
1427 {
1428 *guar
1429 } else {
1430 None
1431 }
1432 })
1433 }
1434
1435 fn has_errors(&self) -> Option<ErrorGuaranteed> {
1436 self.err_guars
1437 .get(0)
1438 .map(|(guar, _)| *guar)
1439 .or_else(|| self.lint_err_guars.get(0).map(|(guar, _)| *guar))
1440 .or_else(|| {
1441 self.stashed_diagnostics.values().find_map(|stashed_diagnostics| {
1442 stashed_diagnostics.values().find_map(|(_, guar, _)| *guar)
1443 })
1444 })
1445 }
1446
1447 fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
1448 self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
1449 }
1450
1451 fn flush_delayed(&mut self) {
1452 if !self.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: self.stashed_diagnostics.is_empty()")
};assert!(self.stashed_diagnostics.is_empty());
1456
1457 if !self.err_guars.is_empty() {
1458 return;
1460 }
1461
1462 if self.delayed_bugs.is_empty() {
1463 return;
1465 }
1466
1467 let bugs: Vec<_> =
1468 std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();
1469
1470 let backtrace = std::env::var_os("RUST_BACKTRACE").as_deref() != Some(OsStr::new("0"));
1471 let decorate = backtrace || self.ice_file.is_none();
1472 let mut out = self
1473 .ice_file
1474 .as_ref()
1475 .and_then(|file| std::fs::File::options().create(true).append(true).open(file).ok());
1476
1477 let note1 = "no errors encountered even though delayed bugs were created";
1482 let note2 = "those delayed bugs will now be shown as internal compiler errors";
1483 self.emit_diagnostic(DiagInner::new(Note, note1), None);
1484 self.emit_diagnostic(DiagInner::new(Note, note2), None);
1485
1486 for bug in bugs {
1487 if let Some(out) = &mut out {
1488 _ = 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!(
1489 out,
1490 "delayed bug: {}\n{}\n",
1491 bug.inner
1492 .messages
1493 .iter()
1494 .filter_map(|(msg, _)| msg.as_str())
1495 .collect::<String>(),
1496 &bug.note
1497 );
1498 }
1499
1500 let mut bug = if decorate { bug.decorate() } else { bug.inner };
1501
1502 if bug.level != DelayedBug {
1504 let msg = rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"))msg!(
1511 "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"
1512 ).arg("level", bug.level).format();
1513 bug.sub(Note, msg, bug.span.primary_span().unwrap().into());
1514 }
1515 bug.level = Bug;
1516
1517 self.emit_diagnostic(bug, None);
1518 }
1519
1520 panic::panic_any(DelayedBugPanic);
1522 }
1523
1524 fn panic_if_treat_err_as_bug(&self) {
1525 if self.treat_err_as_bug() {
1526 let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
1527 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());
1528 if n == 1 {
1529 {
::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`");
1530 } else {
1531 {
::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}`");
1532 }
1533 }
1534 }
1535}
1536
1537struct DelayedDiagInner {
1538 inner: DiagInner,
1539 note: Backtrace,
1540}
1541
1542impl DelayedDiagInner {
1543 fn with_backtrace(diagnostic: DiagInner, backtrace: Backtrace) -> Self {
1544 DelayedDiagInner { inner: diagnostic, note: backtrace }
1545 }
1546
1547 fn decorate(self) -> DiagInner {
1548 let mut diag = self.inner;
1552 let msg = match self.note.status() {
1553 BacktraceStatus::Captured => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at}\n {$note}"))msg!(
1554 "delayed at {$emitted_at}
1555 {$note}"
1556 ),
1557 _ => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at} - {$note}"))msg!("delayed at {$emitted_at} - {$note}"),
1560 }
1561 .arg("emitted_at", diag.emitted_at.clone())
1562 .arg("note", self.note)
1563 .format();
1564 diag.sub(Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
1565 diag
1566 }
1567}
1568
1569#[derive(#[automatically_derived]
impl ::core::marker::Copy for Level { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for Level {
#[inline]
fn eq(&self, other: &Level) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Level {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::clone::Clone for Level {
#[inline]
fn clone(&self) -> Level { *self }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for Level {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Level {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Level::Bug => "Bug",
Level::Fatal => "Fatal",
Level::Error => "Error",
Level::DelayedBug => "DelayedBug",
Level::ForceWarning => "ForceWarning",
Level::Warning => "Warning",
Level::Note => "Note",
Level::OnceNote => "OnceNote",
Level::Help => "Help",
Level::OnceHelp => "OnceHelp",
Level::FailureNote => "FailureNote",
Level::Allow => "Allow",
Level::Expect => "Expect",
})
}
}Debug, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Level {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
Level::Bug => { 0usize }
Level::Fatal => { 1usize }
Level::Error => { 2usize }
Level::DelayedBug => { 3usize }
Level::ForceWarning => { 4usize }
Level::Warning => { 5usize }
Level::Note => { 6usize }
Level::OnceNote => { 7usize }
Level::Help => { 8usize }
Level::OnceHelp => { 9usize }
Level::FailureNote => { 10usize }
Level::Allow => { 11usize }
Level::Expect => { 12usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
Level::Bug => {}
Level::Fatal => {}
Level::Error => {}
Level::DelayedBug => {}
Level::ForceWarning => {}
Level::Warning => {}
Level::Note => {}
Level::OnceNote => {}
Level::Help => {}
Level::OnceHelp => {}
Level::FailureNote => {}
Level::Allow => {}
Level::Expect => {}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Level {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { Level::Bug }
1usize => { Level::Fatal }
2usize => { Level::Error }
3usize => { Level::DelayedBug }
4usize => { Level::ForceWarning }
5usize => { Level::Warning }
6usize => { Level::Note }
7usize => { Level::OnceNote }
8usize => { Level::Help }
9usize => { Level::OnceHelp }
10usize => { Level::FailureNote }
11usize => { Level::Allow }
12usize => { Level::Expect }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Level`, expected 0..13, actual {0}",
n));
}
}
}
}
};Decodable)]
1589pub enum Level {
1590 Bug,
1592
1593 Fatal,
1596
1597 Error,
1600
1601 DelayedBug,
1606
1607 ForceWarning,
1613
1614 Warning,
1617
1618 Note,
1620
1621 OnceNote,
1623
1624 Help,
1626
1627 OnceHelp,
1629
1630 FailureNote,
1633
1634 Allow,
1636
1637 Expect,
1639}
1640
1641impl fmt::Display for Level {
1642 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1643 self.to_str().fmt(f)
1644 }
1645}
1646
1647impl Level {
1648 fn color(self) -> anstyle::Style {
1649 match self {
1650 Bug | Fatal | Error | DelayedBug => AnsiColor::BrightRed.on_default(),
1651 ForceWarning | Warning => {
1652 if falsecfg!(windows) {
1653 AnsiColor::BrightYellow.on_default()
1654 } else {
1655 AnsiColor::Yellow.on_default()
1656 }
1657 }
1658 Note | OnceNote => AnsiColor::BrightGreen.on_default(),
1659 Help | OnceHelp => AnsiColor::BrightCyan.on_default(),
1660 FailureNote => anstyle::Style::new(),
1661 Allow | Expect => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1662 }
1663 }
1664
1665 pub fn to_str(self) -> &'static str {
1666 match self {
1667 Bug | DelayedBug => "error: internal compiler error",
1668 Fatal | Error => "error",
1669 ForceWarning | Warning => "warning",
1670 Note | OnceNote => "note",
1671 Help | OnceHelp => "help",
1672 FailureNote => "failure-note",
1673 Allow | Expect => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1674 }
1675 }
1676
1677 pub fn is_failure_note(&self) -> bool {
1678 #[allow(non_exhaustive_omitted_patterns)] match *self {
FailureNote => true,
_ => false,
}matches!(*self, FailureNote)
1679 }
1680}
1681
1682impl IntoDiagArg for Level {
1683 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
1684 DiagArgValue::Str(Cow::from(self.to_string()))
1685 }
1686}
1687
1688#[derive(#[automatically_derived]
impl ::core::marker::Copy for Style { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Style {
#[inline]
fn clone(&self) -> Style {
let _: ::core::clone::AssertParamIsClone<Level>;
*self
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Style {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Style::MainHeaderMsg =>
::core::fmt::Formatter::write_str(f, "MainHeaderMsg"),
Style::HeaderMsg =>
::core::fmt::Formatter::write_str(f, "HeaderMsg"),
Style::LineAndColumn =>
::core::fmt::Formatter::write_str(f, "LineAndColumn"),
Style::LineNumber =>
::core::fmt::Formatter::write_str(f, "LineNumber"),
Style::Quotation =>
::core::fmt::Formatter::write_str(f, "Quotation"),
Style::UnderlinePrimary =>
::core::fmt::Formatter::write_str(f, "UnderlinePrimary"),
Style::UnderlineSecondary =>
::core::fmt::Formatter::write_str(f, "UnderlineSecondary"),
Style::LabelPrimary =>
::core::fmt::Formatter::write_str(f, "LabelPrimary"),
Style::LabelSecondary =>
::core::fmt::Formatter::write_str(f, "LabelSecondary"),
Style::NoStyle => ::core::fmt::Formatter::write_str(f, "NoStyle"),
Style::Level(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Level",
&__self_0),
Style::Highlight =>
::core::fmt::Formatter::write_str(f, "Highlight"),
Style::Addition =>
::core::fmt::Formatter::write_str(f, "Addition"),
Style::Removal => ::core::fmt::Formatter::write_str(f, "Removal"),
}
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Style {
#[inline]
fn eq(&self, other: &Style) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Style::Level(__self_0), Style::Level(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Style {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Level>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Style {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
Style::Level(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
_ => {}
}
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Style {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
Style::MainHeaderMsg => { 0usize }
Style::HeaderMsg => { 1usize }
Style::LineAndColumn => { 2usize }
Style::LineNumber => { 3usize }
Style::Quotation => { 4usize }
Style::UnderlinePrimary => { 5usize }
Style::UnderlineSecondary => { 6usize }
Style::LabelPrimary => { 7usize }
Style::LabelSecondary => { 8usize }
Style::NoStyle => { 9usize }
Style::Level(ref __binding_0) => { 10usize }
Style::Highlight => { 11usize }
Style::Addition => { 12usize }
Style::Removal => { 13usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
Style::MainHeaderMsg => {}
Style::HeaderMsg => {}
Style::LineAndColumn => {}
Style::LineNumber => {}
Style::Quotation => {}
Style::UnderlinePrimary => {}
Style::UnderlineSecondary => {}
Style::LabelPrimary => {}
Style::LabelSecondary => {}
Style::NoStyle => {}
Style::Level(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
Style::Highlight => {}
Style::Addition => {}
Style::Removal => {}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Style {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { Style::MainHeaderMsg }
1usize => { Style::HeaderMsg }
2usize => { Style::LineAndColumn }
3usize => { Style::LineNumber }
4usize => { Style::Quotation }
5usize => { Style::UnderlinePrimary }
6usize => { Style::UnderlineSecondary }
7usize => { Style::LabelPrimary }
8usize => { Style::LabelSecondary }
9usize => { Style::NoStyle }
10usize => {
Style::Level(::rustc_serialize::Decodable::decode(__decoder))
}
11usize => { Style::Highlight }
12usize => { Style::Addition }
13usize => { Style::Removal }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Style`, expected 0..14, actual {0}",
n));
}
}
}
}
};Decodable)]
1689pub enum Style {
1690 MainHeaderMsg,
1691 HeaderMsg,
1692 LineAndColumn,
1693 LineNumber,
1694 Quotation,
1695 UnderlinePrimary,
1696 UnderlineSecondary,
1697 LabelPrimary,
1698 LabelSecondary,
1699 NoStyle,
1700 Level(Level),
1701 Highlight,
1702 Addition,
1703 Removal,
1704}
1705
1706pub fn elided_lifetime_in_path_suggestion(
1708 source_map: &SourceMap,
1709 n: usize,
1710 path_span: Span,
1711 incl_angl_brckt: bool,
1712 insertion_span: Span,
1713) -> ElidedLifetimeInPathSubdiag {
1714 let expected = ExpectedLifetimeParameter { span: path_span, count: n };
1715 let indicate = source_map.is_span_accessible(insertion_span).then(|| {
1717 let anon_lts = ::alloc::vec::from_elem("'_", n)vec!["'_"; n].join(", ");
1718 let suggestion =
1719 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}, ") };
1720
1721 IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }
1722 });
1723
1724 ElidedLifetimeInPathSubdiag { expected, indicate }
1725}
1726
1727pub fn a_or_an(s: &str) -> &'static str {
1731 let mut chars = s.chars();
1732 let Some(mut first_alpha_char) = chars.next() else {
1733 return "a";
1734 };
1735 if first_alpha_char == '`' {
1736 let Some(next) = chars.next() else {
1737 return "a";
1738 };
1739 first_alpha_char = next;
1740 }
1741 if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) {
1742 "an"
1743 } else {
1744 "a"
1745 }
1746}
1747
1748#[derive(#[automatically_derived]
impl ::core::clone::Clone for TerminalUrl {
#[inline]
fn clone(&self) -> TerminalUrl { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TerminalUrl { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for TerminalUrl {
#[inline]
fn eq(&self, other: &TerminalUrl) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for TerminalUrl {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for TerminalUrl {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
TerminalUrl::No => "No",
TerminalUrl::Yes => "Yes",
TerminalUrl::Auto => "Auto",
})
}
}Debug)]
1749pub enum TerminalUrl {
1750 No,
1751 Yes,
1752 Auto,
1753}