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, SubdiagMessage, Substitution, SubstitutionPart, SuggestionStyle,
21 Suggestions,
22};
23
24pub type DiagArgMap = FxIndexMap<DiagArgName, DiagArgValue>;
25
26pub trait EmissionGuarantee: Sized {
29 type EmitResult = Self;
32
33 #[track_caller]
37 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult;
38}
39
40impl EmissionGuarantee for ErrorGuaranteed {
41 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
42 diag.emit_producing_error_guaranteed()
43 }
44}
45
46impl EmissionGuarantee for () {
47 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
48 diag.emit_producing_nothing();
49 }
50}
51
52#[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)]
55pub struct BugAbort;
56
57impl EmissionGuarantee for BugAbort {
58 type EmitResult = !;
59
60 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
61 diag.emit_producing_nothing();
62 panic::panic_any(ExplicitBug);
63 }
64}
65
66#[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)]
69pub struct FatalAbort;
70
71impl EmissionGuarantee for FatalAbort {
72 type EmitResult = !;
73
74 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
75 diag.emit_producing_nothing();
76 crate::FatalError.raise()
77 }
78}
79
80impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
81 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
82 diag.emit_producing_nothing();
83 rustc_span::fatal_error::FatalError
84 }
85}
86
87#[rustc_diagnostic_item = "Diagnostic"]
109pub trait Diagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> {
110 #[must_use]
112 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G>;
113}
114
115impl<'a, T, G> Diagnostic<'a, G> for Spanned<T>
116where
117 T: Diagnostic<'a, G>,
118 G: EmissionGuarantee,
119{
120 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
121 self.node.into_diag(dcx, level).with_span(self.span)
122 }
123}
124
125#[rustc_diagnostic_item = "Subdiagnostic"]
128pub trait Subdiagnostic
129where
130 Self: Sized,
131{
132 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
134}
135
136#[rustc_diagnostic_item = "LintDiagnostic"]
139pub trait LintDiagnostic<'a, G: EmissionGuarantee> {
140 fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>);
142}
143
144pub trait LintDiagnosticBox<'a, G: EmissionGuarantee> {
145 fn decorate_lint_box<'b>(self: Box<Self>, diag: &'b mut Diag<'a, G>);
146}
147
148impl<'a, G: EmissionGuarantee, D: LintDiagnostic<'a, G>> LintDiagnosticBox<'a, G> for D {
149 fn decorate_lint_box<'b>(self: Box<Self>, diag: &'b mut Diag<'a, G>) {
150 self.decorate_lint(diag);
151 }
152}
153
154#[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)]
155pub(crate) struct DiagLocation {
156 file: Cow<'static, str>,
157 line: u32,
158 col: u32,
159}
160
161impl DiagLocation {
162 #[track_caller]
163 fn caller() -> Self {
164 let loc = panic::Location::caller();
165 DiagLocation { file: loc.file().into(), line: loc.line(), col: loc.column() }
166 }
167}
168
169impl fmt::Display for DiagLocation {
170 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171 f.write_fmt(format_args!("{0}:{1}:{2}", self.file, self.line, self.col))write!(f, "{}:{}:{}", self.file, self.line, self.col)
172 }
173}
174
175#[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 {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_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)]
176pub struct IsLint {
177 pub(crate) name: String,
179 has_future_breakage: bool,
181}
182
183#[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 {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Vec<StringPart>>;
}
}Eq)]
184pub struct DiagStyledString(pub Vec<StringPart>);
185
186impl DiagStyledString {
187 pub fn new() -> DiagStyledString {
188 DiagStyledString(::alloc::vec::Vec::new()vec![])
189 }
190 pub fn push_normal<S: Into<String>>(&mut self, t: S) {
191 self.0.push(StringPart::normal(t));
192 }
193 pub fn push_highlighted<S: Into<String>>(&mut self, t: S) {
194 self.0.push(StringPart::highlighted(t));
195 }
196 pub fn push<S: Into<String>>(&mut self, t: S, highlight: bool) {
197 if highlight {
198 self.push_highlighted(t);
199 } else {
200 self.push_normal(t);
201 }
202 }
203 pub fn normal<S: Into<String>>(t: S) -> DiagStyledString {
204 DiagStyledString(<[_]>::into_vec(::alloc::boxed::box_new([StringPart::normal(t)]))vec![StringPart::normal(t)])
205 }
206
207 pub fn highlighted<S: Into<String>>(t: S) -> DiagStyledString {
208 DiagStyledString(<[_]>::into_vec(::alloc::boxed::box_new([StringPart::highlighted(t)]))vec![StringPart::highlighted(t)])
209 }
210
211 pub fn content(&self) -> String {
212 self.0.iter().map(|x| x.content.as_str()).collect::<String>()
213 }
214}
215
216#[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 {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<Style>;
}
}Eq)]
217pub struct StringPart {
218 content: String,
219 style: Style,
220}
221
222impl StringPart {
223 pub fn normal<S: Into<String>>(content: S) -> StringPart {
224 StringPart { content: content.into(), style: Style::NoStyle }
225 }
226
227 pub fn highlighted<S: Into<String>>(content: S) -> StringPart {
228 StringPart { content: content.into(), style: Style::Highlight }
229 }
230}
231
232#[must_use]
237#[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)]
238pub struct DiagInner {
239 pub(crate) level: Level,
242
243 pub messages: Vec<(DiagMessage, Style)>,
244 pub code: Option<ErrCode>,
245 pub lint_id: Option<LintExpectationId>,
246 pub span: MultiSpan,
247 pub children: Vec<Subdiag>,
248 pub suggestions: Suggestions,
249 pub args: DiagArgMap,
250
251 pub reserved_args: DiagArgMap,
253
254 pub sort_span: Span,
258
259 pub is_lint: Option<IsLint>,
260
261 pub long_ty_path: Option<PathBuf>,
262 pub(crate) emitted_at: DiagLocation,
265}
266
267impl DiagInner {
268 #[track_caller]
269 pub fn new<M: Into<DiagMessage>>(level: Level, message: M) -> Self {
270 DiagInner::new_with_messages(level, <[_]>::into_vec(::alloc::boxed::box_new([(message.into(), Style::NoStyle)]))vec![(message.into(), Style::NoStyle)])
271 }
272
273 #[track_caller]
274 pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self {
275 DiagInner {
276 level,
277 lint_id: None,
278 messages,
279 code: None,
280 span: MultiSpan::new(),
281 children: ::alloc::vec::Vec::new()vec![],
282 suggestions: Suggestions::Enabled(::alloc::vec::Vec::new()vec![]),
283 args: Default::default(),
284 reserved_args: Default::default(),
285 sort_span: DUMMY_SP,
286 is_lint: None,
287 long_ty_path: None,
288 emitted_at: DiagLocation::caller(),
289 }
290 }
291
292 #[inline(always)]
293 pub fn level(&self) -> Level {
294 self.level
295 }
296
297 pub fn is_error(&self) -> bool {
298 match self.level {
299 Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true,
300
301 Level::ForceWarning
302 | Level::Warning
303 | Level::Note
304 | Level::OnceNote
305 | Level::Help
306 | Level::OnceHelp
307 | Level::FailureNote
308 | Level::Allow
309 | Level::Expect => false,
310 }
311 }
312
313 pub(crate) fn has_future_breakage(&self) -> bool {
315 #[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, .. }))
316 }
317
318 pub(crate) fn is_force_warn(&self) -> bool {
319 match self.level {
320 Level::ForceWarning => {
321 if !self.is_lint.is_some() {
::core::panicking::panic("assertion failed: self.is_lint.is_some()")
};assert!(self.is_lint.is_some());
322 true
323 }
324 _ => false,
325 }
326 }
327
328 pub(crate) fn subdiagnostic_message_to_diagnostic_message(
330 &self,
331 attr: impl Into<SubdiagMessage>,
332 ) -> DiagMessage {
333 let msg =
334 self.messages.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages");
335 msg.with_subdiagnostic_message(attr.into())
336 }
337
338 pub(crate) fn sub(
339 &mut self,
340 level: Level,
341 message: impl Into<SubdiagMessage>,
342 span: MultiSpan,
343 ) {
344 let sub = Subdiag {
345 level,
346 messages: <[_]>::into_vec(::alloc::boxed::box_new([(self.subdiagnostic_message_to_diagnostic_message(message),
Style::NoStyle)]))vec![(
347 self.subdiagnostic_message_to_diagnostic_message(message),
348 Style::NoStyle,
349 )],
350 span,
351 };
352 self.children.push(sub);
353 }
354
355 pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) {
356 let name = name.into();
357 let value = arg.into_diag_arg(&mut self.long_ty_path);
358 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!(
360 !self.args.contains_key(&name) || self.args.get(&name) == Some(&value),
361 "arg {} already exists",
362 name
363 );
364 self.args.insert(name, value);
365 }
366
367 pub fn remove_arg(&mut self, name: &str) {
368 self.args.swap_remove(name);
369 }
370
371 pub fn store_args(&mut self) {
372 self.reserved_args = self.args.clone();
373 }
374
375 pub fn restore_args(&mut self) {
376 self.args = std::mem::take(&mut self.reserved_args);
377 }
378
379 pub fn emitted_at_sub_diag(&self) -> Subdiag {
380 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);
381 Subdiag {
382 level: crate::Level::Note,
383 messages: <[_]>::into_vec(::alloc::boxed::box_new([(DiagMessage::Str(Cow::Owned(track)),
Style::NoStyle)]))vec![(DiagMessage::Str(Cow::Owned(track)), Style::NoStyle)],
384 span: MultiSpan::new(),
385 }
386 }
387
388 fn keys(
390 &self,
391 ) -> (
392 &Level,
393 &[(DiagMessage, Style)],
394 &Option<ErrCode>,
395 &MultiSpan,
396 &[Subdiag],
397 &Suggestions,
398 Vec<(&DiagArgName, &DiagArgValue)>,
399 &Option<IsLint>,
400 ) {
401 (
402 &self.level,
403 &self.messages,
404 &self.code,
405 &self.span,
406 &self.children,
407 &self.suggestions,
408 self.args.iter().collect(),
409 &self.is_lint,
411 )
413 }
414}
415
416impl Hash for DiagInner {
417 fn hash<H>(&self, state: &mut H)
418 where
419 H: Hasher,
420 {
421 self.keys().hash(state);
422 }
423}
424
425impl PartialEq for DiagInner {
426 fn eq(&self, other: &Self) -> bool {
427 self.keys() == other.keys()
428 }
429}
430
431#[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)]
434pub struct Subdiag {
435 pub level: Level,
436 pub messages: Vec<(DiagMessage, Style)>,
437 pub span: MultiSpan,
438}
439
440#[must_use]
453pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> {
454 pub dcx: DiagCtxtHandle<'a>,
455
456 diag: Option<Box<DiagInner>>,
466
467 _marker: PhantomData<G>,
468}
469
470impl<G> !Clone for Diag<'_, G> {}
473
474const _: [(); 3 * size_of::<usize>()] =
[(); ::std::mem::size_of::<Diag<'_, ()>>()];rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * size_of::<usize>());
475
476impl<G: EmissionGuarantee> Deref for Diag<'_, G> {
477 type Target = DiagInner;
478
479 fn deref(&self) -> &DiagInner {
480 self.diag.as_ref().unwrap()
481 }
482}
483
484impl<G: EmissionGuarantee> DerefMut for Diag<'_, G> {
485 fn deref_mut(&mut self) -> &mut DiagInner {
486 self.diag.as_mut().unwrap()
487 }
488}
489
490impl<G: EmissionGuarantee> Debug for Diag<'_, G> {
491 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
492 self.diag.fmt(f)
493 }
494}
495
496macro_rules! with_fn {
515 {
516 $with_f:ident,
517 $(#[$attrs:meta])*
518 pub fn $f:ident(&mut $self:ident, $($name:ident: $ty:ty),* $(,)?) -> &mut Self {
519 $($body:tt)*
520 }
521 } => {
522 $(#[$attrs])*
524 #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
525 pub fn $f(&mut $self, $($name: $ty),*) -> &mut Self {
526 $($body)*
527 }
528
529 $(#[$attrs])*
531 #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
532 pub fn $with_f(mut $self, $($name: $ty),*) -> Self {
533 $self.$f($($name),*);
534 $self
535 }
536 };
537}
538
539impl<'a, G: EmissionGuarantee> Diag<'a, G> {
540 #[track_caller]
541 pub fn new(dcx: DiagCtxtHandle<'a>, level: Level, message: impl Into<DiagMessage>) -> Self {
542 Self::new_diagnostic(dcx, DiagInner::new(level, message))
543 }
544
545 pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_, G> {
547 Diag { dcx, diag: self.diag.take(), _marker: PhantomData }
548 }
549
550 #[track_caller]
552 pub(crate) fn new_diagnostic(dcx: DiagCtxtHandle<'a>, diag: DiagInner) -> Self {
553 {
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:553",
"rustc_errors::diagnostic", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/diagnostic.rs"),
::tracing_core::__macro_support::Option::Some(553u32),
::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");
554 Self { dcx, diag: Some(Box::new(diag)), _marker: PhantomData }
555 }
556
557 #[track_caller]
568 pub fn downgrade_to_delayed_bug(&mut self) {
569 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!(
570 matches!(self.level, Level::Error | Level::DelayedBug),
571 "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
572 self.level
573 );
574 self.level = Level::DelayedBug;
575 }
576
577 #[track_caller]
585 pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> {
586 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!(
587 matches!(self.level, Level::Error),
588 "upgrade_to_fatal: cannot upgrade {:?} to Fatal: not an error",
589 self.level
590 );
591 self.level = Level::Fatal;
592
593 let diag = self.diag.take();
596 Diag { dcx: self.dcx, diag, _marker: PhantomData }
597 }
598
599 "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,
600 pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagMessage>) -> &mut Self {
613 let msg = self.subdiagnostic_message_to_diagnostic_message(label);
614 self.span.push_span_label(span, msg);
615 self
616 } }
617
618 "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,
619 pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
622 for span in spans {
623 self.span_label(span, label.to_string());
624 }
625 self
626 } }
627
628 pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self {
629 let before = self.span.clone();
630 self.span(after);
631 for span_label in before.span_labels() {
632 if let Some(label) = span_label.label {
633 if span_label.is_primary && keep_label {
634 self.span.push_span_label(after, label);
635 } else {
636 self.span.push_span_label(span_label.span, label);
637 }
638 }
639 }
640 self
641 }
642
643 pub fn note_expected_found(
644 &mut self,
645 expected_label: &str,
646 expected: DiagStyledString,
647 found_label: &str,
648 found: DiagStyledString,
649 ) -> &mut Self {
650 self.note_expected_found_extra(
651 expected_label,
652 expected,
653 found_label,
654 found,
655 DiagStyledString::normal(""),
656 DiagStyledString::normal(""),
657 )
658 }
659
660 pub fn note_expected_found_extra(
661 &mut self,
662 expected_label: &str,
663 expected: DiagStyledString,
664 found_label: &str,
665 found: DiagStyledString,
666 expected_extra: DiagStyledString,
667 found_extra: DiagStyledString,
668 ) -> &mut Self {
669 let expected_label = expected_label.to_string();
670 let expected_label = if expected_label.is_empty() {
671 "expected".to_string()
672 } else {
673 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected {0}", expected_label))
})format!("expected {expected_label}")
674 };
675 let found_label = found_label.to_string();
676 let found_label = if found_label.is_empty() {
677 "found".to_string()
678 } else {
679 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("found {0}", found_label))
})format!("found {found_label}")
680 };
681 let (found_padding, expected_padding) = if expected_label.len() > found_label.len() {
682 (expected_label.len() - found_label.len(), 0)
683 } else {
684 (0, found_label.len() - expected_label.len())
685 };
686 let mut msg = <[_]>::into_vec(::alloc::boxed::box_new([StringPart::normal(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1} `",
" ".repeat(expected_padding), expected_label))
}))]))vec![StringPart::normal(format!(
687 "{}{} `",
688 " ".repeat(expected_padding),
689 expected_label
690 ))];
691 msg.extend(expected.0);
692 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
693 msg.extend(expected_extra.0);
694 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("\n")) })format!("\n")));
695 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)));
696 msg.extend(found.0);
697 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
698 msg.extend(found_extra.0);
699
700 self.highlighted_note(msg);
702 self
703 }
704
705 pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
706 self.highlighted_note(<[_]>::into_vec(::alloc::boxed::box_new([StringPart::normal(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` from trait: `",
name))
})), StringPart::highlighted(signature),
StringPart::normal("`")]))vec![
707 StringPart::normal(format!("`{name}` from trait: `")),
708 StringPart::highlighted(signature),
709 StringPart::normal("`"),
710 ]);
711 self
712 }
713
714 "See [`Diag::note()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::note()`]."
mut self
msg
Self
self.note(msg);
self;with_fn! { with_note,
715 pub fn note(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
717 self.sub(Level::Note, msg, MultiSpan::new());
718 self
719 } }
720
721 pub fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self {
722 self.sub_with_highlights(Level::Note, msg, MultiSpan::new());
723 self
724 }
725
726 pub fn highlighted_span_note(
727 &mut self,
728 span: impl Into<MultiSpan>,
729 msg: Vec<StringPart>,
730 ) -> &mut Self {
731 self.sub_with_highlights(Level::Note, msg, span.into());
732 self
733 }
734
735 pub fn note_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
737 self.sub(Level::OnceNote, msg, MultiSpan::new());
738 self
739 }
740
741 "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,
742 pub fn span_note(
745 &mut self,
746 sp: impl Into<MultiSpan>,
747 msg: impl Into<SubdiagMessage>,
748 ) -> &mut Self {
749 self.sub(Level::Note, msg, sp.into());
750 self
751 } }
752
753 pub fn span_note_once<S: Into<MultiSpan>>(
756 &mut self,
757 sp: S,
758 msg: impl Into<SubdiagMessage>,
759 ) -> &mut Self {
760 self.sub(Level::OnceNote, msg, sp.into());
761 self
762 }
763
764 "See [`Diag::warn()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::warn()`]."
mut self
msg
Self
self.warn(msg);
self;with_fn! { with_warn,
765 pub fn warn(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
767 self.sub(Level::Warning, msg, MultiSpan::new());
768 self
769 } }
770
771 pub fn span_warn<S: Into<MultiSpan>>(
774 &mut self,
775 sp: S,
776 msg: impl Into<SubdiagMessage>,
777 ) -> &mut Self {
778 self.sub(Level::Warning, msg, sp.into());
779 self
780 }
781
782 "See [`Diag::help()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::help()`]."
mut self
msg
Self
self.help(msg);
self;with_fn! { with_help,
783 pub fn help(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
785 self.sub(Level::Help, msg, MultiSpan::new());
786 self
787 } }
788
789 pub fn help_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
791 self.sub(Level::OnceHelp, msg, MultiSpan::new());
792 self
793 }
794
795 pub fn highlighted_help(&mut self, msg: Vec<StringPart>) -> &mut Self {
797 self.sub_with_highlights(Level::Help, msg, MultiSpan::new());
798 self
799 }
800
801 pub fn highlighted_span_help(
803 &mut self,
804 span: impl Into<MultiSpan>,
805 msg: Vec<StringPart>,
806 ) -> &mut Self {
807 self.sub_with_highlights(Level::Help, msg, span.into());
808 self
809 }
810
811 "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,
812 pub fn span_help(
815 &mut self,
816 sp: impl Into<MultiSpan>,
817 msg: impl Into<SubdiagMessage>,
818 ) -> &mut Self {
819 self.sub(Level::Help, msg, sp.into());
820 self
821 } }
822
823 pub fn disable_suggestions(&mut self) -> &mut Self {
827 self.suggestions = Suggestions::Disabled;
828 self
829 }
830
831 pub fn seal_suggestions(&mut self) -> &mut Self {
836 if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
837 let suggestions_slice = std::mem::take(suggestions).into_boxed_slice();
838 self.suggestions = Suggestions::Sealed(suggestions_slice);
839 }
840 self
841 }
842
843 fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
848 for subst in &suggestion.substitutions {
849 for part in &subst.parts {
850 let span = part.span;
851 let call_site = span.ctxt().outer_expn_data().call_site;
852 if span.in_derive_expansion() && span.overlaps_or_adjacent(call_site) {
853 return;
855 }
856 }
857 }
858
859 if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
860 suggestions.push(suggestion);
861 }
862 }
863
864 "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,
865 pub fn multipart_suggestion(
868 &mut self,
869 msg: impl Into<SubdiagMessage>,
870 suggestion: Vec<(Span, String)>,
871 applicability: Applicability,
872 ) -> &mut Self {
873 self.multipart_suggestion_with_style(
874 msg,
875 suggestion,
876 applicability,
877 SuggestionStyle::ShowCode,
878 )
879 } }
880
881 pub fn multipart_suggestion_verbose(
884 &mut self,
885 msg: impl Into<SubdiagMessage>,
886 suggestion: Vec<(Span, String)>,
887 applicability: Applicability,
888 ) -> &mut Self {
889 self.multipart_suggestion_with_style(
890 msg,
891 suggestion,
892 applicability,
893 SuggestionStyle::ShowAlways,
894 )
895 }
896
897 pub fn multipart_suggestion_with_style(
899 &mut self,
900 msg: impl Into<SubdiagMessage>,
901 mut suggestion: Vec<(Span, String)>,
902 applicability: Applicability,
903 style: SuggestionStyle,
904 ) -> &mut Self {
905 let mut seen = crate::FxHashSet::default();
906 suggestion.retain(|(span, msg)| seen.insert((span.lo(), span.hi(), msg.clone())));
907
908 let parts = suggestion
909 .into_iter()
910 .map(|(span, snippet)| SubstitutionPart { snippet, span })
911 .collect::<Vec<_>>();
912
913 if !!parts.is_empty() {
::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
914 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!(
915 parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
916 None,
917 "Span must not be empty and have no suggestion",
918 );
919 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!(
920 parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
921 None,
922 "suggestion must not have overlapping parts",
923 );
924
925 self.push_suggestion(CodeSuggestion {
926 substitutions: <[_]>::into_vec(::alloc::boxed::box_new([Substitution { parts }]))vec![Substitution { parts }],
927 msg: self.subdiagnostic_message_to_diagnostic_message(msg),
928 style,
929 applicability,
930 });
931 self
932 }
933
934 pub fn tool_only_multipart_suggestion(
941 &mut self,
942 msg: impl Into<SubdiagMessage>,
943 suggestion: Vec<(Span, String)>,
944 applicability: Applicability,
945 ) -> &mut Self {
946 self.multipart_suggestion_with_style(
947 msg,
948 suggestion,
949 applicability,
950 SuggestionStyle::CompletelyHidden,
951 )
952 }
953
954 "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,
955 pub fn span_suggestion(
973 &mut self,
974 sp: Span,
975 msg: impl Into<SubdiagMessage>,
976 suggestion: impl ToString,
977 applicability: Applicability,
978 ) -> &mut Self {
979 self.span_suggestion_with_style(
980 sp,
981 msg,
982 suggestion,
983 applicability,
984 SuggestionStyle::ShowCode,
985 );
986 self
987 } }
988
989 pub fn span_suggestion_with_style(
991 &mut self,
992 sp: Span,
993 msg: impl Into<SubdiagMessage>,
994 suggestion: impl ToString,
995 applicability: Applicability,
996 style: SuggestionStyle,
997 ) -> &mut Self {
998 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!(
999 !(sp.is_empty() && suggestion.to_string().is_empty()),
1000 "Span must not be empty and have no suggestion"
1001 );
1002 self.push_suggestion(CodeSuggestion {
1003 substitutions: <[_]>::into_vec(::alloc::boxed::box_new([Substitution {
parts: <[_]>::into_vec(::alloc::boxed::box_new([SubstitutionPart {
snippet: suggestion.to_string(),
span: sp,
}])),
}]))vec![Substitution {
1004 parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
1005 }],
1006 msg: self.subdiagnostic_message_to_diagnostic_message(msg),
1007 style,
1008 applicability,
1009 });
1010 self
1011 }
1012
1013 "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,
1014 pub fn span_suggestion_verbose(
1016 &mut self,
1017 sp: Span,
1018 msg: impl Into<SubdiagMessage>,
1019 suggestion: impl ToString,
1020 applicability: Applicability,
1021 ) -> &mut Self {
1022 self.span_suggestion_with_style(
1023 sp,
1024 msg,
1025 suggestion,
1026 applicability,
1027 SuggestionStyle::ShowAlways,
1028 );
1029 self
1030 } }
1031
1032 "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,
1033 pub fn span_suggestions(
1036 &mut self,
1037 sp: Span,
1038 msg: impl Into<SubdiagMessage>,
1039 suggestions: impl IntoIterator<Item = String>,
1040 applicability: Applicability,
1041 ) -> &mut Self {
1042 self.span_suggestions_with_style(
1043 sp,
1044 msg,
1045 suggestions,
1046 applicability,
1047 SuggestionStyle::ShowCode,
1048 )
1049 } }
1050
1051 pub fn span_suggestions_with_style(
1052 &mut self,
1053 sp: Span,
1054 msg: impl Into<SubdiagMessage>,
1055 suggestions: impl IntoIterator<Item = String>,
1056 applicability: Applicability,
1057 style: SuggestionStyle,
1058 ) -> &mut Self {
1059 let substitutions = suggestions
1060 .into_iter()
1061 .map(|snippet| {
1062 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!(
1063 !(sp.is_empty() && snippet.is_empty()),
1064 "Span `{sp:?}` must not be empty and have no suggestion"
1065 );
1066 Substitution { parts: <[_]>::into_vec(::alloc::boxed::box_new([SubstitutionPart {
snippet,
span: sp,
}]))vec![SubstitutionPart { snippet, span: sp }] }
1067 })
1068 .collect();
1069 self.push_suggestion(CodeSuggestion {
1070 substitutions,
1071 msg: self.subdiagnostic_message_to_diagnostic_message(msg),
1072 style,
1073 applicability,
1074 });
1075 self
1076 }
1077
1078 pub fn multipart_suggestions(
1082 &mut self,
1083 msg: impl Into<SubdiagMessage>,
1084 suggestions: impl IntoIterator<Item = Vec<(Span, String)>>,
1085 applicability: Applicability,
1086 ) -> &mut Self {
1087 let substitutions = suggestions
1088 .into_iter()
1089 .map(|sugg| {
1090 let mut parts = sugg
1091 .into_iter()
1092 .map(|(span, snippet)| SubstitutionPart { snippet, span })
1093 .collect::<Vec<_>>();
1094
1095 parts.sort_unstable_by_key(|part| part.span);
1096
1097 if !!parts.is_empty() {
::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
1098 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!(
1099 parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
1100 None,
1101 "Span must not be empty and have no suggestion",
1102 );
1103 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!(
1104 parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
1105 None,
1106 "suggestion must not have overlapping parts",
1107 );
1108
1109 Substitution { parts }
1110 })
1111 .collect();
1112
1113 self.push_suggestion(CodeSuggestion {
1114 substitutions,
1115 msg: self.subdiagnostic_message_to_diagnostic_message(msg),
1116 style: SuggestionStyle::ShowAlways,
1117 applicability,
1118 });
1119 self
1120 }
1121
1122 "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,
1123 pub fn span_suggestion_short(
1128 &mut self,
1129 sp: Span,
1130 msg: impl Into<SubdiagMessage>,
1131 suggestion: impl ToString,
1132 applicability: Applicability,
1133 ) -> &mut Self {
1134 self.span_suggestion_with_style(
1135 sp,
1136 msg,
1137 suggestion,
1138 applicability,
1139 SuggestionStyle::HideCodeInline,
1140 );
1141 self
1142 } }
1143
1144 pub fn span_suggestion_hidden(
1151 &mut self,
1152 sp: Span,
1153 msg: impl Into<SubdiagMessage>,
1154 suggestion: impl ToString,
1155 applicability: Applicability,
1156 ) -> &mut Self {
1157 self.span_suggestion_with_style(
1158 sp,
1159 msg,
1160 suggestion,
1161 applicability,
1162 SuggestionStyle::HideCodeAlways,
1163 );
1164 self
1165 }
1166
1167 "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,
1168 pub fn tool_only_span_suggestion(
1173 &mut self,
1174 sp: Span,
1175 msg: impl Into<SubdiagMessage>,
1176 suggestion: impl ToString,
1177 applicability: Applicability,
1178 ) -> &mut Self {
1179 self.span_suggestion_with_style(
1180 sp,
1181 msg,
1182 suggestion,
1183 applicability,
1184 SuggestionStyle::CompletelyHidden,
1185 );
1186 self
1187 } }
1188
1189 pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self {
1194 subdiagnostic.add_to_diag(self);
1195 self
1196 }
1197
1198 pub fn eagerly_translate(&self, msg: impl Into<SubdiagMessage>) -> SubdiagMessage {
1204 let args = self.args.iter();
1205 let msg = self.subdiagnostic_message_to_diagnostic_message(msg.into());
1206 self.dcx.eagerly_translate(msg, args)
1207 }
1208
1209 "See [`Diag::span()`]."
&mut Self
self
sp
&mut Self
"See [`Diag::span()`]."
mut self
sp
Self
self.span(sp);
self;with_fn! { with_span,
1210 pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self {
1212 self.span = sp.into();
1213 if let Some(span) = self.span.primary_span() {
1214 self.sort_span = span;
1215 }
1216 self
1217 } }
1218
1219 pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
1220 self.is_lint = Some(IsLint { name, has_future_breakage });
1221 self
1222 }
1223
1224 "See [`Diag::code()`]."
&mut Self
self
code
&mut Self
"See [`Diag::code()`]."
mut self
code
Self
self.code(code);
self;with_fn! { with_code,
1225 pub fn code(&mut self, code: ErrCode) -> &mut Self {
1227 self.code = Some(code);
1228 self
1229 } }
1230
1231 "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,
1232 pub fn lint_id(
1234 &mut self,
1235 id: LintExpectationId,
1236 ) -> &mut Self {
1237 self.lint_id = Some(id);
1238 self
1239 } }
1240
1241 "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,
1242 pub fn primary_message(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
1244 self.messages[0] = (msg.into(), Style::NoStyle);
1245 self
1246 } }
1247
1248 "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,
1249 pub fn arg(
1251 &mut self,
1252 name: impl Into<DiagArgName>,
1253 arg: impl IntoDiagArg,
1254 ) -> &mut Self {
1255 self.deref_mut().arg(name, arg);
1256 self
1257 } }
1258
1259 pub(crate) fn subdiagnostic_message_to_diagnostic_message(
1263 &self,
1264 attr: impl Into<SubdiagMessage>,
1265 ) -> DiagMessage {
1266 self.deref().subdiagnostic_message_to_diagnostic_message(attr)
1267 }
1268
1269 pub fn sub(&mut self, level: Level, message: impl Into<SubdiagMessage>, span: MultiSpan) {
1274 self.deref_mut().sub(level, message, span);
1275 }
1276
1277 fn sub_with_highlights(&mut self, level: Level, messages: Vec<StringPart>, span: MultiSpan) {
1280 let messages = messages
1281 .into_iter()
1282 .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.content), m.style))
1283 .collect();
1284 let sub = Subdiag { level, messages, span };
1285 self.children.push(sub);
1286 }
1287
1288 fn take_diag(&mut self) -> DiagInner {
1292 if let Some(path) = &self.long_ty_path {
1293 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!(
1294 "the full name for the type has been written to '{}'",
1295 path.display()
1296 ));
1297 self.note("consider using `--verbose` to print the full type name to the console");
1298 }
1299 *self.diag.take().unwrap()
1300 }
1301
1302 pub fn long_ty_path(&mut self) -> &mut Option<PathBuf> {
1320 &mut self.long_ty_path
1321 }
1322
1323 pub fn with_long_ty_path(mut self, long_ty_path: Option<PathBuf>) -> Self {
1324 self.long_ty_path = long_ty_path;
1325 self
1326 }
1327
1328 fn emit_producing_nothing(mut self) {
1330 let diag = self.take_diag();
1331 self.dcx.emit_diagnostic(diag);
1332 }
1333
1334 fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed {
1336 let diag = self.take_diag();
1337
1338 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!(
1347 matches!(diag.level, Level::Error | Level::DelayedBug),
1348 "invalid diagnostic level ({:?})",
1349 diag.level,
1350 );
1351
1352 let guar = self.dcx.emit_diagnostic(diag);
1353 guar.unwrap()
1354 }
1355
1356 #[track_caller]
1358 pub fn emit(self) -> G::EmitResult {
1359 G::emit_producing_guarantee(self)
1360 }
1361
1362 #[track_caller]
1367 pub fn emit_unless_delay(mut self, delay: bool) -> G::EmitResult {
1368 if delay {
1369 self.downgrade_to_delayed_bug();
1370 }
1371 self.emit()
1372 }
1373
1374 pub fn cancel(mut self) {
1377 self.diag = None;
1378 drop(self);
1379 }
1380
1381 pub fn stash(mut self, span: Span, key: StashKey) -> Option<ErrorGuaranteed> {
1383 let diag = self.take_diag();
1384 self.dcx.stash_diagnostic(span, key, diag)
1385 }
1386
1387 #[track_caller]
1398 pub fn delay_as_bug(mut self) -> G::EmitResult {
1399 self.downgrade_to_delayed_bug();
1400 self.emit()
1401 }
1402
1403 pub fn remove_arg(&mut self, name: &str) {
1404 if let Some(diag) = self.diag.as_mut() {
1405 diag.remove_arg(name);
1406 }
1407 }
1408}
1409
1410impl<G: EmissionGuarantee> Drop for Diag<'_, G> {
1413 fn drop(&mut self) {
1414 match self.diag.take() {
1415 Some(diag) if !panicking() => {
1416 self.dcx.emit_diagnostic(DiagInner::new(
1417 Level::Bug,
1418 DiagMessage::from("the following error was constructed but not emitted"),
1419 ));
1420 self.dcx.emit_diagnostic(*diag);
1421 {
::core::panicking::panic_fmt(format_args!("error was constructed but not emitted"));
};panic!("error was constructed but not emitted");
1422 }
1423 _ => {}
1424 }
1425 }
1426}
1427
1428#[macro_export]
1429macro_rules! struct_span_code_err {
1430 ($dcx:expr, $span:expr, $code:expr, $($message:tt)*) => ({
1431 $dcx.struct_span_err($span, format!($($message)*)).with_code($code)
1432 })
1433}