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