1use std::borrow::Cow;
2use std::fmt::{self, Debug};
3use std::hash::{Hash, Hasher};
4use std::marker::PhantomData;
5use std::ops::{Deref, DerefMut};
6use std::panic;
7use std::path::PathBuf;
8use std::thread::panicking;
9
10use rustc_data_structures::fx::FxIndexMap;
11use rustc_error_messages::{DiagArgName, DiagArgValue, IntoDiagArg};
12use rustc_lint_defs::{Applicability, LintExpectationId};
13use rustc_macros::{Decodable, Encodable};
14use rustc_span::source_map::Spanned;
15use rustc_span::{DUMMY_SP, Span, Symbol};
16use tracing::debug;
17
18use crate::{
19 CodeSuggestion, DiagCtxtHandle, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level,
20 MultiSpan, StashKey, Style, Substitution, SubstitutionPart, SuggestionStyle, Suggestions,
21};
22
23pub type DiagArgMap = FxIndexMap<DiagArgName, DiagArgValue>;
24
25pub trait EmissionGuarantee: Sized {
28 type EmitResult = Self;
31
32 #[track_caller]
36 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult;
37}
38
39impl EmissionGuarantee for ErrorGuaranteed {
40 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
41 diag.emit_producing_error_guaranteed()
42 }
43}
44
45impl EmissionGuarantee for () {
46 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
47 diag.emit_producing_nothing();
48 }
49}
50
51#[derive(#[automatically_derived]
impl ::core::marker::Copy for BugAbort { }Copy, #[automatically_derived]
impl ::core::clone::Clone for BugAbort {
#[inline]
fn clone(&self) -> BugAbort { *self }
}Clone)]
54pub struct BugAbort;
55
56impl EmissionGuarantee for BugAbort {
57 type EmitResult = !;
58
59 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
60 diag.emit_producing_nothing();
61 panic::panic_any(ExplicitBug);
62 }
63}
64
65#[derive(#[automatically_derived]
impl ::core::marker::Copy for FatalAbort { }Copy, #[automatically_derived]
impl ::core::clone::Clone for FatalAbort {
#[inline]
fn clone(&self) -> FatalAbort { *self }
}Clone)]
68pub struct FatalAbort;
69
70impl EmissionGuarantee for FatalAbort {
71 type EmitResult = !;
72
73 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
74 diag.emit_producing_nothing();
75 crate::FatalError.raise()
76 }
77}
78
79impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
80 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
81 diag.emit_producing_nothing();
82 rustc_span::fatal_error::FatalError
83 }
84}
85
86#[rustc_diagnostic_item = "Diagnostic"]
108pub trait Diagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> {
109 #[must_use]
111 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G>;
112}
113
114impl<'a, T, G> Diagnostic<'a, G> for Spanned<T>
115where
116 T: Diagnostic<'a, G>,
117 G: EmissionGuarantee,
118{
119 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
120 self.node.into_diag(dcx, level).with_span(self.span)
121 }
122}
123
124#[rustc_diagnostic_item = "Subdiagnostic"]
127pub trait Subdiagnostic
128where
129 Self: Sized,
130{
131 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
133}
134
135#[rustc_diagnostic_item = "LintDiagnostic"]
138pub trait LintDiagnostic<'a, G: EmissionGuarantee> {
139 fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>);
141}
142
143pub trait LintDiagnosticBox<'a, G: EmissionGuarantee> {
144 fn decorate_lint_box<'b>(self: Box<Self>, diag: &'b mut Diag<'a, G>);
145}
146
147impl<'a, G: EmissionGuarantee, D: LintDiagnostic<'a, G>> LintDiagnosticBox<'a, G> for D {
148 fn decorate_lint_box<'b>(self: Box<Self>, diag: &'b mut Diag<'a, G>) {
149 self.decorate_lint(diag);
150 }
151}
152
153#[derive(#[automatically_derived]
impl ::core::clone::Clone for DiagLocation {
#[inline]
fn clone(&self) -> DiagLocation {
DiagLocation {
file: ::core::clone::Clone::clone(&self.file),
line: ::core::clone::Clone::clone(&self.line),
col: ::core::clone::Clone::clone(&self.col),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for DiagLocation {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "DiagLocation",
"file", &self.file, "line", &self.line, "col", &&self.col)
}
}Debug, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for DiagLocation {
fn encode(&self, __encoder: &mut __E) {
match *self {
DiagLocation {
file: ref __binding_0,
line: ref __binding_1,
col: ref __binding_2 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_2,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for DiagLocation {
fn decode(__decoder: &mut __D) -> Self {
DiagLocation {
file: ::rustc_serialize::Decodable::decode(__decoder),
line: ::rustc_serialize::Decodable::decode(__decoder),
col: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
154pub(crate) struct DiagLocation {
155 file: Cow<'static, str>,
156 line: u32,
157 col: u32,
158}
159
160impl DiagLocation {
161 #[track_caller]
162 fn caller() -> Self {
163 let loc = panic::Location::caller();
164 DiagLocation { file: loc.file().into(), line: loc.line(), col: loc.column() }
165 }
166}
167
168impl fmt::Display for DiagLocation {
169 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170 f.write_fmt(format_args!("{0}:{1}:{2}", self.file, self.line, self.col))write!(f, "{}:{}:{}", self.file, self.line, self.col)
171 }
172}
173
174#[derive(#[automatically_derived]
impl ::core::clone::Clone for IsLint {
#[inline]
fn clone(&self) -> IsLint {
IsLint {
name: ::core::clone::Clone::clone(&self.name),
has_future_breakage: ::core::clone::Clone::clone(&self.has_future_breakage),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for IsLint {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "IsLint",
"name", &self.name, "has_future_breakage",
&&self.has_future_breakage)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for IsLint {
#[inline]
fn eq(&self, other: &IsLint) -> bool {
self.has_future_breakage == other.has_future_breakage &&
self.name == other.name
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for IsLint {
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<bool>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for IsLint {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.name, state);
::core::hash::Hash::hash(&self.has_future_breakage, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for IsLint {
fn encode(&self, __encoder: &mut __E) {
match *self {
IsLint {
name: ref __binding_0, has_future_breakage: ref __binding_1
} => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for IsLint {
fn decode(__decoder: &mut __D) -> Self {
IsLint {
name: ::rustc_serialize::Decodable::decode(__decoder),
has_future_breakage: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
175pub struct IsLint {
176 pub(crate) name: String,
178 has_future_breakage: bool,
180}
181
182#[derive(#[automatically_derived]
impl ::core::fmt::Debug for DiagStyledString {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"DiagStyledString", &&self.0)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for DiagStyledString {
#[inline]
fn eq(&self, other: &DiagStyledString) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DiagStyledString {
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Vec<StringPart>>;
}
}Eq)]
183pub struct DiagStyledString(pub Vec<StringPart>);
184
185impl DiagStyledString {
186 pub fn new() -> DiagStyledString {
187 DiagStyledString(::alloc::vec::Vec::new()vec![])
188 }
189 pub fn push_normal<S: Into<String>>(&mut self, t: S) {
190 self.0.push(StringPart::normal(t));
191 }
192 pub fn push_highlighted<S: Into<String>>(&mut self, t: S) {
193 self.0.push(StringPart::highlighted(t));
194 }
195 pub fn push<S: Into<String>>(&mut self, t: S, highlight: bool) {
196 if highlight {
197 self.push_highlighted(t);
198 } else {
199 self.push_normal(t);
200 }
201 }
202 pub fn normal<S: Into<String>>(t: S) -> DiagStyledString {
203 DiagStyledString(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[StringPart::normal(t)]))vec![StringPart::normal(t)])
204 }
205
206 pub fn highlighted<S: Into<String>>(t: S) -> DiagStyledString {
207 DiagStyledString(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[StringPart::highlighted(t)]))vec![StringPart::highlighted(t)])
208 }
209
210 pub fn content(&self) -> String {
211 self.0.iter().map(|x| x.content.as_str()).collect::<String>()
212 }
213}
214
215#[derive(#[automatically_derived]
impl ::core::fmt::Debug for StringPart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "StringPart",
"content", &self.content, "style", &&self.style)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for StringPart {
#[inline]
fn eq(&self, other: &StringPart) -> bool {
self.content == other.content && self.style == other.style
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for StringPart {
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<Style>;
}
}Eq)]
216pub struct StringPart {
217 content: String,
218 style: Style,
219}
220
221impl StringPart {
222 pub fn normal<S: Into<String>>(content: S) -> StringPart {
223 StringPart { content: content.into(), style: Style::NoStyle }
224 }
225
226 pub fn highlighted<S: Into<String>>(content: S) -> StringPart {
227 StringPart { content: content.into(), style: Style::Highlight }
228 }
229}
230
231#[must_use]
236#[derive(#[automatically_derived]
impl ::core::clone::Clone for DiagInner {
#[inline]
fn clone(&self) -> DiagInner {
DiagInner {
level: ::core::clone::Clone::clone(&self.level),
messages: ::core::clone::Clone::clone(&self.messages),
code: ::core::clone::Clone::clone(&self.code),
lint_id: ::core::clone::Clone::clone(&self.lint_id),
span: ::core::clone::Clone::clone(&self.span),
children: ::core::clone::Clone::clone(&self.children),
suggestions: ::core::clone::Clone::clone(&self.suggestions),
args: ::core::clone::Clone::clone(&self.args),
reserved_args: ::core::clone::Clone::clone(&self.reserved_args),
sort_span: ::core::clone::Clone::clone(&self.sort_span),
is_lint: ::core::clone::Clone::clone(&self.is_lint),
long_ty_path: ::core::clone::Clone::clone(&self.long_ty_path),
emitted_at: ::core::clone::Clone::clone(&self.emitted_at),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for DiagInner {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["level", "messages", "code", "lint_id", "span", "children",
"suggestions", "args", "reserved_args", "sort_span",
"is_lint", "long_ty_path", "emitted_at"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.level, &self.messages, &self.code, &self.lint_id,
&self.span, &self.children, &self.suggestions, &self.args,
&self.reserved_args, &self.sort_span, &self.is_lint,
&self.long_ty_path, &&self.emitted_at];
::core::fmt::Formatter::debug_struct_fields_finish(f, "DiagInner",
names, values)
}
}Debug, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for DiagInner {
fn encode(&self, __encoder: &mut __E) {
match *self {
DiagInner {
level: ref __binding_0,
messages: ref __binding_1,
code: ref __binding_2,
lint_id: ref __binding_3,
span: ref __binding_4,
children: ref __binding_5,
suggestions: ref __binding_6,
args: ref __binding_7,
reserved_args: ref __binding_8,
sort_span: ref __binding_9,
is_lint: ref __binding_10,
long_ty_path: ref __binding_11,
emitted_at: ref __binding_12 } => {
::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);
::rustc_serialize::Encodable::<__E>::encode(__binding_4,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_5,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_6,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_7,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_8,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_9,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_10,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_11,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_12,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for DiagInner {
fn decode(__decoder: &mut __D) -> Self {
DiagInner {
level: ::rustc_serialize::Decodable::decode(__decoder),
messages: ::rustc_serialize::Decodable::decode(__decoder),
code: ::rustc_serialize::Decodable::decode(__decoder),
lint_id: ::rustc_serialize::Decodable::decode(__decoder),
span: ::rustc_serialize::Decodable::decode(__decoder),
children: ::rustc_serialize::Decodable::decode(__decoder),
suggestions: ::rustc_serialize::Decodable::decode(__decoder),
args: ::rustc_serialize::Decodable::decode(__decoder),
reserved_args: ::rustc_serialize::Decodable::decode(__decoder),
sort_span: ::rustc_serialize::Decodable::decode(__decoder),
is_lint: ::rustc_serialize::Decodable::decode(__decoder),
long_ty_path: ::rustc_serialize::Decodable::decode(__decoder),
emitted_at: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
237pub struct DiagInner {
238 pub(crate) level: Level,
241
242 pub messages: Vec<(DiagMessage, Style)>,
243 pub code: Option<ErrCode>,
244 pub lint_id: Option<LintExpectationId>,
245 pub span: MultiSpan,
246 pub children: Vec<Subdiag>,
247 pub suggestions: Suggestions,
248 pub args: DiagArgMap,
249
250 pub reserved_args: DiagArgMap,
252
253 pub sort_span: Span,
257
258 pub is_lint: Option<IsLint>,
259
260 pub long_ty_path: Option<PathBuf>,
261 pub(crate) emitted_at: DiagLocation,
264}
265
266impl DiagInner {
267 #[track_caller]
268 pub fn new<M: Into<DiagMessage>>(level: Level, message: M) -> Self {
269 DiagInner::new_with_messages(level, ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(message.into(), Style::NoStyle)]))vec![(message.into(), Style::NoStyle)])
270 }
271
272 #[track_caller]
273 pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self {
274 DiagInner {
275 level,
276 lint_id: None,
277 messages,
278 code: None,
279 span: MultiSpan::new(),
280 children: ::alloc::vec::Vec::new()vec![],
281 suggestions: Suggestions::Enabled(::alloc::vec::Vec::new()vec![]),
282 args: Default::default(),
283 reserved_args: Default::default(),
284 sort_span: DUMMY_SP,
285 is_lint: None,
286 long_ty_path: None,
287 emitted_at: DiagLocation::caller(),
288 }
289 }
290
291 #[inline(always)]
292 pub fn level(&self) -> Level {
293 self.level
294 }
295
296 pub fn is_error(&self) -> bool {
297 match self.level {
298 Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true,
299
300 Level::ForceWarning
301 | Level::Warning
302 | Level::Note
303 | Level::OnceNote
304 | Level::Help
305 | Level::OnceHelp
306 | Level::FailureNote
307 | Level::Allow
308 | Level::Expect => false,
309 }
310 }
311
312 pub(crate) fn has_future_breakage(&self) -> bool {
314 #[allow(non_exhaustive_omitted_patterns)] match self.is_lint {
Some(IsLint { has_future_breakage: true, .. }) => true,
_ => false,
}matches!(self.is_lint, Some(IsLint { has_future_breakage: true, .. }))
315 }
316
317 pub(crate) fn is_force_warn(&self) -> bool {
318 match self.level {
319 Level::ForceWarning => {
320 if !self.is_lint.is_some() {
::core::panicking::panic("assertion failed: self.is_lint.is_some()")
};assert!(self.is_lint.is_some());
321 true
322 }
323 _ => false,
324 }
325 }
326
327 pub(crate) fn sub(&mut self, level: Level, message: impl Into<DiagMessage>, span: MultiSpan) {
328 let sub = Subdiag { level, messages: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(message.into(), Style::NoStyle)]))vec![(message.into(), Style::NoStyle)], span };
329 self.children.push(sub);
330 }
331
332 pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) {
333 let name = name.into();
334 let value = arg.into_diag_arg(&mut self.long_ty_path);
335 if true {
if !(!self.args.contains_key(&name) ||
self.args.get(&name) == Some(&value)) {
{
::core::panicking::panic_fmt(format_args!("arg {0} already exists",
name));
}
};
};debug_assert!(
337 !self.args.contains_key(&name) || self.args.get(&name) == Some(&value),
338 "arg {} already exists",
339 name
340 );
341 self.args.insert(name, value);
342 }
343
344 pub fn remove_arg(&mut self, name: &str) {
345 self.args.swap_remove(name);
346 }
347
348 pub fn store_args(&mut self) {
349 self.reserved_args = self.args.clone();
350 }
351
352 pub fn restore_args(&mut self) {
353 self.args = std::mem::take(&mut self.reserved_args);
354 }
355
356 pub fn emitted_at_sub_diag(&self) -> Subdiag {
357 let track = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-Ztrack-diagnostics: created at {0}",
self.emitted_at))
})format!("-Ztrack-diagnostics: created at {}", self.emitted_at);
358 Subdiag {
359 level: crate::Level::Note,
360 messages: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(DiagMessage::Str(Cow::Owned(track)), Style::NoStyle)]))vec![(DiagMessage::Str(Cow::Owned(track)), Style::NoStyle)],
361 span: MultiSpan::new(),
362 }
363 }
364
365 fn keys(
367 &self,
368 ) -> (
369 &Level,
370 &[(DiagMessage, Style)],
371 &Option<ErrCode>,
372 &MultiSpan,
373 &[Subdiag],
374 &Suggestions,
375 Vec<(&DiagArgName, &DiagArgValue)>,
376 &Option<IsLint>,
377 ) {
378 (
379 &self.level,
380 &self.messages,
381 &self.code,
382 &self.span,
383 &self.children,
384 &self.suggestions,
385 self.args.iter().collect(),
386 &self.is_lint,
388 )
390 }
391}
392
393impl Hash for DiagInner {
394 fn hash<H>(&self, state: &mut H)
395 where
396 H: Hasher,
397 {
398 self.keys().hash(state);
399 }
400}
401
402impl PartialEq for DiagInner {
403 fn eq(&self, other: &Self) -> bool {
404 self.keys() == other.keys()
405 }
406}
407
408#[derive(#[automatically_derived]
impl ::core::clone::Clone for Subdiag {
#[inline]
fn clone(&self) -> Subdiag {
Subdiag {
level: ::core::clone::Clone::clone(&self.level),
messages: ::core::clone::Clone::clone(&self.messages),
span: ::core::clone::Clone::clone(&self.span),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Subdiag {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "Subdiag",
"level", &self.level, "messages", &self.messages, "span",
&&self.span)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Subdiag {
#[inline]
fn eq(&self, other: &Subdiag) -> bool {
self.level == other.level && self.messages == other.messages &&
self.span == other.span
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for Subdiag {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.level, state);
::core::hash::Hash::hash(&self.messages, state);
::core::hash::Hash::hash(&self.span, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for Subdiag {
fn encode(&self, __encoder: &mut __E) {
match *self {
Subdiag {
level: ref __binding_0,
messages: ref __binding_1,
span: ref __binding_2 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_2,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for Subdiag {
fn decode(__decoder: &mut __D) -> Self {
Subdiag {
level: ::rustc_serialize::Decodable::decode(__decoder),
messages: ::rustc_serialize::Decodable::decode(__decoder),
span: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
411pub struct Subdiag {
412 pub level: Level,
413 pub messages: Vec<(DiagMessage, Style)>,
414 pub span: MultiSpan,
415}
416
417#[must_use]
430pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> {
431 pub dcx: DiagCtxtHandle<'a>,
432
433 diag: Option<Box<DiagInner>>,
443
444 _marker: PhantomData<G>,
445}
446
447impl<G> !Clone for Diag<'_, G> {}
450
451const _: [(); 3 * size_of::<usize>()] =
[(); ::std::mem::size_of::<Diag<'_, ()>>()];rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * size_of::<usize>());
452
453impl<G: EmissionGuarantee> Deref for Diag<'_, G> {
454 type Target = DiagInner;
455
456 fn deref(&self) -> &DiagInner {
457 self.diag.as_ref().unwrap()
458 }
459}
460
461impl<G: EmissionGuarantee> DerefMut for Diag<'_, G> {
462 fn deref_mut(&mut self) -> &mut DiagInner {
463 self.diag.as_mut().unwrap()
464 }
465}
466
467impl<G: EmissionGuarantee> Debug for Diag<'_, G> {
468 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
469 self.diag.fmt(f)
470 }
471}
472
473macro_rules! with_fn {
492 {
493 $with_f:ident,
494 $(#[$attrs:meta])*
495 pub fn $f:ident(&mut $self:ident, $($name:ident: $ty:ty),* $(,)?) -> &mut Self {
496 $($body:tt)*
497 }
498 } => {
499 $(#[$attrs])*
501 #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
502 pub fn $f(&mut $self, $($name: $ty),*) -> &mut Self {
503 $($body)*
504 }
505
506 $(#[$attrs])*
508 #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
509 pub fn $with_f(mut $self, $($name: $ty),*) -> Self {
510 $self.$f($($name),*);
511 $self
512 }
513 };
514}
515
516impl<'a, G: EmissionGuarantee> Diag<'a, G> {
517 #[track_caller]
518 pub fn new(dcx: DiagCtxtHandle<'a>, level: Level, message: impl Into<DiagMessage>) -> Self {
519 Self::new_diagnostic(dcx, DiagInner::new(level, message))
520 }
521
522 pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_, G> {
524 Diag { dcx, diag: self.diag.take(), _marker: PhantomData }
525 }
526
527 #[track_caller]
529 pub(crate) fn new_diagnostic(dcx: DiagCtxtHandle<'a>, diag: DiagInner) -> Self {
530 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/diagnostic.rs:530",
"rustc_errors::diagnostic", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/diagnostic.rs"),
::tracing_core::__macro_support::Option::Some(530u32),
::tracing_core::__macro_support::Option::Some("rustc_errors::diagnostic"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("Created new diagnostic")
as &dyn Value))])
});
} else { ; }
};debug!("Created new diagnostic");
531 Self { dcx, diag: Some(Box::new(diag)), _marker: PhantomData }
532 }
533
534 #[track_caller]
545 pub fn downgrade_to_delayed_bug(&mut self) {
546 if !#[allow(non_exhaustive_omitted_patterns)] match self.level {
Level::Error | Level::DelayedBug => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("downgrade_to_delayed_bug: cannot downgrade {0:?} to DelayedBug: not an error",
self.level));
}
};assert!(
547 matches!(self.level, Level::Error | Level::DelayedBug),
548 "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
549 self.level
550 );
551 self.level = Level::DelayedBug;
552 }
553
554 #[track_caller]
562 pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> {
563 if !#[allow(non_exhaustive_omitted_patterns)] match self.level {
Level::Error => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("upgrade_to_fatal: cannot upgrade {0:?} to Fatal: not an error",
self.level));
}
};assert!(
564 matches!(self.level, Level::Error),
565 "upgrade_to_fatal: cannot upgrade {:?} to Fatal: not an error",
566 self.level
567 );
568 self.level = Level::Fatal;
569
570 let diag = self.diag.take();
573 Diag { dcx: self.dcx, diag, _marker: PhantomData }
574 }
575
576 "See [`Diag::span_label()`]."
&mut Self
self
span
label
&mut Self
"See [`Diag::span_label()`]."
mut self
span
label
Self
self.span_label(span, label);
self;with_fn! { with_span_label,
577 pub fn span_label(&mut self, span: Span, label: impl Into<DiagMessage>) -> &mut Self {
590 self.span.push_span_label(span, label.into());
591 self
592 } }
593
594 "See [`Diag::span_labels()`]."
&mut Self
self
spans
label
&mut Self
"See [`Diag::span_labels()`]."
mut self
spans
label
Self
self.span_labels(spans, label);
self;with_fn! { with_span_labels,
595 pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
598 for span in spans {
599 self.span_label(span, label.to_string());
600 }
601 self
602 } }
603
604 pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self {
605 let before = self.span.clone();
606 self.span(after);
607 for span_label in before.span_labels() {
608 if let Some(label) = span_label.label {
609 if span_label.is_primary && keep_label {
610 self.span.push_span_label(after, label);
611 } else {
612 self.span.push_span_label(span_label.span, label);
613 }
614 }
615 }
616 self
617 }
618
619 pub fn note_expected_found(
620 &mut self,
621 expected_label: &str,
622 expected: DiagStyledString,
623 found_label: &str,
624 found: DiagStyledString,
625 ) -> &mut Self {
626 self.note_expected_found_extra(
627 expected_label,
628 expected,
629 found_label,
630 found,
631 DiagStyledString::normal(""),
632 DiagStyledString::normal(""),
633 )
634 }
635
636 pub fn note_expected_found_extra(
637 &mut self,
638 expected_label: &str,
639 expected: DiagStyledString,
640 found_label: &str,
641 found: DiagStyledString,
642 expected_extra: DiagStyledString,
643 found_extra: DiagStyledString,
644 ) -> &mut Self {
645 let expected_label = expected_label.to_string();
646 let expected_label = if expected_label.is_empty() {
647 "expected".to_string()
648 } else {
649 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected {0}", expected_label))
})format!("expected {expected_label}")
650 };
651 let found_label = found_label.to_string();
652 let found_label = if found_label.is_empty() {
653 "found".to_string()
654 } else {
655 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("found {0}", found_label))
})format!("found {found_label}")
656 };
657 let (found_padding, expected_padding) = if expected_label.len() > found_label.len() {
658 (expected_label.len() - found_label.len(), 0)
659 } else {
660 (0, found_label.len() - expected_label.len())
661 };
662 let mut msg = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[StringPart::normal(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1} `",
" ".repeat(expected_padding), expected_label))
}))]))vec![StringPart::normal(format!(
663 "{}{} `",
664 " ".repeat(expected_padding),
665 expected_label
666 ))];
667 msg.extend(expected.0);
668 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
669 msg.extend(expected_extra.0);
670 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("\n")) })format!("\n")));
671 msg.push(StringPart::normal(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1} `",
" ".repeat(found_padding), found_label))
})format!("{}{} `", " ".repeat(found_padding), found_label)));
672 msg.extend(found.0);
673 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
674 msg.extend(found_extra.0);
675
676 self.highlighted_note(msg);
678 self
679 }
680
681 pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
682 self.highlighted_note(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[StringPart::normal(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` from trait: `",
name))
})), StringPart::highlighted(signature),
StringPart::normal("`")]))vec![
683 StringPart::normal(format!("`{name}` from trait: `")),
684 StringPart::highlighted(signature),
685 StringPart::normal("`"),
686 ]);
687 self
688 }
689
690 "See [`Diag::note()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::note()`]."
mut self
msg
Self
self.note(msg);
self;with_fn! { with_note,
691 pub fn note(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
693 self.sub(Level::Note, msg, MultiSpan::new());
694 self
695 } }
696
697 pub fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self {
698 self.sub_with_highlights(Level::Note, msg, MultiSpan::new());
699 self
700 }
701
702 pub fn highlighted_span_note(
703 &mut self,
704 span: impl Into<MultiSpan>,
705 msg: Vec<StringPart>,
706 ) -> &mut Self {
707 self.sub_with_highlights(Level::Note, msg, span.into());
708 self
709 }
710
711 pub fn note_once(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
713 self.sub(Level::OnceNote, msg, MultiSpan::new());
714 self
715 }
716
717 "See [`Diag::span_note()`]."
&mut Self
self
sp
msg
&mut Self
"See [`Diag::span_note()`]."
mut self
sp
msg
Self
self.span_note(sp, msg);
self;with_fn! { with_span_note,
718 pub fn span_note(
721 &mut self,
722 sp: impl Into<MultiSpan>,
723 msg: impl Into<DiagMessage>,
724 ) -> &mut Self {
725 self.sub(Level::Note, msg, sp.into());
726 self
727 } }
728
729 pub fn span_note_once<S: Into<MultiSpan>>(
732 &mut self,
733 sp: S,
734 msg: impl Into<DiagMessage>,
735 ) -> &mut Self {
736 self.sub(Level::OnceNote, msg, sp.into());
737 self
738 }
739
740 "See [`Diag::warn()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::warn()`]."
mut self
msg
Self
self.warn(msg);
self;with_fn! { with_warn,
741 pub fn warn(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
743 self.sub(Level::Warning, msg, MultiSpan::new());
744 self
745 } }
746
747 pub fn span_warn<S: Into<MultiSpan>>(
750 &mut self,
751 sp: S,
752 msg: impl Into<DiagMessage>,
753 ) -> &mut Self {
754 self.sub(Level::Warning, msg, sp.into());
755 self
756 }
757
758 "See [`Diag::help()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::help()`]."
mut self
msg
Self
self.help(msg);
self;with_fn! { with_help,
759 pub fn help(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
761 self.sub(Level::Help, msg, MultiSpan::new());
762 self
763 } }
764
765 pub fn help_once(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
767 self.sub(Level::OnceHelp, msg, MultiSpan::new());
768 self
769 }
770
771 pub fn highlighted_help(&mut self, msg: Vec<StringPart>) -> &mut Self {
773 self.sub_with_highlights(Level::Help, msg, MultiSpan::new());
774 self
775 }
776
777 pub fn highlighted_span_help(
779 &mut self,
780 span: impl Into<MultiSpan>,
781 msg: Vec<StringPart>,
782 ) -> &mut Self {
783 self.sub_with_highlights(Level::Help, msg, span.into());
784 self
785 }
786
787 "See [`Diag::span_help()`]."
&mut Self
self
sp
msg
&mut Self
"See [`Diag::span_help()`]."
mut self
sp
msg
Self
self.span_help(sp, msg);
self;with_fn! { with_span_help,
788 pub fn span_help(
791 &mut self,
792 sp: impl Into<MultiSpan>,
793 msg: impl Into<DiagMessage>,
794 ) -> &mut Self {
795 self.sub(Level::Help, msg, sp.into());
796 self
797 } }
798
799 pub fn disable_suggestions(&mut self) -> &mut Self {
803 self.suggestions = Suggestions::Disabled;
804 self
805 }
806
807 pub fn seal_suggestions(&mut self) -> &mut Self {
812 if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
813 let suggestions_slice = std::mem::take(suggestions).into_boxed_slice();
814 self.suggestions = Suggestions::Sealed(suggestions_slice);
815 }
816 self
817 }
818
819 fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
824 for subst in &suggestion.substitutions {
825 for part in &subst.parts {
826 let span = part.span;
827 let call_site = span.ctxt().outer_expn_data().call_site;
828 if span.in_derive_expansion() && span.overlaps_or_adjacent(call_site) {
829 return;
831 }
832 }
833 }
834
835 if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
836 suggestions.push(suggestion);
837 }
838 }
839
840 "See [`Diag::multipart_suggestion()`]."
&mut Self
self
msg
suggestion
applicability
&mut Self
"See [`Diag::multipart_suggestion()`]."
mut self
msg
suggestion
applicability
Self
self.multipart_suggestion(msg, suggestion, applicability);
self;with_fn! { with_multipart_suggestion,
841 pub fn multipart_suggestion(
844 &mut self,
845 msg: impl Into<DiagMessage>,
846 suggestion: Vec<(Span, String)>,
847 applicability: Applicability,
848 ) -> &mut Self {
849 self.multipart_suggestion_with_style(
850 msg,
851 suggestion,
852 applicability,
853 SuggestionStyle::ShowAlways,
854 )
855 } }
856
857 pub fn multipart_suggestion_with_style(
859 &mut self,
860 msg: impl Into<DiagMessage>,
861 mut suggestion: Vec<(Span, String)>,
862 applicability: Applicability,
863 style: SuggestionStyle,
864 ) -> &mut Self {
865 let mut seen = crate::FxHashSet::default();
866 suggestion.retain(|(span, msg)| seen.insert((span.lo(), span.hi(), msg.clone())));
867
868 let parts = suggestion
869 .into_iter()
870 .map(|(span, snippet)| SubstitutionPart { snippet, span })
871 .collect::<Vec<_>>();
872
873 if !!parts.is_empty() {
::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
874 if true {
match (&parts.iter().find(|part|
part.span.is_empty() && part.snippet.is_empty()), &None) {
(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::Some(format_args!("Span must not be empty and have no suggestion")));
}
}
};
};debug_assert_eq!(
875 parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
876 None,
877 "Span must not be empty and have no suggestion",
878 );
879 if true {
match (&parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
&None) {
(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::Some(format_args!("suggestion must not have overlapping parts")));
}
}
};
};debug_assert_eq!(
880 parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
881 None,
882 "suggestion must not have overlapping parts",
883 );
884
885 self.push_suggestion(CodeSuggestion {
886 substitutions: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Substitution { parts }]))vec![Substitution { parts }],
887 msg: msg.into(),
888 style,
889 applicability,
890 });
891 self
892 }
893
894 pub fn tool_only_multipart_suggestion(
901 &mut self,
902 msg: impl Into<DiagMessage>,
903 suggestion: Vec<(Span, String)>,
904 applicability: Applicability,
905 ) -> &mut Self {
906 self.multipart_suggestion_with_style(
907 msg,
908 suggestion,
909 applicability,
910 SuggestionStyle::CompletelyHidden,
911 )
912 }
913
914 "See [`Diag::span_suggestion()`]."
&mut Self
self
sp
msg
suggestion
applicability
&mut Self
"See [`Diag::span_suggestion()`]."
mut self
sp
msg
suggestion
applicability
Self
self.span_suggestion(sp, msg, suggestion, applicability);
self;with_fn! { with_span_suggestion,
915 pub fn span_suggestion(
933 &mut self,
934 sp: Span,
935 msg: impl Into<DiagMessage>,
936 suggestion: impl ToString,
937 applicability: Applicability,
938 ) -> &mut Self {
939 self.span_suggestion_with_style(
940 sp,
941 msg,
942 suggestion,
943 applicability,
944 SuggestionStyle::ShowCode,
945 );
946 self
947 } }
948
949 pub fn span_suggestion_with_style(
951 &mut self,
952 sp: Span,
953 msg: impl Into<DiagMessage>,
954 suggestion: impl ToString,
955 applicability: Applicability,
956 style: SuggestionStyle,
957 ) -> &mut Self {
958 if true {
if !!(sp.is_empty() && suggestion.to_string().is_empty()) {
{
::core::panicking::panic_fmt(format_args!("Span must not be empty and have no suggestion"));
}
};
};debug_assert!(
959 !(sp.is_empty() && suggestion.to_string().is_empty()),
960 "Span must not be empty and have no suggestion"
961 );
962 self.push_suggestion(CodeSuggestion {
963 substitutions: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Substitution {
parts: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[SubstitutionPart {
snippet: suggestion.to_string(),
span: sp,
}])),
}]))vec![Substitution {
964 parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
965 }],
966 msg: msg.into(),
967 style,
968 applicability,
969 });
970 self
971 }
972
973 "See [`Diag::span_suggestion_verbose()`]."
&mut Self
self
sp
msg
suggestion
applicability
&mut Self
"See [`Diag::span_suggestion_verbose()`]."
mut self
sp
msg
suggestion
applicability
Self
self.span_suggestion_verbose(sp, msg, suggestion, applicability);
self;with_fn! { with_span_suggestion_verbose,
974 pub fn span_suggestion_verbose(
976 &mut self,
977 sp: Span,
978 msg: impl Into<DiagMessage>,
979 suggestion: impl ToString,
980 applicability: Applicability,
981 ) -> &mut Self {
982 self.span_suggestion_with_style(
983 sp,
984 msg,
985 suggestion,
986 applicability,
987 SuggestionStyle::ShowAlways,
988 );
989 self
990 } }
991
992 "See [`Diag::span_suggestions()`]."
&mut Self
self
sp
msg
suggestions
applicability
&mut Self
"See [`Diag::span_suggestions()`]."
mut self
sp
msg
suggestions
applicability
Self
self.span_suggestions(sp, msg, suggestions, applicability);
self;with_fn! { with_span_suggestions,
993 pub fn span_suggestions(
996 &mut self,
997 sp: Span,
998 msg: impl Into<DiagMessage>,
999 suggestions: impl IntoIterator<Item = String>,
1000 applicability: Applicability,
1001 ) -> &mut Self {
1002 self.span_suggestions_with_style(
1003 sp,
1004 msg,
1005 suggestions,
1006 applicability,
1007 SuggestionStyle::ShowCode,
1008 )
1009 } }
1010
1011 pub fn span_suggestions_with_style(
1012 &mut self,
1013 sp: Span,
1014 msg: impl Into<DiagMessage>,
1015 suggestions: impl IntoIterator<Item = String>,
1016 applicability: Applicability,
1017 style: SuggestionStyle,
1018 ) -> &mut Self {
1019 let substitutions = suggestions
1020 .into_iter()
1021 .map(|snippet| {
1022 if true {
if !!(sp.is_empty() && snippet.is_empty()) {
{
::core::panicking::panic_fmt(format_args!("Span `{0:?}` must not be empty and have no suggestion",
sp));
}
};
};debug_assert!(
1023 !(sp.is_empty() && snippet.is_empty()),
1024 "Span `{sp:?}` must not be empty and have no suggestion"
1025 );
1026 Substitution { parts: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[SubstitutionPart { snippet, span: sp }]))vec![SubstitutionPart { snippet, span: sp }] }
1027 })
1028 .collect();
1029 self.push_suggestion(CodeSuggestion {
1030 substitutions,
1031 msg: msg.into(),
1032 style,
1033 applicability,
1034 });
1035 self
1036 }
1037
1038 pub fn multipart_suggestions(
1042 &mut self,
1043 msg: impl Into<DiagMessage>,
1044 suggestions: impl IntoIterator<Item = Vec<(Span, String)>>,
1045 applicability: Applicability,
1046 ) -> &mut Self {
1047 let substitutions = suggestions
1048 .into_iter()
1049 .map(|sugg| {
1050 let mut parts = sugg
1051 .into_iter()
1052 .map(|(span, snippet)| SubstitutionPart { snippet, span })
1053 .collect::<Vec<_>>();
1054
1055 parts.sort_unstable_by_key(|part| part.span);
1056
1057 if !!parts.is_empty() {
::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
1058 if true {
match (&parts.iter().find(|part|
part.span.is_empty() && part.snippet.is_empty()), &None) {
(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::Some(format_args!("Span must not be empty and have no suggestion")));
}
}
};
};debug_assert_eq!(
1059 parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
1060 None,
1061 "Span must not be empty and have no suggestion",
1062 );
1063 if true {
match (&parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
&None) {
(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::Some(format_args!("suggestion must not have overlapping parts")));
}
}
};
};debug_assert_eq!(
1064 parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
1065 None,
1066 "suggestion must not have overlapping parts",
1067 );
1068
1069 Substitution { parts }
1070 })
1071 .collect();
1072
1073 self.push_suggestion(CodeSuggestion {
1074 substitutions,
1075 msg: msg.into(),
1076 style: SuggestionStyle::ShowAlways,
1077 applicability,
1078 });
1079 self
1080 }
1081
1082 "See [`Diag::span_suggestion_short()`]."
&mut Self
self
sp
msg
suggestion
applicability
&mut Self
"See [`Diag::span_suggestion_short()`]."
mut self
sp
msg
suggestion
applicability
Self
self.span_suggestion_short(sp, msg, suggestion, applicability);
self;with_fn! { with_span_suggestion_short,
1083 pub fn span_suggestion_short(
1088 &mut self,
1089 sp: Span,
1090 msg: impl Into<DiagMessage>,
1091 suggestion: impl ToString,
1092 applicability: Applicability,
1093 ) -> &mut Self {
1094 self.span_suggestion_with_style(
1095 sp,
1096 msg,
1097 suggestion,
1098 applicability,
1099 SuggestionStyle::HideCodeInline,
1100 );
1101 self
1102 } }
1103
1104 pub fn span_suggestion_hidden(
1111 &mut self,
1112 sp: Span,
1113 msg: impl Into<DiagMessage>,
1114 suggestion: impl ToString,
1115 applicability: Applicability,
1116 ) -> &mut Self {
1117 self.span_suggestion_with_style(
1118 sp,
1119 msg,
1120 suggestion,
1121 applicability,
1122 SuggestionStyle::HideCodeAlways,
1123 );
1124 self
1125 }
1126
1127 "See [`Diag::tool_only_span_suggestion()`]."
&mut Self
self
sp
msg
suggestion
applicability
&mut Self
"See [`Diag::tool_only_span_suggestion()`]."
mut self
sp
msg
suggestion
applicability
Self
self.tool_only_span_suggestion(sp, msg, suggestion, applicability);
self;with_fn! { with_tool_only_span_suggestion,
1128 pub fn tool_only_span_suggestion(
1133 &mut self,
1134 sp: Span,
1135 msg: impl Into<DiagMessage>,
1136 suggestion: impl ToString,
1137 applicability: Applicability,
1138 ) -> &mut Self {
1139 self.span_suggestion_with_style(
1140 sp,
1141 msg,
1142 suggestion,
1143 applicability,
1144 SuggestionStyle::CompletelyHidden,
1145 );
1146 self
1147 } }
1148
1149 pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self {
1154 subdiagnostic.add_to_diag(self);
1155 self
1156 }
1157
1158 pub fn eagerly_translate(&self, msg: impl Into<DiagMessage>) -> DiagMessage {
1164 let args = self.args.iter();
1165 self.dcx.eagerly_translate(msg.into(), args)
1166 }
1167
1168 "See [`Diag::span()`]."
&mut Self
self
sp
&mut Self
"See [`Diag::span()`]."
mut self
sp
Self
self.span(sp);
self;with_fn! { with_span,
1169 pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self {
1171 self.span = sp.into();
1172 if let Some(span) = self.span.primary_span() {
1173 self.sort_span = span;
1174 }
1175 self
1176 } }
1177
1178 pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
1179 self.is_lint = Some(IsLint { name, has_future_breakage });
1180 self
1181 }
1182
1183 "See [`Diag::code()`]."
&mut Self
self
code
&mut Self
"See [`Diag::code()`]."
mut self
code
Self
self.code(code);
self;with_fn! { with_code,
1184 pub fn code(&mut self, code: ErrCode) -> &mut Self {
1186 self.code = Some(code);
1187 self
1188 } }
1189
1190 "See [`Diag::lint_id()`]."
&mut Self
self
id
&mut Self
"See [`Diag::lint_id()`]."
mut self
id
Self
self.lint_id(id);
self;with_fn! { with_lint_id,
1191 pub fn lint_id(
1193 &mut self,
1194 id: LintExpectationId,
1195 ) -> &mut Self {
1196 self.lint_id = Some(id);
1197 self
1198 } }
1199
1200 "See [`Diag::primary_message()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::primary_message()`]."
mut self
msg
Self
self.primary_message(msg);
self;with_fn! { with_primary_message,
1201 pub fn primary_message(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
1203 self.messages[0] = (msg.into(), Style::NoStyle);
1204 self
1205 } }
1206
1207 "See [`Diag::arg()`]."
&mut Self
self
name
arg
&mut Self
"See [`Diag::arg()`]."
mut self
name
arg
Self
self.arg(name, arg);
self;with_fn! { with_arg,
1208 pub fn arg(
1210 &mut self,
1211 name: impl Into<DiagArgName>,
1212 arg: impl IntoDiagArg,
1213 ) -> &mut Self {
1214 self.deref_mut().arg(name, arg);
1215 self
1216 } }
1217
1218 pub fn sub(&mut self, level: Level, message: impl Into<DiagMessage>, span: MultiSpan) {
1223 self.deref_mut().sub(level, message, span);
1224 }
1225
1226 fn sub_with_highlights(&mut self, level: Level, messages: Vec<StringPart>, span: MultiSpan) {
1229 let messages = messages.into_iter().map(|m| (m.content.into(), m.style)).collect();
1230 let sub = Subdiag { level, messages, span };
1231 self.children.push(sub);
1232 }
1233
1234 fn take_diag(&mut self) -> DiagInner {
1238 if let Some(path) = &self.long_ty_path {
1239 self.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the full name for the type has been written to \'{0}\'",
path.display()))
})format!(
1240 "the full name for the type has been written to '{}'",
1241 path.display()
1242 ));
1243 self.note("consider using `--verbose` to print the full type name to the console");
1244 }
1245 *self.diag.take().unwrap()
1246 }
1247
1248 pub fn long_ty_path(&mut self) -> &mut Option<PathBuf> {
1266 &mut self.long_ty_path
1267 }
1268
1269 pub fn with_long_ty_path(mut self, long_ty_path: Option<PathBuf>) -> Self {
1270 self.long_ty_path = long_ty_path;
1271 self
1272 }
1273
1274 fn emit_producing_nothing(mut self) {
1276 let diag = self.take_diag();
1277 self.dcx.emit_diagnostic(diag);
1278 }
1279
1280 fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed {
1282 let diag = self.take_diag();
1283
1284 if !#[allow(non_exhaustive_omitted_patterns)] match diag.level {
Level::Error | Level::DelayedBug => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("invalid diagnostic level ({0:?})",
diag.level));
}
};assert!(
1293 matches!(diag.level, Level::Error | Level::DelayedBug),
1294 "invalid diagnostic level ({:?})",
1295 diag.level,
1296 );
1297
1298 let guar = self.dcx.emit_diagnostic(diag);
1299 guar.unwrap()
1300 }
1301
1302 #[track_caller]
1304 pub fn emit(self) -> G::EmitResult {
1305 G::emit_producing_guarantee(self)
1306 }
1307
1308 #[track_caller]
1313 pub fn emit_unless_delay(mut self, delay: bool) -> G::EmitResult {
1314 if delay {
1315 self.downgrade_to_delayed_bug();
1316 }
1317 self.emit()
1318 }
1319
1320 pub fn cancel(mut self) {
1323 self.diag = None;
1324 drop(self);
1325 }
1326
1327 pub fn cancel_into_message(self) -> Option<String> {
1329 let s = self.diag.as_ref()?.messages.get(0)?.0.as_str().map(ToString::to_string);
1330 self.cancel();
1331 s
1332 }
1333
1334 pub fn stash(mut self, span: Span, key: StashKey) -> Option<ErrorGuaranteed> {
1336 let diag = self.take_diag();
1337 self.dcx.stash_diagnostic(span, key, diag)
1338 }
1339
1340 #[track_caller]
1351 pub fn delay_as_bug(mut self) -> G::EmitResult {
1352 self.downgrade_to_delayed_bug();
1353 self.emit()
1354 }
1355
1356 pub fn remove_arg(&mut self, name: &str) {
1357 if let Some(diag) = self.diag.as_mut() {
1358 diag.remove_arg(name);
1359 }
1360 }
1361}
1362
1363impl<G: EmissionGuarantee> Drop for Diag<'_, G> {
1366 fn drop(&mut self) {
1367 match self.diag.take() {
1368 Some(diag) if !panicking() => {
1369 self.dcx.emit_diagnostic(DiagInner::new(
1370 Level::Bug,
1371 DiagMessage::from("the following error was constructed but not emitted"),
1372 ));
1373 self.dcx.emit_diagnostic(*diag);
1374 {
::core::panicking::panic_fmt(format_args!("error was constructed but not emitted"));
};panic!("error was constructed but not emitted");
1375 }
1376 _ => {}
1377 }
1378 }
1379}
1380
1381#[macro_export]
1382macro_rules! struct_span_code_err {
1383 ($dcx:expr, $span:expr, $code:expr, $($message:tt)*) => ({
1384 $dcx.struct_span_err($span, format!($($message)*)).with_code($code)
1385 })
1386}