1#![feature(default_field_values)]
7#![feature(macro_metavar_expr_concat)]
8#![feature(negative_impls)]
9extern crate self as rustc_errors;
12
13use std::backtrace::{Backtrace, BacktraceStatus};
14use std::borrow::Cow;
15use std::cell::Cell;
16use std::ffi::OsStr;
17use std::hash::Hash;
18use std::io::Write;
19use std::num::NonZero;
20use std::ops::DerefMut;
21use std::path::{Path, PathBuf};
22use std::thread::ThreadId;
23use std::{assert_matches, fmt, mem, panic};
24
25use Level::*;
26pub use anstream::{AutoStream, ColorChoice};
29pub use anstyle::{
30 Ansi256Color, AnsiColor, Color, EffectIter, Effects, Reset, RgbColor, Style as Anstyle,
31};
32pub use codes::*;
33pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer};
34pub use diagnostic::{
35 Diag, DiagDecorator, DiagInner, DiagLocation, DiagStyledString, Diagnostic, StringPart,
36 Subdiag, Subdiagnostic,
37};
38pub use diagnostic_impls::{
39 DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,
40 IndicateAnonymousLifetime, SingleLabelManySpans,
41};
42pub use emitter::ColorConfig;
43use emitter::{DynEmitter, Emitter};
44use rustc_ast::attr::version::RustcVersion;
45use rustc_data_structures::AtomicRef;
46use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
47use rustc_data_structures::stable_hash::StableHasher;
48use rustc_data_structures::sync::{DynSend, Lock};
49pub use rustc_error_messages::{
50 DiagArg, DiagArgFromDisplay, DiagArgMap, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg,
51 LanguageIdentifier, MultiSpan, SpanLabel, fluent_bundle, into_diag_arg_using_display,
52};
53use rustc_hashes::Hash128;
54use rustc_lint_defs::LintExpectationId;
55pub use rustc_lint_defs::{Applicability, listify, pluralize};
56pub use rustc_macros::msg;
57use rustc_macros::{Decodable, Encodable};
58pub use rustc_span::ErrorGuaranteed;
59pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors};
60pub use rustc_span::macros::ExplicitBug;
61use rustc_span::source_map::SourceMap;
62use rustc_span::{DUMMY_SP, Span};
63use tracing::debug;
64
65use crate::emitter::TimingEvent;
66use crate::formatting::DiagMessageAddArg;
67pub use crate::formatting::format_diag_message;
68use crate::timings::TimingRecord;
69
70pub mod annotate_snippet_emitter_writer;
71pub mod codes;
72mod decorate_diag;
73mod diagnostic;
74mod diagnostic_impls;
75pub mod emitter;
76pub mod formatting;
77pub mod json;
78mod lock;
79pub mod markdown;
80pub mod timings;
81
82pub type PResult<'a, T> = Result<T, Diag<'a>>;
83
84#[cfg(target_pointer_width = "64")]
86const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, ()>>()];rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24);
87#[cfg(target_pointer_width = "64")]
88const _: [(); 24] = [(); ::std::mem::size_of::<PResult<'_, bool>>()];rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
89
90#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SuggestionStyle {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
SuggestionStyle::HideCodeInline => "HideCodeInline",
SuggestionStyle::HideCodeAlways => "HideCodeAlways",
SuggestionStyle::CompletelyHidden => "CompletelyHidden",
SuggestionStyle::ShowCode => "ShowCode",
SuggestionStyle::ShowAlways => "ShowAlways",
})
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for SuggestionStyle { }
#[automatically_derived]
impl ::core::cmp::PartialEq for SuggestionStyle {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SuggestionStyle { }Eq, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for SuggestionStyle { }
#[automatically_derived]
impl ::core::clone::Clone for SuggestionStyle {
#[inline]
fn clone(&self) -> Self { *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) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for SuggestionStyle {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
SuggestionStyle::HideCodeInline => { 0usize }
SuggestionStyle::HideCodeAlways => { 1usize }
SuggestionStyle::CompletelyHidden => { 2usize }
SuggestionStyle::ShowCode => { 3usize }
SuggestionStyle::ShowAlways => { 4usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for SuggestionStyle {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { SuggestionStyle::HideCodeInline }
1usize => { SuggestionStyle::HideCodeAlways }
2usize => { SuggestionStyle::CompletelyHidden }
3usize => { SuggestionStyle::ShowCode }
4usize => { SuggestionStyle::ShowAlways }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `SuggestionStyle`, expected 0..5, actual {0}",
n));
}
}
}
}
};Decodable)]
91pub enum SuggestionStyle {
92 HideCodeInline,
94 HideCodeAlways,
96 CompletelyHidden,
98 ShowCode,
102 ShowAlways,
104}
105
106impl SuggestionStyle {
107 fn hide_inline(&self) -> bool {
108 !#[allow(non_exhaustive_omitted_patterns)] match *self {
SuggestionStyle::ShowCode => true,
_ => false,
}matches!(*self, SuggestionStyle::ShowCode)
109 }
110}
111
112#[derive(#[automatically_derived]
impl ::core::clone::Clone for Suggestions {
#[inline]
fn clone(&self) -> Self {
match self {
Self::Enabled(__self_0) =>
Self::Enabled(::core::clone::Clone::clone(__self_0)),
Self::Sealed(__self_0) =>
Self::Sealed(::core::clone::Clone::clone(__self_0)),
Self::Disabled => Self::Disabled,
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Suggestions {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Enabled(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Enabled", &__self_0),
Self::Sealed(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Sealed",
&__self_0),
Self::Disabled =>
::core::fmt::Formatter::write_str(f, "Disabled"),
}
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Suggestions { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Suggestions {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other) &&
match (self, other) {
(Self::Enabled(__self_0), Self::Enabled(__arg1_0)) =>
__self_0 == __arg1_0,
(Self::Sealed(__self_0), Self::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) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state);
match self {
Self::Enabled(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Self::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)]
114pub enum Suggestions {
115 Enabled(Vec<CodeSuggestion>),
120 Sealed(Box<[CodeSuggestion]>),
124 Disabled,
128}
129
130impl Suggestions {
131 pub fn unwrap_tag(self) -> Vec<CodeSuggestion> {
133 match self {
134 Suggestions::Enabled(suggestions) => suggestions,
135 Suggestions::Sealed(suggestions) => suggestions.into_vec(),
136 Suggestions::Disabled => Vec::new(),
137 }
138 }
139
140 pub fn len(&self) -> usize {
141 match self {
142 Suggestions::Enabled(suggestions) => suggestions.len(),
143 Suggestions::Sealed(suggestions) => suggestions.len(),
144 Suggestions::Disabled => 0,
145 }
146 }
147}
148
149impl Default for Suggestions {
150 fn default() -> Self {
151 Self::Enabled(::alloc::vec::Vec::new()vec![])
152 }
153}
154
155#[derive(#[automatically_derived]
impl ::core::clone::Clone for CodeSuggestion {
#[inline]
fn clone(&self) -> Self {
Self {
substitutions: ::core::clone::Clone::clone(&self.substitutions),
msg: ::core::clone::Clone::clone(&self.msg),
style: ::core::clone::Clone::clone(&self.style),
applicability: ::core::clone::Clone::clone(&self.applicability),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for CodeSuggestion {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"CodeSuggestion", "substitutions", &self.substitutions, "msg",
&self.msg, "style", &self.style, "applicability",
&&self.applicability)
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for CodeSuggestion { }
#[automatically_derived]
impl ::core::cmp::PartialEq for CodeSuggestion {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.substitutions == other.substitutions && self.msg == other.msg &&
self.style == other.style &&
self.applicability == other.applicability
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for CodeSuggestion {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.substitutions, state);
::core::hash::Hash::hash(&self.msg, state);
::core::hash::Hash::hash(&self.style, state);
::core::hash::Hash::hash(&self.applicability, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for CodeSuggestion {
fn encode(&self, __encoder: &mut __E) {
let CodeSuggestion {
substitutions: ref __binding_0,
msg: ref __binding_1,
style: ref __binding_2,
applicability: ref __binding_3 } = *self;
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_2,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_3,
__encoder);
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for CodeSuggestion {
fn decode(__decoder: &mut __D) -> Self {
CodeSuggestion {
substitutions: ::rustc_serialize::Decodable::decode(__decoder),
msg: ::rustc_serialize::Decodable::decode(__decoder),
style: ::rustc_serialize::Decodable::decode(__decoder),
applicability: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
156pub struct CodeSuggestion {
157 pub substitutions: Vec<Substitution>,
179 pub msg: DiagMessage,
180 pub style: SuggestionStyle,
182 pub applicability: Applicability,
188}
189
190#[derive(#[automatically_derived]
impl ::core::clone::Clone for Substitution {
#[inline]
fn clone(&self) -> Self {
Self { parts: ::core::clone::Clone::clone(&self.parts) }
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Substitution {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "Substitution",
"parts", &&self.parts)
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Substitution { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Substitution {
#[inline]
fn eq(&self, other: &Self) -> bool { self.parts == other.parts }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for Substitution {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.parts, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Substitution {
fn encode(&self, __encoder: &mut __E) {
let Substitution { parts: ref __binding_0 } = *self;
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Substitution {
fn decode(__decoder: &mut __D) -> Self {
Substitution {
parts: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
191pub struct Substitution {
193 pub parts: Vec<SubstitutionPart>,
194}
195
196#[derive(#[automatically_derived]
impl ::core::clone::Clone for SubstitutionPart {
#[inline]
fn clone(&self) -> Self {
Self {
span: ::core::clone::Clone::clone(&self.span),
snippet: ::core::clone::Clone::clone(&self.snippet),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for SubstitutionPart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"SubstitutionPart", "span", &self.span, "snippet", &&self.snippet)
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for SubstitutionPart { }
#[automatically_derived]
impl ::core::cmp::PartialEq for SubstitutionPart {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.span == other.span && self.snippet == other.snippet
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for SubstitutionPart {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.span, state);
::core::hash::Hash::hash(&self.snippet, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for SubstitutionPart {
fn encode(&self, __encoder: &mut __E) {
let SubstitutionPart {
span: ref __binding_0, snippet: ref __binding_1 } = *self;
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for SubstitutionPart {
fn decode(__decoder: &mut __D) -> Self {
SubstitutionPart {
span: ::rustc_serialize::Decodable::decode(__decoder),
snippet: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
197pub struct SubstitutionPart {
198 pub span: Span,
199 pub snippet: String,
200}
201
202#[derive(#[automatically_derived]
impl ::core::clone::Clone for TrimmedSubstitutionPart {
#[inline]
fn clone(&self) -> Self {
Self {
original_span: ::core::clone::Clone::clone(&self.original_span),
span: ::core::clone::Clone::clone(&self.span),
snippet: ::core::clone::Clone::clone(&self.snippet),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for TrimmedSubstitutionPart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"TrimmedSubstitutionPart", "original_span", &self.original_span,
"span", &self.span, "snippet", &&self.snippet)
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for TrimmedSubstitutionPart { }
#[automatically_derived]
impl ::core::cmp::PartialEq for TrimmedSubstitutionPart {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.original_span == other.original_span && self.span == other.span
&& self.snippet == other.snippet
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for TrimmedSubstitutionPart {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.original_span, state);
::core::hash::Hash::hash(&self.span, state);
::core::hash::Hash::hash(&self.snippet, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for TrimmedSubstitutionPart {
fn encode(&self, __encoder: &mut __E) {
let TrimmedSubstitutionPart {
original_span: ref __binding_0,
span: ref __binding_1,
snippet: ref __binding_2 } = *self;
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_2,
__encoder);
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for TrimmedSubstitutionPart {
fn decode(__decoder: &mut __D) -> Self {
TrimmedSubstitutionPart {
original_span: ::rustc_serialize::Decodable::decode(__decoder),
span: ::rustc_serialize::Decodable::decode(__decoder),
snippet: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
203pub struct TrimmedSubstitutionPart {
204 pub original_span: Span,
205 pub span: Span,
206 pub snippet: String,
207}
208
209impl TrimmedSubstitutionPart {
210 pub fn is_addition(&self, sm: &SourceMap) -> bool {
211 !self.snippet.is_empty() && !self.replaces_meaningful_content(sm)
212 }
213
214 pub fn is_deletion(&self, sm: &SourceMap) -> bool {
215 self.snippet.trim().is_empty() && self.replaces_meaningful_content(sm)
216 }
217
218 pub fn is_replacement(&self, sm: &SourceMap) -> bool {
219 !self.snippet.is_empty() && self.replaces_meaningful_content(sm)
220 }
221
222 pub fn is_destructive_replacement(&self, sm: &SourceMap) -> bool {
227 self.is_replacement(sm)
228 && !sm
229 .span_to_snippet(self.span)
230 .is_ok_and(|snippet| as_substr(snippet.trim(), self.snippet.trim()).is_some())
231 }
232
233 fn replaces_meaningful_content(&self, sm: &SourceMap) -> bool {
234 sm.span_to_snippet(self.span)
235 .map_or(!self.span.is_empty(), |snippet| !snippet.trim().is_empty())
236 }
237}
238
239fn as_substr<'a>(original: &'a str, suggestion: &'a str) -> Option<(usize, &'a str, usize)> {
244 let common_prefix = original
245 .chars()
246 .zip(suggestion.chars())
247 .take_while(|(c1, c2)| c1 == c2)
248 .map(|(c, _)| c.len_utf8())
249 .sum();
250 let original = &original[common_prefix..];
251 let suggestion = &suggestion[common_prefix..];
252 if suggestion.ends_with(original) {
253 let common_suffix = original.len();
254 Some((common_prefix, &suggestion[..suggestion.len() - original.len()], common_suffix))
255 } else {
256 None
257 }
258}
259
260pub struct DelayedBugPanic;
263
264pub struct DiagCtxt {
271 inner: Lock<DiagCtxtInner>,
272}
273
274#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for DiagCtxtHandle<'a> { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl<'a> ::core::clone::TrivialClone for DiagCtxtHandle<'a> { }
#[automatically_derived]
impl<'a> ::core::clone::Clone for DiagCtxtHandle<'a> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<&'a DiagCtxt>;
let _:
::core::clone::AssertParamIsClone<Option<&'a Cell<Option<ErrorGuaranteed>>>>;
*self
}
}Clone)]
275pub struct DiagCtxtHandle<'a> {
276 dcx: &'a DiagCtxt,
277 tainted_with_errors: Option<&'a Cell<Option<ErrorGuaranteed>>>,
280}
281
282struct DiagCtxtInner {
289 flags: DiagCtxtFlags,
290
291 err_guars: Vec<(ErrorGuaranteed, ThreadId)>,
294 lint_err_guars: Vec<(ErrorGuaranteed, ThreadId)>,
297 delayed_bugs: Vec<(DelayedDiagInner, ErrorGuaranteed)>,
299
300 deduplicated_err_count: usize,
302 deduplicated_warn_count: usize,
304
305 emitter: Box<DynEmitter>,
306
307 must_produce_diag: Option<Backtrace>,
310
311 has_printed: bool,
314
315 suppressed_expected_diag: bool,
318
319 taught_diagnostics: FxHashSet<ErrCode>,
323
324 emitted_diagnostic_codes: FxIndexSet<ErrCode>,
326
327 emitted_diagnostics: FxHashSet<Hash128>,
333
334 emitted_recursion_depth_exceeding_limit: bool,
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]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for StashKey { }
#[automatically_derived]
impl ::core::clone::Clone for StashKey {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for StashKey { }
#[automatically_derived]
impl ::core::cmp::PartialEq for StashKey {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for StashKey { }Eq, #[automatically_derived]
impl ::core::hash::Hash for StashKey {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
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::EarlySyntaxWarning => "EarlySyntaxWarning",
StashKey::CallIntoMethod => "CallIntoMethod",
StashKey::LifetimeIsChar => "LifetimeIsChar",
StashKey::MaybeFruTypo => "MaybeFruTypo",
StashKey::CallAssocMethod => "CallAssocMethod",
StashKey::UndeterminedMacroResolution =>
"UndeterminedMacroResolution",
StashKey::ExprInPat => "ExprInPat",
StashKey::GenericInFieldExpr => "GenericInFieldExpr",
StashKey::ReturnTypeNotation => "ReturnTypeNotation",
})
}
}Debug)]
376pub enum StashKey {
377 ItemNoType,
378 EarlySyntaxWarning,
379 CallIntoMethod,
380 LifetimeIsChar,
383 MaybeFruTypo,
386 CallAssocMethod,
387 UndeterminedMacroResolution,
388 ExprInPat,
390 GenericInFieldExpr,
394 ReturnTypeNotation,
395}
396
397fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
398 (*f)(diag)
399}
400
401pub static TRACK_DIAGNOSTIC: AtomicRef<
404 fn(DiagInner, &mut dyn FnMut(DiagInner) -> Option<ErrorGuaranteed>) -> Option<ErrorGuaranteed>,
405> = AtomicRef::new(&(default_track_diagnostic as _));
406
407#[derive(#[automatically_derived]
impl ::core::marker::Copy for DiagCtxtFlags { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for DiagCtxtFlags { }
#[automatically_derived]
impl ::core::clone::Clone for DiagCtxtFlags {
#[inline]
fn clone(&self) -> Self {
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() -> Self {
Self {
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)]
408pub struct DiagCtxtFlags {
409 pub can_emit_warnings: bool,
412 pub treat_err_as_bug: Option<NonZero<usize>>,
415 pub eagerly_emit_delayed_bugs: bool,
418 pub macro_backtrace: bool,
421 pub deduplicate_diagnostics: bool,
423 pub track_diagnostics: bool,
425}
426
427impl Drop for DiagCtxtInner {
428 fn drop(&mut self) {
429 self.emit_stashed_diagnostics();
437
438 self.flush_delayed();
442
443 if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
447 if let Some(backtrace) = &self.must_produce_diag {
448 let suggestion = match backtrace.status() {
449 BacktraceStatus::Disabled => String::from(
450 "Backtraces are currently disabled: set `RUST_BACKTRACE=1` and re-run \
451 to see where it happened.",
452 ),
453 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!(
454 "This happened in the following `must_produce_diag` call's backtrace:\n\
455 {backtrace}",
456 ),
457 _ => String::from("(impossible to capture backtrace where this happened)"),
458 };
459 {
::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!(
460 "`trimmed_def_paths` called, diagnostics were expected but none were emitted. \
461 Use `with_no_trimmed_paths` for debugging. {suggestion}"
462 );
463 }
464 }
465 }
466}
467
468impl DiagCtxt {
469 pub fn disable_warnings(mut self) -> Self {
470 self.inner.get_mut().flags.can_emit_warnings = false;
471 self
472 }
473
474 pub fn with_flags(mut self, flags: DiagCtxtFlags) -> Self {
475 self.inner.get_mut().flags = flags;
476 self
477 }
478
479 pub fn with_ice_file(mut self, ice_file: PathBuf) -> Self {
480 self.inner.get_mut().ice_file = Some(ice_file);
481 self
482 }
483
484 pub fn with_msrv(mut self, msrv: RustcVersion) -> Self {
485 self.inner.get_mut().msrv = Some(msrv);
486 self
487 }
488
489 pub fn new(emitter: Box<DynEmitter>) -> Self {
490 Self { inner: Lock::new(DiagCtxtInner::new(emitter)) }
491 }
492
493 pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> {
494 DiagCtxtHandle { dcx: self, tainted_with_errors: None }
495 }
496}
497
498impl<'a> DiagCtxtHandle<'a> {
499 pub fn make_silent(&self) {
500 let mut inner = self.dcx.inner.borrow_mut();
501 inner.emitter = Box::new(emitter::SilentEmitter {});
502 }
503
504 pub fn set_emitter(&self, emitter: Box<dyn Emitter + DynSend>) {
505 self.dcx.inner.borrow_mut().emitter = emitter;
506 }
507
508 pub fn can_emit_warnings(&self) -> bool {
511 self.dcx.inner.borrow().flags.can_emit_warnings
512 }
513
514 pub fn reset_err_count(&self) {
520 let mut inner = self.dcx.inner.borrow_mut();
523 let DiagCtxtInner {
524 flags: _,
525 err_guars,
526 lint_err_guars,
527 delayed_bugs,
528 deduplicated_err_count,
529 deduplicated_warn_count,
530 emitter: _,
531 must_produce_diag,
532 has_printed,
533 suppressed_expected_diag,
534 taught_diagnostics,
535 emitted_diagnostic_codes,
536 emitted_diagnostics,
537 emitted_recursion_depth_exceeding_limit,
538 stashed_diagnostics,
539 future_breakage_diagnostics,
540 fulfilled_expectations,
541 ice_file: _,
542 msrv: _,
543 } = inner.deref_mut();
544
545 *err_guars = Default::default();
548 *lint_err_guars = Default::default();
549 *delayed_bugs = Default::default();
550 *deduplicated_err_count = 0;
551 *deduplicated_warn_count = 0;
552 *must_produce_diag = None;
553 *has_printed = false;
554 *suppressed_expected_diag = false;
555 *taught_diagnostics = Default::default();
556 *emitted_diagnostic_codes = Default::default();
557 *emitted_diagnostics = Default::default();
558 *emitted_recursion_depth_exceeding_limit = false;
559 *stashed_diagnostics = Default::default();
560 *future_breakage_diagnostics = Default::default();
561 *fulfilled_expectations = Default::default();
562 }
563
564 pub fn into_taintable(
568 self,
569 tainted_with_errors: &'a Cell<Option<ErrorGuaranteed>>,
570 ) -> DiagCtxtHandle<'a> {
571 DiagCtxtHandle { dcx: self.dcx, tainted_with_errors: Some(tainted_with_errors) }
572 }
573
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.dcx.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors);
614 }
615 ForceWarning | Warning | Note | Help | FailureNote | Allow | Expect => None,
616 };
617
618 self.dcx
622 .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, _) =
638 self.dcx.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.dcx.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);
665 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
666 let mut err = Diag::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_err()
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.dcx.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::new_diagnostic(self, old_err).cancel();
693 }
694 None => {}
695 };
696 new_err.emit_err()
697 }
698
699 pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool {
700 let inner = self.dcx.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.dcx.inner.borrow_mut().emit_stashed_diagnostics()
713 }
714
715 #[inline]
717 pub fn err_count(&self) -> usize {
718 let inner = self.dcx.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.dcx.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.dcx.inner.borrow().has_errors_excluding_lint_errors()
752 }
753
754 pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
756 self.dcx.inner.borrow().has_errors()
757 }
758
759 pub fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
762 self.dcx.inner.borrow().has_errors_or_delayed_bugs()
763 }
764
765 pub fn print_error_count(&self) {
766 let mut inner = self.dcx.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.dcx.inner.borrow_mut().taught_diagnostics.insert(code)
865 }
866
867 pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
868 self.dcx.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.dcx.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type);
873 }
874
875 pub fn emit_timing_section_start(&self, record: TimingRecord) {
876 self.dcx.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start);
877 }
878
879 pub fn emit_timing_section_end(&self, record: TimingRecord) {
880 self.dcx.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.dcx.inner.borrow_mut();
885 let diags = 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.dcx.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 mem::take(&mut self.dcx.inner.borrow_mut().fulfilled_expectations)
926 }
927
928 pub fn flush_delayed(&self) {
933 self.dcx.inner.borrow_mut().flush_delayed();
934 }
935
936 #[track_caller]
939 pub fn set_must_produce_diag(&self) {
940 if !self.dcx.inner.borrow().must_produce_diag.is_none() {
{
::core::panicking::panic_fmt(format_args!("should only need to collect a backtrace once"));
}
};assert!(
941 self.dcx.inner.borrow().must_produce_diag.is_none(),
942 "should only need to collect a backtrace once"
943 );
944 self.dcx.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> {
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_bug()
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> {
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_bug()
975 }
976
977 #[track_caller]
978 pub fn create_bug(self, bug: impl Diagnostic<'a>) -> Diag<'a> {
979 bug.into_diag(self, Bug)
980 }
981
982 #[track_caller]
983 pub fn emit_bug(self, bug: impl Diagnostic<'a>) -> ! {
984 self.create_bug(bug).emit_bug()
985 }
986
987 #[track_caller]
988 pub fn struct_fatal(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
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_fatal()
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> {
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_fatal()
1009 }
1010
1011 #[track_caller]
1012 pub fn create_fatal(self, fatal: impl Diagnostic<'a>) -> Diag<'a> {
1013 fatal.into_diag(self, Fatal)
1014 }
1015
1016 #[track_caller]
1017 pub fn emit_fatal(self, fatal: impl Diagnostic<'a>) -> ! {
1018 self.create_fatal(fatal).emit_fatal()
1019 }
1020
1021 #[track_caller]
1023 pub fn struct_err(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
1024 Diag::new(self, Error, msg)
1025 }
1026
1027 #[track_caller]
1028 pub fn err(self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed {
1029 self.struct_err(msg).emit_err()
1030 }
1031
1032 #[track_caller]
1033 pub fn struct_span_err(
1034 self,
1035 span: impl Into<MultiSpan>,
1036 msg: impl Into<DiagMessage>,
1037 ) -> Diag<'a> {
1038 self.struct_err(msg).with_span(span)
1039 }
1040
1041 #[track_caller]
1042 pub fn span_err(
1043 self,
1044 span: impl Into<MultiSpan>,
1045 msg: impl Into<DiagMessage>,
1046 ) -> ErrorGuaranteed {
1047 self.struct_span_err(span, msg).emit_err()
1048 }
1049
1050 #[track_caller]
1051 pub fn create_err(self, err: impl Diagnostic<'a>) -> Diag<'a> {
1052 err.into_diag(self, Error)
1053 }
1054
1055 #[track_caller]
1056 pub fn emit_err(self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
1057 self.create_err(err).emit_err()
1058 }
1059
1060 #[track_caller]
1062 pub fn delayed_bug(self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed {
1063 Diag::new(self, DelayedBug, msg.into()).emit_err()
1064 }
1065
1066 #[track_caller]
1071 pub fn span_delayed_bug(
1072 self,
1073 sp: impl Into<MultiSpan>,
1074 msg: impl Into<Cow<'static, str>>,
1075 ) -> ErrorGuaranteed {
1076 Diag::new(self, DelayedBug, msg.into()).with_span(sp).emit_err()
1077 }
1078
1079 #[track_caller]
1080 pub fn struct_warn(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
1081 Diag::new(self, Warning, msg)
1082 }
1083
1084 #[track_caller]
1085 pub fn warn(self, msg: impl Into<DiagMessage>) {
1086 self.struct_warn(msg).emit()
1087 }
1088
1089 #[track_caller]
1090 pub fn struct_span_warn(
1091 self,
1092 span: impl Into<MultiSpan>,
1093 msg: impl Into<DiagMessage>,
1094 ) -> Diag<'a> {
1095 self.struct_warn(msg).with_span(span)
1096 }
1097
1098 #[track_caller]
1099 pub fn span_warn(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1100 self.struct_span_warn(span, msg).emit()
1101 }
1102
1103 #[track_caller]
1104 pub fn create_warn(self, warning: impl Diagnostic<'a>) -> Diag<'a> {
1105 warning.into_diag(self, Warning)
1106 }
1107
1108 #[track_caller]
1109 pub fn emit_warn(self, warning: impl Diagnostic<'a>) {
1110 self.create_warn(warning).emit()
1111 }
1112
1113 #[track_caller]
1114 pub fn struct_note(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
1115 Diag::new(self, Note, msg)
1116 }
1117
1118 #[track_caller]
1119 pub fn note(&self, msg: impl Into<DiagMessage>) {
1120 self.struct_note(msg).emit()
1121 }
1122
1123 #[track_caller]
1124 pub fn struct_span_note(
1125 self,
1126 span: impl Into<MultiSpan>,
1127 msg: impl Into<DiagMessage>,
1128 ) -> Diag<'a> {
1129 self.struct_note(msg).with_span(span)
1130 }
1131
1132 #[track_caller]
1133 pub fn span_note(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1134 self.struct_span_note(span, msg).emit()
1135 }
1136
1137 #[track_caller]
1138 pub fn create_note(self, note: impl Diagnostic<'a>) -> Diag<'a> {
1139 note.into_diag(self, Note)
1140 }
1141
1142 #[track_caller]
1143 pub fn emit_note(self, note: impl Diagnostic<'a>) {
1144 self.create_note(note).emit()
1145 }
1146
1147 #[track_caller]
1148 pub fn struct_allow(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
1149 Diag::new(self, Allow, msg)
1150 }
1151
1152 #[track_caller]
1153 pub fn struct_expect(self, msg: impl Into<DiagMessage>, id: LintExpectationId) -> Diag<'a> {
1154 Diag::new(self, Expect, msg).with_lint_id(id)
1155 }
1156}
1157
1158impl DiagCtxtInner {
1159 fn new(emitter: Box<DynEmitter>) -> Self {
1160 Self {
1161 flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
1162 err_guars: Vec::new(),
1163 lint_err_guars: Vec::new(),
1164 delayed_bugs: Vec::new(),
1165 deduplicated_err_count: 0,
1166 deduplicated_warn_count: 0,
1167 emitter,
1168 must_produce_diag: None,
1169 has_printed: false,
1170 suppressed_expected_diag: false,
1171 taught_diagnostics: Default::default(),
1172 emitted_diagnostic_codes: Default::default(),
1173 emitted_diagnostics: Default::default(),
1174 emitted_recursion_depth_exceeding_limit: false,
1175 stashed_diagnostics: Default::default(),
1176 future_breakage_diagnostics: Vec::new(),
1177 fulfilled_expectations: Default::default(),
1178 ice_file: None,
1179 msrv: None,
1180 }
1181 }
1182
1183 fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
1185 let mut guar = None;
1186 let has_errors = !self.err_guars.is_empty();
1187 for (_, stashed_diagnostics) in mem::take(&mut self.stashed_diagnostics).into_iter() {
1188 for (_, (diag, _guar, _thread)) in stashed_diagnostics {
1189 if !diag.is_error() {
1190 if !diag.is_force_warn() && has_errors {
1194 continue;
1195 }
1196 }
1197 guar = guar.or(self.emit_diagnostic(diag, None));
1198 }
1199 }
1200 guar
1201 }
1202
1203 fn emit_diagnostic(
1205 &mut self,
1206 mut diagnostic: DiagInner,
1207 taint: Option<&Cell<Option<ErrorGuaranteed>>>,
1208 ) -> Option<ErrorGuaranteed> {
1209 if diagnostic.has_future_breakage() {
1210 {
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);
1214 self.future_breakage_diagnostics.push(diagnostic.clone());
1215 }
1216
1217 match diagnostic.level {
1221 Bug => {}
1222 Fatal | Error => {
1223 if self.treat_next_err_as_bug() {
1224 diagnostic.level = Bug;
1226 }
1227 }
1228 DelayedBug => {
1229 if self.flags.eagerly_emit_delayed_bugs {
1234 if self.treat_next_err_as_bug() {
1236 diagnostic.level = Bug;
1237 } else {
1238 diagnostic.level = Error;
1239 }
1240 } else {
1241 return if let Some(guar) = self.has_errors() {
1244 Some(guar)
1245 } else {
1246 let backtrace = std::backtrace::Backtrace::capture();
1250 #[allow(deprecated)]
1254 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1255 self.delayed_bugs
1256 .push((DelayedDiagInner::with_backtrace(diagnostic, backtrace), guar));
1257 Some(guar)
1258 };
1259 }
1260 }
1261 ForceWarning if diagnostic.lint_id.is_none() => {} Warning => {
1263 if !self.flags.can_emit_warnings {
1264 if diagnostic.has_future_breakage() {
1266 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1268 }
1269 return None;
1270 }
1271 }
1272 Note | Help | FailureNote => {}
1273 Allow => {
1274 if diagnostic.has_future_breakage() {
1276 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1278 self.suppressed_expected_diag = true;
1279 }
1280 return None;
1281 }
1282 Expect | ForceWarning => {
1283 self.fulfilled_expectations.insert(diagnostic.lint_id.unwrap());
1284 if let Expect = diagnostic.level {
1285 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1287 self.suppressed_expected_diag = true;
1288 return None;
1289 }
1290 }
1291 }
1292
1293 if let (Some(msrv), Some(diag_msrv)) = (self.msrv, diagnostic.rust_version())
1294 && diag_msrv > msrv
1295 {
1296 return None;
1297 }
1298
1299 TRACK_DIAGNOSTIC(diagnostic, &mut |mut diagnostic| {
1300 if let Some(code) = diagnostic.code {
1301 self.emitted_diagnostic_codes.insert(code);
1302 }
1303
1304 let already_emitted = !self.emitted_diagnostics.insert(diagnostic.dedup_hash());
1305
1306 let is_error = diagnostic.is_error();
1307 let is_lint = diagnostic.is_lint.is_some();
1308 let silence_recursion_depth_exceeded_limit =
1310 diagnostic.is_lint.as_ref().is_some_and(|lint| {
1311 lint.name.eq_ignore_ascii_case(
1312 rustc_lint_defs::builtin::RECURSION_DEPTH_EXCEEDING_LIMIT.name,
1313 ) && mem::replace(&mut self.emitted_recursion_depth_exceeding_limit, true)
1314 });
1315
1316 if !silence_recursion_depth_exceeded_limit
1319 && !(self.flags.deduplicate_diagnostics && already_emitted)
1320 {
1321 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/f7575a9da8e4a4fca3b5668d5a2ea7476db44b3f/compiler/rustc_errors/src/lib.rs:1321",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/f7575a9da8e4a4fca3b5668d5a2ea7476db44b3f/compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1321u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("diagnostic")
}> =
::tracing::__macro_support::FieldName::new("diagnostic");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&diagnostic)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?diagnostic);
1322 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/f7575a9da8e4a4fca3b5668d5a2ea7476db44b3f/compiler/rustc_errors/src/lib.rs:1322",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/f7575a9da8e4a4fca3b5668d5a2ea7476db44b3f/compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1322u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("self.emitted_diagnostics")
}> =
::tracing::__macro_support::FieldName::new("self.emitted_diagnostics");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.emitted_diagnostics)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?self.emitted_diagnostics);
1323
1324 let not_yet_emitted = |sub: &mut Subdiag| {
1325 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/f7575a9da8e4a4fca3b5668d5a2ea7476db44b3f/compiler/rustc_errors/src/lib.rs:1325",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/f7575a9da8e4a4fca3b5668d5a2ea7476db44b3f/compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1325u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("sub")
}> =
::tracing::__macro_support::FieldName::new("sub");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sub)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?sub);
1326 match sub.level {
1327 Sublevel::Error | Sublevel::Warning | Sublevel::Note | Sublevel::Help => {
1328 return true;
1329 }
1330 Sublevel::OnceNote | Sublevel::OnceHelp => {}
1331 }
1332 let mut hasher = StableHasher::new();
1333 sub.hash(&mut hasher);
1334 let diagnostic_hash = hasher.finish();
1335 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/f7575a9da8e4a4fca3b5668d5a2ea7476db44b3f/compiler/rustc_errors/src/lib.rs:1335",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/f7575a9da8e4a4fca3b5668d5a2ea7476db44b3f/compiler/rustc_errors/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1335u32),
::tracing_core::__macro_support::Option::Some("rustc_errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("diagnostic_hash")
}> =
::tracing::__macro_support::FieldName::new("diagnostic_hash");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&diagnostic_hash)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?diagnostic_hash);
1336 self.emitted_diagnostics.insert(diagnostic_hash)
1337 };
1338 diagnostic.children.retain_mut(not_yet_emitted);
1339 if already_emitted {
1340 let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
1341 diagnostic.sub(Sublevel::Note, msg, MultiSpan::new());
1342 }
1343
1344 if is_error {
1345 self.deduplicated_err_count += 1;
1346 } else if #[allow(non_exhaustive_omitted_patterns)] match diagnostic.level {
ForceWarning | Warning => true,
_ => false,
}matches!(diagnostic.level, ForceWarning | Warning) {
1347 self.deduplicated_warn_count += 1;
1348 }
1349 self.has_printed = true;
1350
1351 self.emitter.emit_diagnostic(diagnostic);
1352 }
1353
1354 if is_error {
1355 if !self.delayed_bugs.is_empty() {
1360 {
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);
1361 self.delayed_bugs.clear();
1362 self.delayed_bugs.shrink_to_fit();
1363 }
1364
1365 #[allow(deprecated)]
1368 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1369 let thread = std::thread::current().id();
1370 if is_lint {
1371 self.lint_err_guars.push((guar, thread));
1372 } else {
1373 if let Some(taint) = taint {
1374 taint.set(Some(guar));
1375 }
1376 self.err_guars.push((guar, thread));
1377 }
1378 self.panic_if_treat_err_as_bug();
1379 Some(guar)
1380 } else {
1381 None
1382 }
1383 })
1384 }
1385
1386 fn treat_err_as_bug(&self) -> bool {
1387 self.flags
1388 .treat_err_as_bug
1389 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() >= c.get())
1390 }
1391
1392 fn treat_next_err_as_bug(&self) -> bool {
1394 self.flags
1395 .treat_err_as_bug
1396 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() + 1 >= c.get())
1397 }
1398
1399 fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
1400 self.err_guars.get(0).map(|(guar, _)| *guar).or_else(|| {
1401 if let Some((_diag, guar, _)) = self
1402 .stashed_diagnostics
1403 .values()
1404 .flat_map(|stashed_diagnostics| stashed_diagnostics.values())
1405 .find(|(diag, guar, _)| guar.is_some() && diag.is_lint.is_none())
1406 {
1407 *guar
1408 } else {
1409 None
1410 }
1411 })
1412 }
1413
1414 fn has_errors(&self) -> Option<ErrorGuaranteed> {
1415 self.err_guars
1416 .get(0)
1417 .map(|(guar, _)| *guar)
1418 .or_else(|| self.lint_err_guars.get(0).map(|(guar, _)| *guar))
1419 .or_else(|| {
1420 self.stashed_diagnostics.values().find_map(|stashed_diagnostics| {
1421 stashed_diagnostics.values().find_map(|(_, guar, _)| *guar)
1422 })
1423 })
1424 }
1425
1426 fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
1427 self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
1428 }
1429
1430 fn flush_delayed(&mut self) {
1431 if !self.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: self.stashed_diagnostics.is_empty()")
};assert!(self.stashed_diagnostics.is_empty());
1435
1436 if !self.err_guars.is_empty() {
1437 return;
1439 }
1440
1441 if self.delayed_bugs.is_empty() {
1442 return;
1444 }
1445
1446 let bugs: Vec<_> = mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();
1447
1448 let backtrace = std::env::var_os("RUST_BACKTRACE").as_deref() != Some(OsStr::new("0"));
1449 let decorate = backtrace || self.ice_file.is_none();
1450 let mut out = self
1451 .ice_file
1452 .as_ref()
1453 .and_then(|file| std::fs::File::options().create(true).append(true).open(file).ok());
1454
1455 let note1 = "no errors encountered even though delayed bugs were created";
1460 let note2 = "those delayed bugs will now be shown as internal compiler errors";
1461 self.emit_diagnostic(DiagInner::new(Note, note1), None);
1462 self.emit_diagnostic(DiagInner::new(Note, note2), None);
1463
1464 for bug in bugs {
1465 if let Some(out) = &mut out {
1466 _ = 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!(
1467 out,
1468 "delayed bug: {}\n{}\n",
1469 bug.inner
1470 .messages
1471 .iter()
1472 .filter_map(|(msg, _)| msg.as_str())
1473 .collect::<String>(),
1474 &bug.note
1475 );
1476 }
1477
1478 let mut bug = if decorate { bug.decorate() } else { bug.inner };
1479
1480 if bug.level != DelayedBug {
1482 let msg = rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"))msg!(
1489 "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"
1490 ).arg("level", bug.level).format();
1491 bug.sub(Sublevel::Note, msg, bug.span.primary_span().unwrap().into());
1492 }
1493 bug.level = Bug;
1494
1495 self.emit_diagnostic(bug, None);
1496 }
1497
1498 panic::panic_any(DelayedBugPanic);
1500 }
1501
1502 fn panic_if_treat_err_as_bug(&self) {
1503 if self.treat_err_as_bug() {
1504 let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
1505 {
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());
1506 if n == 1 {
1507 {
::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`");
1508 } else {
1509 {
::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}`");
1510 }
1511 }
1512 }
1513}
1514
1515struct DelayedDiagInner {
1516 inner: DiagInner,
1517 note: Backtrace,
1518}
1519
1520impl DelayedDiagInner {
1521 fn with_backtrace(diagnostic: DiagInner, backtrace: Backtrace) -> Self {
1522 DelayedDiagInner { inner: diagnostic, note: backtrace }
1523 }
1524
1525 fn decorate(self) -> DiagInner {
1526 let mut diag = self.inner;
1530 let msg = match self.note.status() {
1531 BacktraceStatus::Captured => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at}\n {$note}"))msg!(
1532 "delayed at {$emitted_at}
1533 {$note}"
1534 ),
1535 _ => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at} - {$note}"))msg!("delayed at {$emitted_at} - {$note}"),
1538 }
1539 .arg("emitted_at", diag.emitted_at.clone())
1540 .arg("note", self.note)
1541 .format();
1542 diag.sub(Sublevel::Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
1543 diag
1544 }
1545}
1546
1547#[derive(#[automatically_derived]
impl ::core::marker::Copy for Level { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Level { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Level {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Level { }Eq, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Level { }
#[automatically_derived]
impl ::core::clone::Clone for Level {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for Level {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state)
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Level {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Level::Bug => "Bug",
Level::Fatal => "Fatal",
Level::Error => "Error",
Level::DelayedBug => "DelayedBug",
Level::ForceWarning => "ForceWarning",
Level::Warning => "Warning",
Level::Note => "Note",
Level::Help => "Help",
Level::FailureNote => "FailureNote",
Level::Allow => "Allow",
Level::Expect => "Expect",
})
}
}Debug, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Level {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
Level::Bug => { 0usize }
Level::Fatal => { 1usize }
Level::Error => { 2usize }
Level::DelayedBug => { 3usize }
Level::ForceWarning => { 4usize }
Level::Warning => { 5usize }
Level::Note => { 6usize }
Level::Help => { 7usize }
Level::FailureNote => { 8usize }
Level::Allow => { 9usize }
Level::Expect => { 10usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Level {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { Level::Bug }
1usize => { Level::Fatal }
2usize => { Level::Error }
3usize => { Level::DelayedBug }
4usize => { Level::ForceWarning }
5usize => { Level::Warning }
6usize => { Level::Note }
7usize => { Level::Help }
8usize => { Level::FailureNote }
9usize => { Level::Allow }
10usize => { Level::Expect }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Level`, expected 0..11, actual {0}",
n));
}
}
}
}
};Decodable)]
1562pub enum Level {
1563 Bug,
1565
1566 Fatal,
1569
1570 Error,
1573
1574 DelayedBug,
1579
1580 ForceWarning,
1586
1587 Warning,
1590
1591 Note,
1593
1594 Help,
1600
1601 FailureNote,
1604
1605 Allow,
1607
1608 Expect,
1610}
1611
1612impl fmt::Display for Level {
1613 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1614 self.to_str().fmt(f)
1615 }
1616}
1617
1618impl Level {
1619 pub fn to_str(self) -> &'static str {
1620 match self {
1621 Bug | DelayedBug => "error: internal compiler error",
1622 Fatal | Error => "error",
1623 ForceWarning | Warning => "warning",
1624 Note => "note",
1625 Help => "help",
1626 FailureNote => "failure-note",
1627 Allow | Expect => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1628 }
1629 }
1630
1631 pub fn is_failure_note(&self) -> bool {
1632 #[allow(non_exhaustive_omitted_patterns)] match *self {
FailureNote => true,
_ => false,
}matches!(*self, FailureNote)
1633 }
1634}
1635
1636impl IntoDiagArg for Level {
1637 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
1638 DiagArgValue::Str(Cow::from(self.to_string()))
1639 }
1640}
1641
1642#[derive(#[automatically_derived]
impl ::core::marker::Copy for Sublevel { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Sublevel { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Sublevel {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Sublevel { }Eq, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Sublevel { }
#[automatically_derived]
impl ::core::clone::Clone for Sublevel {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for Sublevel {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state)
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Sublevel {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Sublevel::Error => "Error",
Sublevel::Warning => "Warning",
Sublevel::Note => "Note",
Sublevel::OnceNote => "OnceNote",
Sublevel::Help => "Help",
Sublevel::OnceHelp => "OnceHelp",
})
}
}Debug, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Sublevel {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
Sublevel::Error => { 0usize }
Sublevel::Warning => { 1usize }
Sublevel::Note => { 2usize }
Sublevel::OnceNote => { 3usize }
Sublevel::Help => { 4usize }
Sublevel::OnceHelp => { 5usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Sublevel {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { Sublevel::Error }
1usize => { Sublevel::Warning }
2usize => { Sublevel::Note }
3usize => { Sublevel::OnceNote }
4usize => { Sublevel::Help }
5usize => { Sublevel::OnceHelp }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Sublevel`, expected 0..6, actual {0}",
n));
}
}
}
}
};Decodable)]
1644pub enum Sublevel {
1645 Error,
1650
1651 Warning,
1653
1654 Note,
1656
1657 OnceNote,
1659
1660 Help,
1662
1663 OnceHelp,
1665}
1666
1667impl Sublevel {
1668 pub fn to_str(self) -> &'static str {
1669 match self {
1670 Sublevel::Error => "error",
1671 Sublevel::Warning => "warning",
1672 Sublevel::Note | Sublevel::OnceNote => "note",
1673 Sublevel::Help | Sublevel::OnceHelp => "help",
1674 }
1675 }
1676}
1677
1678#[derive(#[automatically_derived]
impl ::core::marker::Copy for Style { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Style { }
#[automatically_derived]
impl ::core::clone::Clone for Style {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Style {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Style::NoStyle => "NoStyle",
Style::Highlight => "Highlight",
})
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Style { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Style {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Style { }Eq, #[automatically_derived]
impl ::core::hash::Hash for Style {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Style {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
Style::NoStyle => { 0usize }
Style::Highlight => { 1usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Style {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { Style::NoStyle }
1usize => { Style::Highlight }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Style`, expected 0..2, actual {0}",
n));
}
}
}
}
};Decodable)]
1679pub enum Style {
1680 NoStyle,
1681 Highlight,
1682}
1683
1684pub fn elided_lifetime_in_path_suggestion(
1686 source_map: &SourceMap,
1687 n: usize,
1688 path_span: Span,
1689 incl_angl_brckt: bool,
1690 insertion_span: Span,
1691) -> ElidedLifetimeInPathSubdiag {
1692 let expected = ExpectedLifetimeParameter { span: path_span, count: n };
1693 let indicate = source_map.is_span_accessible(insertion_span).then(|| {
1695 let anon_lts = ::alloc::vec::from_elem("'_", n)vec!["'_"; n].join(", ");
1696 let suggestion =
1697 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}, ") };
1698
1699 IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }
1700 });
1701
1702 ElidedLifetimeInPathSubdiag { expected, indicate }
1703}
1704
1705pub fn a_or_an(s: &str) -> &'static str {
1709 let mut chars = s.chars();
1710 let Some(mut first_alpha_char) = chars.next() else {
1711 return "a";
1712 };
1713 if first_alpha_char == '`' {
1714 let Some(next) = chars.next() else {
1715 return "a";
1716 };
1717 first_alpha_char = next;
1718 }
1719 if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) {
1720 "an"
1721 } else {
1722 "a"
1723 }
1724}
1725
1726#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for TerminalUrl { }
#[automatically_derived]
impl ::core::clone::Clone for TerminalUrl {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TerminalUrl { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for TerminalUrl { }
#[automatically_derived]
impl ::core::cmp::PartialEq for TerminalUrl {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for TerminalUrl {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
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)]
1727pub enum TerminalUrl {
1728 No,
1729 Yes,
1730 Auto,
1731}