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::sync::{DynSend, Lock};
48pub use rustc_error_messages::{
49 DiagArg, DiagArgFromDisplay, DiagArgMap, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg,
50 LanguageIdentifier, MultiSpan, SpanLabel, fluent_bundle, into_diag_arg_using_display,
51};
52use rustc_hashes::Hash128;
53use rustc_lint_defs::LintExpectationId;
54pub use rustc_lint_defs::{Applicability, listify, pluralize};
55pub use rustc_macros::msg;
56use rustc_macros::{Decodable, Encodable};
57pub use rustc_span::ErrorGuaranteed;
58pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors};
59pub use rustc_span::macros::ExplicitBug;
60use rustc_span::source_map::SourceMap;
61use rustc_span::{DUMMY_SP, Span};
62use tracing::debug;
63
64use crate::emitter::TimingEvent;
65use crate::formatting::DiagMessageAddArg;
66pub use crate::formatting::format_diag_message;
67use crate::timings::TimingRecord;
68
69pub mod annotate_snippet_emitter_writer;
70pub mod codes;
71mod decorate_diag;
72mod dedup_hash;
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) =>
Suggestions::Enabled(::core::clone::Clone::clone(__self_0)),
Self::Sealed(__self_0) =>
Suggestions::Sealed(::core::clone::Clone::clone(__self_0)),
Self::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 {
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 {
CodeSuggestion {
substitutions: ::core::clone::Clone::clone(&self.substitutions),
msg: ::core::clone::Clone::clone(&self.msg),
style: ::core::clone::Clone::clone(&self.style),
applicability: ::core::clone::Clone::clone(&self.applicability),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for CodeSuggestion {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"CodeSuggestion", "substitutions", &self.substitutions, "msg",
&self.msg, "style", &self.style, "applicability",
&&self.applicability)
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for CodeSuggestion { }
#[automatically_derived]
impl ::core::cmp::PartialEq for CodeSuggestion {
#[inline]
fn eq(&self, other: &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 {
Substitution { parts: ::core::clone::Clone::clone(&self.parts) }
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Substitution {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "Substitution",
"parts", &&self.parts)
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Substitution { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Substitution {
#[inline]
fn eq(&self, other: &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 {
SubstitutionPart {
span: ::core::clone::Clone::clone(&self.span),
snippet: ::core::clone::Clone::clone(&self.snippet),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for SubstitutionPart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"SubstitutionPart", "span", &self.span, "snippet", &&self.snippet)
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for SubstitutionPart { }
#[automatically_derived]
impl ::core::cmp::PartialEq for SubstitutionPart {
#[inline]
fn eq(&self, other: &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 {
TrimmedSubstitutionPart {
original_span: ::core::clone::Clone::clone(&self.original_span),
span: ::core::clone::Clone::clone(&self.span),
snippet: ::core::clone::Clone::clone(&self.snippet),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for TrimmedSubstitutionPart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"TrimmedSubstitutionPart", "original_span", &self.original_span,
"span", &self.span, "snippet", &&self.snippet)
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for TrimmedSubstitutionPart { }
#[automatically_derived]
impl ::core::cmp::PartialEq for TrimmedSubstitutionPart {
#[inline]
fn eq(&self, other: &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>,
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]
#[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)]
375pub enum StashKey {
376 ItemNoType,
377 EarlySyntaxWarning,
378 CallIntoMethod,
379 LifetimeIsChar,
382 MaybeFruTypo,
385 CallAssocMethod,
386 UndeterminedMacroResolution,
387 ExprInPat,
389 GenericInFieldExpr,
393 ReturnTypeNotation,
394}
395
396fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
397 (*f)(diag)
398}
399
400pub static TRACK_DIAGNOSTIC: AtomicRef<
403 fn(DiagInner, &mut dyn FnMut(DiagInner) -> Option<ErrorGuaranteed>) -> Option<ErrorGuaranteed>,
404> = AtomicRef::new(&(default_track_diagnostic as _));
405
406#[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 {
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)]
407pub struct DiagCtxtFlags {
408 pub can_emit_warnings: bool,
411 pub treat_err_as_bug: Option<NonZero<usize>>,
414 pub eagerly_emit_delayed_bugs: bool,
417 pub macro_backtrace: bool,
420 pub deduplicate_diagnostics: bool,
422 pub track_diagnostics: bool,
424}
425
426impl Drop for DiagCtxtInner {
427 fn drop(&mut self) {
428 self.emit_stashed_diagnostics();
436
437 self.flush_delayed();
441
442 if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
446 if let Some(backtrace) = &self.must_produce_diag {
447 let suggestion = match backtrace.status() {
448 BacktraceStatus::Disabled => String::from(
449 "Backtraces are currently disabled: set `RUST_BACKTRACE=1` and re-run \
450 to see where it happened.",
451 ),
452 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!(
453 "This happened in the following `must_produce_diag` call's backtrace:\n\
454 {backtrace}",
455 ),
456 _ => String::from("(impossible to capture backtrace where this happened)"),
457 };
458 {
::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!(
459 "`trimmed_def_paths` called, diagnostics were expected but none were emitted. \
460 Use `with_no_trimmed_paths` for debugging. {suggestion}"
461 );
462 }
463 }
464 }
465}
466
467impl DiagCtxt {
468 pub fn disable_warnings(mut self) -> Self {
469 self.inner.get_mut().flags.can_emit_warnings = false;
470 self
471 }
472
473 pub fn with_flags(mut self, flags: DiagCtxtFlags) -> Self {
474 self.inner.get_mut().flags = flags;
475 self
476 }
477
478 pub fn with_ice_file(mut self, ice_file: PathBuf) -> Self {
479 self.inner.get_mut().ice_file = Some(ice_file);
480 self
481 }
482
483 pub fn with_msrv(mut self, msrv: RustcVersion) -> Self {
484 self.inner.get_mut().msrv = Some(msrv);
485 self
486 }
487
488 pub fn new(emitter: Box<DynEmitter>) -> Self {
489 Self { inner: Lock::new(DiagCtxtInner::new(emitter)) }
490 }
491
492 pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> {
493 DiagCtxtHandle { dcx: self, tainted_with_errors: None }
494 }
495}
496
497impl<'a> DiagCtxtHandle<'a> {
498 pub fn make_silent(&self) {
499 let mut inner = self.dcx.inner.borrow_mut();
500 inner.emitter = Box::new(emitter::SilentEmitter {});
501 }
502
503 pub fn set_emitter(&self, emitter: Box<dyn Emitter + DynSend>) {
504 self.dcx.inner.borrow_mut().emitter = emitter;
505 }
506
507 pub fn can_emit_warnings(&self) -> bool {
510 self.dcx.inner.borrow().flags.can_emit_warnings
511 }
512
513 pub fn reset_err_count(&self) {
519 let mut inner = self.dcx.inner.borrow_mut();
522 let DiagCtxtInner {
523 flags: _,
524 err_guars,
525 lint_err_guars,
526 delayed_bugs,
527 deduplicated_err_count,
528 deduplicated_warn_count,
529 emitter: _,
530 must_produce_diag,
531 has_printed,
532 suppressed_expected_diag,
533 taught_diagnostics,
534 emitted_diagnostic_codes,
535 emitted_diagnostics,
536 emitted_recursion_depth_exceeding_limit,
537 stashed_diagnostics,
538 future_breakage_diagnostics,
539 fulfilled_expectations,
540 ice_file: _,
541 msrv: _,
542 } = inner.deref_mut();
543
544 *err_guars = Default::default();
547 *lint_err_guars = Default::default();
548 *delayed_bugs = Default::default();
549 *deduplicated_err_count = 0;
550 *deduplicated_warn_count = 0;
551 *must_produce_diag = None;
552 *has_printed = false;
553 *suppressed_expected_diag = false;
554 *taught_diagnostics = Default::default();
555 *emitted_diagnostic_codes = Default::default();
556 *emitted_diagnostics = Default::default();
557 *emitted_recursion_depth_exceeding_limit = false;
558 *stashed_diagnostics = Default::default();
559 *future_breakage_diagnostics = Default::default();
560 *fulfilled_expectations = Default::default();
561 }
562
563 pub fn into_taintable(
567 self,
568 tainted_with_errors: &'a Cell<Option<ErrorGuaranteed>>,
569 ) -> DiagCtxtHandle<'a> {
570 DiagCtxtHandle { dcx: self.dcx, tainted_with_errors: Some(tainted_with_errors) }
571 }
572
573 pub fn stash_diagnostic(
595 &self,
596 span: Span,
597 key: StashKey,
598 diag: DiagInner,
599 ) -> Option<ErrorGuaranteed> {
600 let guar = match diag.level {
601 Bug | Fatal => {
602 self.span_bug(
603 span,
604 ::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),
605 );
606 }
607 Error => Some(self.span_delayed_bug(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("stashing {0:?}", key))
})format!("stashing {key:?}"))),
611 DelayedBug => {
612 return self.dcx.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors);
613 }
614 Warning(_) | Note | Help | FailureNote => None,
615 };
616
617 self.dcx
621 .inner
622 .borrow_mut()
623 .stashed_diagnostics
624 .entry(key)
625 .or_default()
626 .insert(span.with_parent(None), (diag, guar, std::thread::current().id()));
627
628 guar
629 }
630
631 pub fn steal_non_err(self, span: Span, key: StashKey) -> Option<Diag<'a>> {
635 let (diag, guar, _) =
637 self.dcx.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.dcx.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);
664 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
665 let mut err = Diag::new_diagnostic(self, err);
666 modify_err(&mut err);
667 {
match (&err.level, &Error) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(err.level, Error);
668 err.emit_err()
669 })
670 }
671
672 pub fn try_steal_replace_and_emit_err(
676 self,
677 span: Span,
678 key: StashKey,
679 new_err: Diag<'_>,
680 ) -> ErrorGuaranteed {
681 let old_err = self.dcx.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
683 |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
684 );
685 match old_err {
686 Some((old_err, guar, _)) => {
687 {
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);
688 if !guar.is_some() {
::core::panicking::panic("assertion failed: guar.is_some()")
};assert!(guar.is_some());
689 Diag::new_diagnostic(self, old_err).cancel();
692 }
693 None => {}
694 };
695 new_err.emit_err()
696 }
697
698 pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool {
699 let inner = self.dcx.inner.borrow();
700 if let Some(stashed_diagnostics) = inner.stashed_diagnostics.get(&key)
701 && !stashed_diagnostics.is_empty()
702 {
703 stashed_diagnostics.contains_key(&span.with_parent(None))
704 } else {
705 false
706 }
707 }
708
709 pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
711 self.dcx.inner.borrow_mut().emit_stashed_diagnostics()
712 }
713
714 #[inline]
716 pub fn err_count(&self) -> usize {
717 let inner = self.dcx.inner.borrow();
718 inner.err_guars.len()
719 + inner.lint_err_guars.len()
720 + inner
721 .stashed_diagnostics
722 .values()
723 .map(|a| a.values().filter(|(_, guar, _)| guar.is_some()).count())
724 .sum::<usize>()
725 }
726
727 pub fn err_count_on_current_thread(&self) -> usize {
732 let inner = self.dcx.inner.borrow();
733 let current = std::thread::current().id();
734 inner.err_guars.iter().filter(|(_, thread)| *thread == current).count()
735 + inner.lint_err_guars.iter().filter(|(_, thread)| *thread == current).count()
736 + inner
737 .stashed_diagnostics
738 .values()
739 .map(|a| {
740 a.values()
741 .filter(|(_, guar, thread)| guar.is_some() && *thread == current)
742 .count()
743 })
744 .sum::<usize>()
745 }
746
747 pub fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
750 self.dcx.inner.borrow().has_errors_excluding_lint_errors()
751 }
752
753 pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
755 self.dcx.inner.borrow().has_errors()
756 }
757
758 pub fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
761 self.dcx.inner.borrow().has_errors_or_delayed_bugs()
762 }
763
764 pub fn print_error_count(&self) {
765 let mut inner = self.dcx.inner.borrow_mut();
766
767 if !inner.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: inner.stashed_diagnostics.is_empty()")
};assert!(inner.stashed_diagnostics.is_empty());
770
771 if inner.treat_err_as_bug() {
772 return;
773 }
774
775 let warnings = match inner.deduplicated_warn_count {
776 0 => Cow::from(""),
777 1 => Cow::from("1 warning emitted"),
778 count => Cow::from(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} warnings emitted", count))
})format!("{count} warnings emitted")),
779 };
780 let errors = match inner.deduplicated_err_count {
781 0 => Cow::from(""),
782 1 => Cow::from("aborting due to 1 previous error"),
783 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")),
784 };
785
786 match (errors.len(), warnings.len()) {
787 (0, 0) => return,
788 (0, _) => {
789 let diag = DiagInner::new(
791 Warning(Some(EmissionOverride::Forced { lint_id: None })),
792 DiagMessage::Str(warnings),
793 );
794 inner.emit_diagnostic(diag, None);
795 }
796 (_, 0) => {
797 inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors);
798 }
799 (_, _) => {
800 inner.emit_diagnostic(
801 DiagInner::new(Error, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}; {1}", errors, warnings))
})format!("{errors}; {warnings}")),
802 self.tainted_with_errors,
803 );
804 }
805 }
806
807 let can_show_explain = inner.emitter.should_show_explain();
808 let are_there_diagnostics = !inner.emitted_diagnostic_codes.is_empty();
809 if can_show_explain && are_there_diagnostics {
810 let mut error_codes = inner
811 .emitted_diagnostic_codes
812 .iter()
813 .filter_map(|&code| {
814 if crate::codes::try_find_description(code).is_ok() {
815 Some(code.to_string())
816 } else {
817 None
818 }
819 })
820 .collect::<Vec<_>>();
821 if !error_codes.is_empty() {
822 error_codes.sort();
823 if error_codes.len() > 1 {
824 let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
825 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!(
826 "Some errors have detailed explanations: {}{}",
827 error_codes[..limit].join(", "),
828 if error_codes.len() > 9 { "..." } else { "." }
829 );
830 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!(
831 "For more information about an error, try `rustc --explain {}`.",
832 &error_codes[0]
833 );
834 inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None);
835 inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None);
836 } else {
837 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!(
838 "For more information about this error, try `rustc --explain {}`.",
839 &error_codes[0]
840 );
841 inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None);
842 }
843 }
844 }
845 }
846
847 pub fn abort_if_errors(&self) {
852 if let Some(guar) = self.has_errors() {
853 guar.raise_fatal();
854 }
855 }
856
857 pub fn must_teach(&self, code: ErrCode) -> bool {
863 self.dcx.inner.borrow_mut().taught_diagnostics.insert(code)
864 }
865
866 pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
867 self.dcx.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors)
868 }
869
870 pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
871 self.dcx.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type);
872 }
873
874 pub fn emit_timing_section_start(&self, record: TimingRecord) {
875 self.dcx.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start);
876 }
877
878 pub fn emit_timing_section_end(&self, record: TimingRecord) {
879 self.dcx.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::End);
880 }
881
882 pub fn emit_future_breakage_report(&self) {
883 let inner = &mut *self.dcx.inner.borrow_mut();
884 let diags = mem::take(&mut inner.future_breakage_diagnostics);
885 if !diags.is_empty() {
886 inner.emitter.emit_future_breakage_report(diags);
887 }
888 }
889
890 pub fn emit_unused_externs(
891 &self,
892 lint_level: rustc_lint_defs::Level,
893 loud: bool,
894 unused_externs: &[&str],
895 ) {
896 let mut inner = self.dcx.inner.borrow_mut();
897
898 if loud && lint_level.is_error() {
909 #[allow(deprecated)]
912 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
913 inner.lint_err_guars.push((guar, std::thread::current().id()));
914 inner.panic_if_treat_err_as_bug();
915 }
916
917 inner.emitter.emit_unused_externs(lint_level, unused_externs)
918 }
919
920 #[track_caller]
925 pub fn fulfill_expectation(self, expectation: impl Into<LintExpectationId>) {
926 let emission_override = Some(EmissionOverride::Expected { lint_id: expectation.into() });
927 let msg = "this is a dummy diagnostic, to submit and store an expectation";
928 Diag::new(self, Warning(emission_override), msg).emit()
929 }
930
931 #[must_use]
934 pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet<LintExpectationId> {
935 mem::take(&mut self.dcx.inner.borrow_mut().fulfilled_expectations)
936 }
937
938 pub fn flush_delayed(&self) {
943 self.dcx.inner.borrow_mut().flush_delayed();
944 }
945
946 #[track_caller]
949 pub fn set_must_produce_diag(&self) {
950 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!(
951 self.dcx.inner.borrow().must_produce_diag.is_none(),
952 "should only need to collect a backtrace once"
953 );
954 self.dcx.inner.borrow_mut().must_produce_diag = Some(Backtrace::capture());
955 }
956}
957
958impl<'a> DiagCtxtHandle<'a> {
963 #[track_caller]
964 pub fn struct_bug(self, msg: impl Into<Cow<'static, str>>) -> Diag<'a> {
965 Diag::new(self, Bug, msg.into())
966 }
967
968 #[track_caller]
969 pub fn bug(self, msg: impl Into<Cow<'static, str>>) -> ! {
970 self.struct_bug(msg).emit_bug()
971 }
972
973 #[track_caller]
974 pub fn struct_span_bug(
975 self,
976 span: impl Into<MultiSpan>,
977 msg: impl Into<Cow<'static, str>>,
978 ) -> Diag<'a> {
979 self.struct_bug(msg).with_span(span)
980 }
981
982 #[track_caller]
983 pub fn span_bug(self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! {
984 self.struct_span_bug(span, msg.into()).emit_bug()
985 }
986
987 #[track_caller]
988 pub fn create_bug(self, bug: impl Diagnostic<'a>) -> Diag<'a> {
989 bug.into_diag(self, Bug)
990 }
991
992 #[track_caller]
993 pub fn emit_bug(self, bug: impl Diagnostic<'a>) -> ! {
994 self.create_bug(bug).emit_bug()
995 }
996
997 #[track_caller]
998 pub fn struct_fatal(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
999 Diag::new(self, Fatal, msg)
1000 }
1001
1002 #[track_caller]
1003 pub fn fatal(self, msg: impl Into<DiagMessage>) -> ! {
1004 self.struct_fatal(msg).emit_fatal()
1005 }
1006
1007 #[track_caller]
1008 pub fn struct_span_fatal(
1009 self,
1010 span: impl Into<MultiSpan>,
1011 msg: impl Into<DiagMessage>,
1012 ) -> Diag<'a> {
1013 self.struct_fatal(msg).with_span(span)
1014 }
1015
1016 #[track_caller]
1017 pub fn span_fatal(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) -> ! {
1018 self.struct_span_fatal(span, msg).emit_fatal()
1019 }
1020
1021 #[track_caller]
1022 pub fn create_fatal(self, fatal: impl Diagnostic<'a>) -> Diag<'a> {
1023 fatal.into_diag(self, Fatal)
1024 }
1025
1026 #[track_caller]
1027 pub fn emit_fatal(self, fatal: impl Diagnostic<'a>) -> ! {
1028 self.create_fatal(fatal).emit_fatal()
1029 }
1030
1031 #[track_caller]
1032 pub fn struct_err(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
1033 Diag::new(self, Error, msg)
1034 }
1035
1036 #[track_caller]
1037 pub fn err(self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed {
1038 self.struct_err(msg).emit_err()
1039 }
1040
1041 #[track_caller]
1042 pub fn struct_span_err(
1043 self,
1044 span: impl Into<MultiSpan>,
1045 msg: impl Into<DiagMessage>,
1046 ) -> Diag<'a> {
1047 self.struct_err(msg).with_span(span)
1048 }
1049
1050 #[track_caller]
1051 pub fn span_err(
1052 self,
1053 span: impl Into<MultiSpan>,
1054 msg: impl Into<DiagMessage>,
1055 ) -> ErrorGuaranteed {
1056 self.struct_span_err(span, msg).emit_err()
1057 }
1058
1059 #[track_caller]
1060 pub fn create_err(self, err: impl Diagnostic<'a>) -> Diag<'a> {
1061 err.into_diag(self, Error)
1062 }
1063
1064 #[track_caller]
1065 pub fn emit_err(self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
1066 self.create_err(err).emit_err()
1067 }
1068
1069 #[track_caller]
1071 pub fn delayed_bug(self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed {
1072 Diag::new(self, DelayedBug, msg.into()).emit_err()
1073 }
1074
1075 #[track_caller]
1080 pub fn span_delayed_bug(
1081 self,
1082 sp: impl Into<MultiSpan>,
1083 msg: impl Into<Cow<'static, str>>,
1084 ) -> ErrorGuaranteed {
1085 Diag::new(self, DelayedBug, msg.into()).with_span(sp).emit_err()
1086 }
1087
1088 #[track_caller]
1089 pub fn struct_warn(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
1090 Diag::new(self, Warning(None), msg)
1091 }
1092
1093 #[track_caller]
1094 pub fn warn(self, msg: impl Into<DiagMessage>) {
1095 self.struct_warn(msg).emit()
1096 }
1097
1098 #[track_caller]
1099 pub fn struct_span_warn(
1100 self,
1101 span: impl Into<MultiSpan>,
1102 msg: impl Into<DiagMessage>,
1103 ) -> Diag<'a> {
1104 self.struct_warn(msg).with_span(span)
1105 }
1106
1107 #[track_caller]
1108 pub fn span_warn(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1109 self.struct_span_warn(span, msg).emit()
1110 }
1111
1112 #[track_caller]
1113 pub fn create_warn(self, warning: impl Diagnostic<'a>) -> Diag<'a> {
1114 warning.into_diag(self, Warning(None))
1115 }
1116
1117 #[track_caller]
1118 pub fn emit_warn(self, warning: impl Diagnostic<'a>) {
1119 self.create_warn(warning).emit()
1120 }
1121
1122 #[track_caller]
1123 pub fn struct_note(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
1124 Diag::new(self, Note, msg)
1125 }
1126
1127 #[track_caller]
1128 pub fn note(&self, msg: impl Into<DiagMessage>) {
1129 self.struct_note(msg).emit()
1130 }
1131
1132 #[track_caller]
1133 pub fn struct_span_note(
1134 self,
1135 span: impl Into<MultiSpan>,
1136 msg: impl Into<DiagMessage>,
1137 ) -> Diag<'a> {
1138 self.struct_note(msg).with_span(span)
1139 }
1140
1141 #[track_caller]
1142 pub fn span_note(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
1143 self.struct_span_note(span, msg).emit()
1144 }
1145
1146 #[track_caller]
1147 pub fn create_note(self, note: impl Diagnostic<'a>) -> Diag<'a> {
1148 note.into_diag(self, Note)
1149 }
1150
1151 #[track_caller]
1152 pub fn emit_note(self, note: impl Diagnostic<'a>) {
1153 self.create_note(note).emit()
1154 }
1155}
1156
1157impl DiagCtxtInner {
1158 fn new(emitter: Box<DynEmitter>) -> Self {
1159 Self {
1160 flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
1161 err_guars: Vec::new(),
1162 lint_err_guars: Vec::new(),
1163 delayed_bugs: Vec::new(),
1164 deduplicated_err_count: 0,
1165 deduplicated_warn_count: 0,
1166 emitter,
1167 must_produce_diag: None,
1168 has_printed: false,
1169 suppressed_expected_diag: false,
1170 taught_diagnostics: Default::default(),
1171 emitted_diagnostic_codes: Default::default(),
1172 emitted_diagnostics: Default::default(),
1173 emitted_recursion_depth_exceeding_limit: false,
1174 stashed_diagnostics: Default::default(),
1175 future_breakage_diagnostics: Vec::new(),
1176 fulfilled_expectations: Default::default(),
1177 ice_file: None,
1178 msrv: None,
1179 }
1180 }
1181
1182 fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
1184 let mut guar = None;
1185 let has_errors = !self.err_guars.is_empty();
1186 for (_, stashed_diagnostics) in mem::take(&mut self.stashed_diagnostics).into_iter() {
1187 for (_, (diag, _guar, _thread)) in stashed_diagnostics {
1188 if has_errors
1191 && let Warning(emission_override) = diag.level
1192 && !#[allow(non_exhaustive_omitted_patterns)] match emission_override {
Some(EmissionOverride::Forced { .. }) => true,
_ => false,
}matches!(emission_override, Some(EmissionOverride::Forced { .. }))
1193 {
1194 continue;
1195 }
1196 guar = guar.or(self.emit_diagnostic(diag, None));
1197 }
1198 }
1199 guar
1200 }
1201
1202 fn emit_diagnostic(
1204 &mut self,
1205 mut diagnostic: DiagInner,
1206 taint: Option<&Cell<Option<ErrorGuaranteed>>>,
1207 ) -> Option<ErrorGuaranteed> {
1208 if diagnostic.has_future_breakage() {
1209 {
match diagnostic.level {
Error | Warning(_) => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"Error | Warning(_)", ::core::option::Option::None);
}
}
};assert_matches!(diagnostic.level, Error | Warning(_));
1213 self.future_breakage_diagnostics.push(diagnostic.clone());
1214 }
1215
1216 match diagnostic.level {
1220 Bug => {}
1221 Fatal | Error => {
1222 if self.treat_next_err_as_bug() {
1223 diagnostic.level = Bug;
1225 }
1226 }
1227 DelayedBug => {
1228 if self.flags.eagerly_emit_delayed_bugs {
1233 if self.treat_next_err_as_bug() {
1235 diagnostic.level = Bug;
1236 } else {
1237 diagnostic.level = Error;
1238 }
1239 } else {
1240 return if let Some(guar) = self.has_errors() {
1243 Some(guar)
1244 } else {
1245 let backtrace = std::backtrace::Backtrace::capture();
1249 #[allow(deprecated)]
1253 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1254 self.delayed_bugs
1255 .push((DelayedDiagInner::with_backtrace(diagnostic, backtrace), guar));
1256 Some(guar)
1257 };
1258 }
1259 }
1260 Warning(emission_override) => {
1261 match emission_override {
1262 None => {
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 Some(EmissionOverride::Forced { lint_id: None }) => {}
1273 Some(EmissionOverride::Forced { lint_id: Some(lint_id) }) => {
1274 self.fulfilled_expectations.insert(lint_id);
1275 }
1276 Some(EmissionOverride::Allowed) => {
1277 if !diagnostic.has_future_breakage() {
::core::panicking::panic("assertion failed: diagnostic.has_future_breakage()")
};assert!(diagnostic.has_future_breakage());
1278 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1279 self.suppressed_expected_diag = true;
1280 return None;
1281 }
1282 Some(EmissionOverride::Expected { lint_id }) => {
1283 self.fulfilled_expectations.insert(lint_id);
1284 TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
1285 self.suppressed_expected_diag = true;
1286 return None;
1287 }
1288 }
1289 }
1290 Note | Help | FailureNote => {}
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/4ebd258257737d5b7635c116fa7d281627a7e937/compiler/rustc_errors/src/lib.rs:1321",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/4ebd258257737d5b7635c116fa7d281627a7e937/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/4ebd258257737d5b7635c116fa7d281627a7e937/compiler/rustc_errors/src/lib.rs:1322",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/4ebd258257737d5b7635c116fa7d281627a7e937/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 show_sub = |sub: &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/4ebd258257737d5b7635c116fa7d281627a7e937/compiler/rustc_errors/src/lib.rs:1325",
"rustc_errors", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/4ebd258257737d5b7635c116fa7d281627a7e937/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 true
1329 }
1330 Sublevel::OnceNote | Sublevel::OnceHelp => {
1331 self.emitted_diagnostics.insert(sub.dedup_hash())
1332 }
1333 }
1334 };
1335 diagnostic.children.retain(show_sub);
1336 if already_emitted {
1337 let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
1338 diagnostic.sub(Sublevel::Note, msg, MultiSpan::new());
1339 }
1340
1341 if is_error {
1342 self.deduplicated_err_count += 1;
1343 } else if #[allow(non_exhaustive_omitted_patterns)] match diagnostic.level {
Warning(_) => true,
_ => false,
}matches!(diagnostic.level, Warning(_)) {
1344 self.deduplicated_warn_count += 1;
1345 }
1346 self.has_printed = true;
1347
1348 self.emitter.emit_diagnostic(diagnostic);
1349 }
1350
1351 if is_error {
1352 if !self.delayed_bugs.is_empty() {
1357 {
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);
1358 self.delayed_bugs.clear();
1359 self.delayed_bugs.shrink_to_fit();
1360 }
1361
1362 #[allow(deprecated)]
1365 let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1366 let thread = std::thread::current().id();
1367 if is_lint {
1368 self.lint_err_guars.push((guar, thread));
1369 } else {
1370 if let Some(taint) = taint {
1371 taint.set(Some(guar));
1372 }
1373 self.err_guars.push((guar, thread));
1374 }
1375 self.panic_if_treat_err_as_bug();
1376 Some(guar)
1377 } else {
1378 None
1379 }
1380 })
1381 }
1382
1383 fn treat_err_as_bug(&self) -> bool {
1384 self.flags
1385 .treat_err_as_bug
1386 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() >= c.get())
1387 }
1388
1389 fn treat_next_err_as_bug(&self) -> bool {
1391 self.flags
1392 .treat_err_as_bug
1393 .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() + 1 >= c.get())
1394 }
1395
1396 fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
1397 self.err_guars.get(0).map(|(guar, _)| *guar).or_else(|| {
1398 if let Some((_diag, guar, _)) = self
1399 .stashed_diagnostics
1400 .values()
1401 .flat_map(|stashed_diagnostics| stashed_diagnostics.values())
1402 .find(|(diag, guar, _)| guar.is_some() && diag.is_lint.is_none())
1403 {
1404 *guar
1405 } else {
1406 None
1407 }
1408 })
1409 }
1410
1411 fn has_errors(&self) -> Option<ErrorGuaranteed> {
1412 self.err_guars
1413 .get(0)
1414 .map(|(guar, _)| *guar)
1415 .or_else(|| self.lint_err_guars.get(0).map(|(guar, _)| *guar))
1416 .or_else(|| {
1417 self.stashed_diagnostics.values().find_map(|stashed_diagnostics| {
1418 stashed_diagnostics.values().find_map(|(_, guar, _)| *guar)
1419 })
1420 })
1421 }
1422
1423 fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
1424 self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
1425 }
1426
1427 fn flush_delayed(&mut self) {
1428 if !self.stashed_diagnostics.is_empty() {
::core::panicking::panic("assertion failed: self.stashed_diagnostics.is_empty()")
};assert!(self.stashed_diagnostics.is_empty());
1432
1433 if !self.err_guars.is_empty() {
1434 return;
1436 }
1437
1438 if self.delayed_bugs.is_empty() {
1439 return;
1441 }
1442
1443 let bugs: Vec<_> = mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();
1444
1445 let backtrace = std::env::var_os("RUST_BACKTRACE").as_deref() != Some(OsStr::new("0"));
1446 let decorate = backtrace || self.ice_file.is_none();
1447 let mut out = self
1448 .ice_file
1449 .as_ref()
1450 .and_then(|file| std::fs::File::options().create(true).append(true).open(file).ok());
1451
1452 let note1 = "no errors encountered even though delayed bugs were created";
1457 let note2 = "those delayed bugs will now be shown as internal compiler errors";
1458 self.emit_diagnostic(DiagInner::new(Note, note1), None);
1459 self.emit_diagnostic(DiagInner::new(Note, note2), None);
1460
1461 for bug in bugs {
1462 if let Some(out) = &mut out {
1463 _ = 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!(
1464 out,
1465 "delayed bug: {}\n{}\n",
1466 bug.inner
1467 .messages
1468 .iter()
1469 .filter_map(|(msg, _)| msg.as_str())
1470 .collect::<String>(),
1471 &bug.note
1472 );
1473 }
1474
1475 let mut bug = if decorate { bug.decorate() } else { bug.inner };
1476
1477 if bug.level != DelayedBug {
1479 let msg = rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"))msg!(
1486 "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"
1487 ).arg("level", bug.level).format();
1488 bug.sub(Sublevel::Note, msg, bug.span.primary_span().unwrap().into());
1489 }
1490 bug.level = Bug;
1491
1492 self.emit_diagnostic(bug, None);
1493 }
1494
1495 panic::panic_any(DelayedBugPanic);
1497 }
1498
1499 fn panic_if_treat_err_as_bug(&self) {
1500 if self.treat_err_as_bug() {
1501 let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
1502 {
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());
1503 if n == 1 {
1504 {
::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`");
1505 } else {
1506 {
::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}`");
1507 }
1508 }
1509 }
1510}
1511
1512struct DelayedDiagInner {
1513 inner: DiagInner,
1514 note: Backtrace,
1515}
1516
1517impl DelayedDiagInner {
1518 fn with_backtrace(diagnostic: DiagInner, backtrace: Backtrace) -> Self {
1519 DelayedDiagInner { inner: diagnostic, note: backtrace }
1520 }
1521
1522 fn decorate(self) -> DiagInner {
1523 let mut diag = self.inner;
1527 let msg = match self.note.status() {
1528 BacktraceStatus::Captured => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at}\n {$note}"))msg!(
1529 "delayed at {$emitted_at}
1530 {$note}"
1531 ),
1532 _ => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("delayed at {$emitted_at} - {$note}"))msg!("delayed at {$emitted_at} - {$note}"),
1535 }
1536 .arg("emitted_at", diag.emitted_at.clone())
1537 .arg("note", self.note)
1538 .format();
1539 diag.sub(Sublevel::Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
1540 diag
1541 }
1542}
1543
1544#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for EmissionOverride { }
#[automatically_derived]
impl ::core::clone::Clone for EmissionOverride {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Option<LintExpectationId>>;
let _: ::core::clone::AssertParamIsClone<LintExpectationId>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for EmissionOverride { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for EmissionOverride {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Forced { lint_id: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Forced", "lint_id", &__self_0),
Self::Allowed => ::core::fmt::Formatter::write_str(f, "Allowed"),
Self::Expected { lint_id: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Expected", "lint_id", &__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for EmissionOverride { }
#[automatically_derived]
impl ::core::cmp::PartialEq for EmissionOverride {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other) &&
match (self, other) {
(Self::Forced { lint_id: __self_0 }, Self::Forced {
lint_id: __arg1_0 }) => __self_0 == __arg1_0,
(Self::Expected { lint_id: __self_0 }, Self::Expected {
lint_id: __arg1_0 }) => __self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for EmissionOverride {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Option<LintExpectationId>>;
let _: ::core::cmp::AssertParamIsEq<LintExpectationId>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for EmissionOverride {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state);
match self {
Self::Forced { lint_id: __self_0 } =>
::core::hash::Hash::hash(__self_0, state),
Self::Expected { lint_id: __self_0 } =>
::core::hash::Hash::hash(__self_0, state),
_ => {}
}
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for EmissionOverride {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
EmissionOverride::Forced { lint_id: ref __binding_0 } => {
0usize
}
EmissionOverride::Allowed => { 1usize }
EmissionOverride::Expected { lint_id: ref __binding_0 } => {
2usize
}
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
EmissionOverride::Forced { lint_id: ref __binding_0 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
EmissionOverride::Allowed => {}
EmissionOverride::Expected { lint_id: ref __binding_0 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for EmissionOverride {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => {
EmissionOverride::Forced {
lint_id: ::rustc_serialize::Decodable::decode(__decoder),
}
}
1usize => { EmissionOverride::Allowed }
2usize => {
EmissionOverride::Expected {
lint_id: ::rustc_serialize::Decodable::decode(__decoder),
}
}
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `EmissionOverride`, expected 0..3, actual {0}",
n));
}
}
}
}
};Decodable)]
1561pub enum EmissionOverride {
1562 Forced { lint_id: Option<LintExpectationId> },
1564
1565 Allowed,
1568
1569 Expected { lint_id: LintExpectationId },
1571}
1572
1573#[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) &&
match (self, other) {
(Self::Warning(__self_0), Self::Warning(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Level {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Option<EmissionOverride>>;
}
}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 {
let _: ::core::clone::AssertParamIsClone<Option<EmissionOverride>>;
*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);
match self {
Self::Warning(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
_ => {}
}
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Level {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Bug => ::core::fmt::Formatter::write_str(f, "Bug"),
Self::Fatal => ::core::fmt::Formatter::write_str(f, "Fatal"),
Self::Error => ::core::fmt::Formatter::write_str(f, "Error"),
Self::DelayedBug =>
::core::fmt::Formatter::write_str(f, "DelayedBug"),
Self::Warning(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Warning", &__self_0),
Self::Note => ::core::fmt::Formatter::write_str(f, "Note"),
Self::Help => ::core::fmt::Formatter::write_str(f, "Help"),
Self::FailureNote =>
::core::fmt::Formatter::write_str(f, "FailureNote"),
}
}
}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::Warning(ref __binding_0) => { 4usize }
Level::Note => { 5usize }
Level::Help => { 6usize }
Level::FailureNote => { 7usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
Level::Bug => {}
Level::Fatal => {}
Level::Error => {}
Level::DelayedBug => {}
Level::Warning(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
Level::Note => {}
Level::Help => {}
Level::FailureNote => {}
}
}
}
};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::Warning(::rustc_serialize::Decodable::decode(__decoder))
}
5usize => { Level::Note }
6usize => { Level::Help }
7usize => { Level::FailureNote }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Level`, expected 0..8, actual {0}",
n));
}
}
}
}
};Decodable)]
1585pub enum Level {
1586 Bug,
1588
1589 Fatal,
1592
1593 Error,
1596
1597 DelayedBug,
1602
1603 Warning(Option<EmissionOverride>),
1606
1607 Note,
1609
1610 Help,
1616
1617 FailureNote,
1620}
1621
1622impl fmt::Display for Level {
1623 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1624 self.to_str().fmt(f)
1625 }
1626}
1627
1628impl Level {
1629 pub fn to_str(self) -> &'static str {
1630 match self {
1631 Bug | DelayedBug => "error: internal compiler error",
1632 Fatal | Error => "error",
1633 Warning(_) => "warning",
1634 Note => "note",
1635 Help => "help",
1636 FailureNote => "failure-note",
1637 }
1638 }
1639
1640 pub fn is_failure_note(self) -> bool {
1641 #[allow(non_exhaustive_omitted_patterns)] match self {
FailureNote => true,
_ => false,
}matches!(self, FailureNote)
1642 }
1643}
1644
1645impl IntoDiagArg for Level {
1646 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
1647 DiagArgValue::Str(Cow::from(self.to_string()))
1648 }
1649}
1650
1651#[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)]
1653pub enum Sublevel {
1654 Error,
1659
1660 Warning,
1662
1663 Note,
1665
1666 OnceNote,
1668
1669 Help,
1671
1672 OnceHelp,
1674}
1675
1676impl Sublevel {
1677 pub fn to_str(self) -> &'static str {
1678 match self {
1679 Sublevel::Error => "error",
1680 Sublevel::Warning => "warning",
1681 Sublevel::Note | Sublevel::OnceNote => "note",
1682 Sublevel::Help | Sublevel::OnceHelp => "help",
1683 }
1684 }
1685}
1686
1687#[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)]
1688pub enum Style {
1689 NoStyle,
1690 Highlight,
1691}
1692
1693pub fn elided_lifetime_in_path_suggestion(
1695 source_map: &SourceMap,
1696 n: usize,
1697 path_span: Span,
1698 incl_angl_brckt: bool,
1699 insertion_span: Span,
1700) -> ElidedLifetimeInPathSubdiag {
1701 let expected = ExpectedLifetimeParameter { span: path_span, count: n };
1702 let indicate = source_map.is_span_accessible(insertion_span).then(|| {
1704 let anon_lts = ::alloc::vec::from_elem("'_", n)vec!["'_"; n].join(", ");
1705 let suggestion =
1706 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}, ") };
1707
1708 IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }
1709 });
1710
1711 ElidedLifetimeInPathSubdiag { expected, indicate }
1712}
1713
1714pub fn a_or_an(s: &str) -> &'static str {
1718 let mut chars = s.chars();
1719 let Some(mut first_alpha_char) = chars.next() else {
1720 return "a";
1721 };
1722 if first_alpha_char == '`' {
1723 let Some(next) = chars.next() else {
1724 return "a";
1725 };
1726 first_alpha_char = next;
1727 }
1728 if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) {
1729 "an"
1730 } else {
1731 "a"
1732 }
1733}
1734
1735#[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)]
1736pub enum TerminalUrl {
1737 No,
1738 Yes,
1739 Auto,
1740}