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::sync::DynSend;
11use rustc_error_messages::{DiagArgMap, 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 trait EmissionGuarantee: Sized {
26 type EmitResult = Self;
29
30 #[track_caller]
34 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult;
35}
36
37impl EmissionGuarantee for ErrorGuaranteed {
38 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
39 diag.emit_producing_error_guaranteed()
40 }
41}
42
43impl EmissionGuarantee for () {
44 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
45 diag.emit_producing_nothing();
46 }
47}
48
49#[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)]
52pub struct BugAbort;
53
54impl EmissionGuarantee for BugAbort {
55 type EmitResult = !;
56
57 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
58 diag.emit_producing_nothing();
59 panic::panic_any(ExplicitBug);
60 }
61}
62
63#[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)]
66pub struct FatalAbort;
67
68impl EmissionGuarantee for FatalAbort {
69 type EmitResult = !;
70
71 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
72 diag.emit_producing_nothing();
73 crate::FatalError.raise()
74 }
75}
76
77impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
78 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
79 diag.emit_producing_nothing();
80 rustc_span::fatal_error::FatalError
81 }
82}
83
84#[rustc_diagnostic_item = "Diagnostic"]
106pub trait Diagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> {
107 #[must_use]
109 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G>;
110}
111
112impl<'a, T, G> Diagnostic<'a, G> for Spanned<T>
113where
114 T: Diagnostic<'a, G>,
115 G: EmissionGuarantee,
116{
117 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
118 self.node.into_diag(dcx, level).with_span(self.span)
119 }
120}
121
122impl<'a> Diagnostic<'a, ()>
123 for Box<dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level) -> Diag<'b, ()> + DynSend + 'static>
124{
125 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
126 self(dcx, level)
127 }
128}
129
130#[rustc_diagnostic_item = "Subdiagnostic"]
133pub trait Subdiagnostic
134where
135 Self: Sized,
136{
137 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
139}
140
141#[rustc_diagnostic_item = "LintDiagnostic"]
144pub trait LintDiagnostic<'a, G: EmissionGuarantee> {
145 fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>);
147}
148
149#[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)]
150pub(crate) struct DiagLocation {
151 file: Cow<'static, str>,
152 line: u32,
153 col: u32,
154}
155
156impl DiagLocation {
157 #[track_caller]
158 fn caller() -> Self {
159 let loc = panic::Location::caller();
160 DiagLocation { file: loc.file().into(), line: loc.line(), col: loc.column() }
161 }
162}
163
164impl fmt::Display for DiagLocation {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 f.write_fmt(format_args!("{0}:{1}:{2}", self.file, self.line, self.col))write!(f, "{}:{}:{}", self.file, self.line, self.col)
167 }
168}
169
170#[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_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)]
171pub struct IsLint {
172 pub(crate) name: String,
174 has_future_breakage: bool,
176}
177
178#[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_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Vec<StringPart>>;
}
}Eq)]
179pub struct DiagStyledString(pub Vec<StringPart>);
180
181impl DiagStyledString {
182 pub fn new() -> DiagStyledString {
183 DiagStyledString(::alloc::vec::Vec::new()vec![])
184 }
185 pub fn push_normal<S: Into<String>>(&mut self, t: S) {
186 self.0.push(StringPart::normal(t));
187 }
188 pub fn push_highlighted<S: Into<String>>(&mut self, t: S) {
189 self.0.push(StringPart::highlighted(t));
190 }
191 pub fn push<S: Into<String>>(&mut self, t: S, highlight: bool) {
192 if highlight {
193 self.push_highlighted(t);
194 } else {
195 self.push_normal(t);
196 }
197 }
198 pub fn normal<S: Into<String>>(t: S) -> DiagStyledString {
199 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)])
200 }
201
202 pub fn highlighted<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::highlighted(t)]))vec![StringPart::highlighted(t)])
204 }
205
206 pub fn content(&self) -> String {
207 self.0.iter().map(|x| x.content.as_str()).collect::<String>()
208 }
209}
210
211#[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_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<Style>;
}
}Eq)]
212pub struct StringPart {
213 content: String,
214 style: Style,
215}
216
217impl StringPart {
218 pub fn normal<S: Into<String>>(content: S) -> StringPart {
219 StringPart { content: content.into(), style: Style::NoStyle }
220 }
221
222 pub fn highlighted<S: Into<String>>(content: S) -> StringPart {
223 StringPart { content: content.into(), style: Style::Highlight }
224 }
225}
226
227#[must_use]
232#[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)]
233pub struct DiagInner {
234 pub(crate) level: Level,
237
238 pub messages: Vec<(DiagMessage, Style)>,
239 pub code: Option<ErrCode>,
240 pub lint_id: Option<LintExpectationId>,
241 pub span: MultiSpan,
242 pub children: Vec<Subdiag>,
243 pub suggestions: Suggestions,
244 pub args: DiagArgMap,
245
246 pub reserved_args: DiagArgMap,
248
249 pub sort_span: Span,
253
254 pub is_lint: Option<IsLint>,
255
256 pub long_ty_path: Option<PathBuf>,
257 pub(crate) emitted_at: DiagLocation,
260}
261
262impl DiagInner {
263 #[track_caller]
264 pub fn new<M: Into<DiagMessage>>(level: Level, message: M) -> Self {
265 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)])
266 }
267
268 #[track_caller]
269 pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self {
270 DiagInner {
271 level,
272 lint_id: None,
273 messages,
274 code: None,
275 span: MultiSpan::new(),
276 children: ::alloc::vec::Vec::new()vec![],
277 suggestions: Suggestions::Enabled(::alloc::vec::Vec::new()vec![]),
278 args: Default::default(),
279 reserved_args: Default::default(),
280 sort_span: DUMMY_SP,
281 is_lint: None,
282 long_ty_path: None,
283 emitted_at: DiagLocation::caller(),
284 }
285 }
286
287 #[inline(always)]
288 pub fn level(&self) -> Level {
289 self.level
290 }
291
292 pub fn is_error(&self) -> bool {
293 match self.level {
294 Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true,
295
296 Level::ForceWarning
297 | Level::Warning
298 | Level::Note
299 | Level::OnceNote
300 | Level::Help
301 | Level::OnceHelp
302 | Level::FailureNote
303 | Level::Allow
304 | Level::Expect => false,
305 }
306 }
307
308 pub(crate) fn has_future_breakage(&self) -> bool {
310 #[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, .. }))
311 }
312
313 pub(crate) fn is_force_warn(&self) -> bool {
314 match self.level {
315 Level::ForceWarning => {
316 if !self.is_lint.is_some() {
::core::panicking::panic("assertion failed: self.is_lint.is_some()")
};assert!(self.is_lint.is_some());
317 true
318 }
319 _ => false,
320 }
321 }
322
323 pub(crate) fn sub(&mut self, level: Level, message: impl Into<DiagMessage>, span: MultiSpan) {
324 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 };
325 self.children.push(sub);
326 }
327
328 pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) {
329 let name = name.into();
330 let value = arg.into_diag_arg(&mut self.long_ty_path);
331 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!(
333 !self.args.contains_key(&name) || self.args.get(&name) == Some(&value),
334 "arg {} already exists",
335 name
336 );
337 self.args.insert(name, value);
338 }
339
340 pub fn remove_arg(&mut self, name: &str) {
341 self.args.swap_remove(name);
342 }
343
344 pub fn store_args(&mut self) {
345 self.reserved_args = self.args.clone();
346 }
347
348 pub fn restore_args(&mut self) {
349 self.args = std::mem::take(&mut self.reserved_args);
350 }
351
352 pub fn emitted_at_sub_diag(&self) -> Subdiag {
353 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);
354 Subdiag {
355 level: crate::Level::Note,
356 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)],
357 span: MultiSpan::new(),
358 }
359 }
360
361 fn keys(
363 &self,
364 ) -> (
365 &Level,
366 &[(DiagMessage, Style)],
367 &Option<ErrCode>,
368 &MultiSpan,
369 &[Subdiag],
370 &Suggestions,
371 Vec<(&DiagArgName, &DiagArgValue)>,
372 &Option<IsLint>,
373 ) {
374 (
375 &self.level,
376 &self.messages,
377 &self.code,
378 &self.span,
379 &self.children,
380 &self.suggestions,
381 self.args.iter().collect(),
382 &self.is_lint,
384 )
386 }
387}
388
389impl Hash for DiagInner {
390 fn hash<H>(&self, state: &mut H)
391 where
392 H: Hasher,
393 {
394 self.keys().hash(state);
395 }
396}
397
398impl PartialEq for DiagInner {
399 fn eq(&self, other: &Self) -> bool {
400 self.keys() == other.keys()
401 }
402}
403
404#[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)]
407pub struct Subdiag {
408 pub level: Level,
409 pub messages: Vec<(DiagMessage, Style)>,
410 pub span: MultiSpan,
411}
412
413#[must_use]
426pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> {
427 pub dcx: DiagCtxtHandle<'a>,
428
429 diag: Option<Box<DiagInner>>,
439
440 _marker: PhantomData<G>,
441}
442
443impl<G> !Clone for Diag<'_, G> {}
446
447const _: [(); 3 * size_of::<usize>()] =
[(); ::std::mem::size_of::<Diag<'_, ()>>()];rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * size_of::<usize>());
448
449impl<G: EmissionGuarantee> Deref for Diag<'_, G> {
450 type Target = DiagInner;
451
452 fn deref(&self) -> &DiagInner {
453 self.diag.as_ref().unwrap()
454 }
455}
456
457impl<G: EmissionGuarantee> DerefMut for Diag<'_, G> {
458 fn deref_mut(&mut self) -> &mut DiagInner {
459 self.diag.as_mut().unwrap()
460 }
461}
462
463impl<G: EmissionGuarantee> Debug for Diag<'_, G> {
464 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
465 self.diag.fmt(f)
466 }
467}
468
469macro_rules! with_fn {
488 {
489 $with_f:ident,
490 $(#[$attrs:meta])*
491 pub fn $f:ident(&mut $self:ident, $($name:ident: $ty:ty),* $(,)?) -> &mut Self {
492 $($body:tt)*
493 }
494 } => {
495 $(#[$attrs])*
497 #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
498 pub fn $f(&mut $self, $($name: $ty),*) -> &mut Self {
499 $($body)*
500 }
501
502 $(#[$attrs])*
504 #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
505 pub fn $with_f(mut $self, $($name: $ty),*) -> Self {
506 $self.$f($($name),*);
507 $self
508 }
509 };
510}
511
512impl<'a, G: EmissionGuarantee> Diag<'a, G> {
513 #[track_caller]
514 pub fn new(dcx: DiagCtxtHandle<'a>, level: Level, message: impl Into<DiagMessage>) -> Self {
515 Self::new_diagnostic(dcx, DiagInner::new(level, message))
516 }
517
518 pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_, G> {
520 Diag { dcx, diag: self.diag.take(), _marker: PhantomData }
521 }
522
523 #[track_caller]
525 pub(crate) fn new_diagnostic(dcx: DiagCtxtHandle<'a>, diag: DiagInner) -> Self {
526 {
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:526",
"rustc_errors::diagnostic", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/diagnostic.rs"),
::tracing_core::__macro_support::Option::Some(526u32),
::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");
527 Self { dcx, diag: Some(Box::new(diag)), _marker: PhantomData }
528 }
529
530 #[track_caller]
541 pub fn downgrade_to_delayed_bug(&mut self) {
542 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!(
543 matches!(self.level, Level::Error | Level::DelayedBug),
544 "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
545 self.level
546 );
547 self.level = Level::DelayedBug;
548 }
549
550 #[track_caller]
558 pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> {
559 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!(
560 matches!(self.level, Level::Error),
561 "upgrade_to_fatal: cannot upgrade {:?} to Fatal: not an error",
562 self.level
563 );
564 self.level = Level::Fatal;
565
566 let diag = self.diag.take();
569 Diag { dcx: self.dcx, diag, _marker: PhantomData }
570 }
571
572 "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,
573 pub fn span_label(&mut self, span: Span, label: impl Into<DiagMessage>) -> &mut Self {
586 self.span.push_span_label(span, label.into());
587 self
588 } }
589
590 "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,
591 pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
594 for span in spans {
595 self.span_label(span, label.to_string());
596 }
597 self
598 } }
599
600 pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self {
601 let before = self.span.clone();
602 self.span(after);
603 for span_label in before.span_labels() {
604 if let Some(label) = span_label.label {
605 if span_label.is_primary && keep_label {
606 self.span.push_span_label(after, label);
607 } else {
608 self.span.push_span_label(span_label.span, label);
609 }
610 }
611 }
612 self
613 }
614
615 pub fn note_expected_found(
616 &mut self,
617 expected_label: &str,
618 expected: DiagStyledString,
619 found_label: &str,
620 found: DiagStyledString,
621 ) -> &mut Self {
622 self.note_expected_found_extra(
623 expected_label,
624 expected,
625 found_label,
626 found,
627 DiagStyledString::normal(""),
628 DiagStyledString::normal(""),
629 )
630 }
631
632 pub fn note_expected_found_extra(
633 &mut self,
634 expected_label: &str,
635 expected: DiagStyledString,
636 found_label: &str,
637 found: DiagStyledString,
638 expected_extra: DiagStyledString,
639 found_extra: DiagStyledString,
640 ) -> &mut Self {
641 let expected_label = expected_label.to_string();
642 let expected_label = if expected_label.is_empty() {
643 "expected".to_string()
644 } else {
645 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected {0}", expected_label))
})format!("expected {expected_label}")
646 };
647 let found_label = found_label.to_string();
648 let found_label = if found_label.is_empty() {
649 "found".to_string()
650 } else {
651 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("found {0}", found_label))
})format!("found {found_label}")
652 };
653 let (found_padding, expected_padding) = if expected_label.len() > found_label.len() {
654 (expected_label.len() - found_label.len(), 0)
655 } else {
656 (0, found_label.len() - expected_label.len())
657 };
658 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!(
659 "{}{} `",
660 " ".repeat(expected_padding),
661 expected_label
662 ))];
663 msg.extend(expected.0);
664 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
665 msg.extend(expected_extra.0);
666 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("\n")) })format!("\n")));
667 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)));
668 msg.extend(found.0);
669 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
670 msg.extend(found_extra.0);
671
672 self.highlighted_note(msg);
674 self
675 }
676
677 pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
678 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![
679 StringPart::normal(format!("`{name}` from trait: `")),
680 StringPart::highlighted(signature),
681 StringPart::normal("`"),
682 ]);
683 self
684 }
685
686 "See [`Diag::note()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::note()`]."
mut self
msg
Self
self.note(msg);
self;with_fn! { with_note,
687 pub fn note(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
689 self.sub(Level::Note, msg, MultiSpan::new());
690 self
691 } }
692
693 pub fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self {
694 self.sub_with_highlights(Level::Note, msg, MultiSpan::new());
695 self
696 }
697
698 pub fn highlighted_span_note(
699 &mut self,
700 span: impl Into<MultiSpan>,
701 msg: Vec<StringPart>,
702 ) -> &mut Self {
703 self.sub_with_highlights(Level::Note, msg, span.into());
704 self
705 }
706
707 pub fn note_once(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
709 self.sub(Level::OnceNote, msg, MultiSpan::new());
710 self
711 }
712
713 "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,
714 pub fn span_note(
717 &mut self,
718 sp: impl Into<MultiSpan>,
719 msg: impl Into<DiagMessage>,
720 ) -> &mut Self {
721 self.sub(Level::Note, msg, sp.into());
722 self
723 } }
724
725 pub fn span_note_once<S: Into<MultiSpan>>(
728 &mut self,
729 sp: S,
730 msg: impl Into<DiagMessage>,
731 ) -> &mut Self {
732 self.sub(Level::OnceNote, msg, sp.into());
733 self
734 }
735
736 "See [`Diag::warn()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::warn()`]."
mut self
msg
Self
self.warn(msg);
self;with_fn! { with_warn,
737 pub fn warn(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
739 self.sub(Level::Warning, msg, MultiSpan::new());
740 self
741 } }
742
743 pub fn span_warn<S: Into<MultiSpan>>(
746 &mut self,
747 sp: S,
748 msg: impl Into<DiagMessage>,
749 ) -> &mut Self {
750 self.sub(Level::Warning, msg, sp.into());
751 self
752 }
753
754 "See [`Diag::help()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::help()`]."
mut self
msg
Self
self.help(msg);
self;with_fn! { with_help,
755 pub fn help(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
757 self.sub(Level::Help, msg, MultiSpan::new());
758 self
759 } }
760
761 pub fn help_once(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
763 self.sub(Level::OnceHelp, msg, MultiSpan::new());
764 self
765 }
766
767 pub fn highlighted_help(&mut self, msg: Vec<StringPart>) -> &mut Self {
769 self.sub_with_highlights(Level::Help, msg, MultiSpan::new());
770 self
771 }
772
773 pub fn highlighted_span_help(
775 &mut self,
776 span: impl Into<MultiSpan>,
777 msg: Vec<StringPart>,
778 ) -> &mut Self {
779 self.sub_with_highlights(Level::Help, msg, span.into());
780 self
781 }
782
783 "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,
784 pub fn span_help(
787 &mut self,
788 sp: impl Into<MultiSpan>,
789 msg: impl Into<DiagMessage>,
790 ) -> &mut Self {
791 self.sub(Level::Help, msg, sp.into());
792 self
793 } }
794
795 pub fn disable_suggestions(&mut self) -> &mut Self {
799 self.suggestions = Suggestions::Disabled;
800 self
801 }
802
803 pub fn seal_suggestions(&mut self) -> &mut Self {
808 if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
809 let suggestions_slice = std::mem::take(suggestions).into_boxed_slice();
810 self.suggestions = Suggestions::Sealed(suggestions_slice);
811 }
812 self
813 }
814
815 fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
820 for subst in &suggestion.substitutions {
821 for part in &subst.parts {
822 let span = part.span;
823 let call_site = span.ctxt().outer_expn_data().call_site;
824 if span.in_derive_expansion() && span.overlaps_or_adjacent(call_site) {
825 return;
827 }
828 }
829 }
830
831 if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
832 suggestions.push(suggestion);
833 }
834 }
835
836 "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,
837 pub fn multipart_suggestion(
840 &mut self,
841 msg: impl Into<DiagMessage>,
842 suggestion: Vec<(Span, String)>,
843 applicability: Applicability,
844 ) -> &mut Self {
845 self.multipart_suggestion_with_style(
846 msg,
847 suggestion,
848 applicability,
849 SuggestionStyle::ShowAlways,
850 )
851 } }
852
853 pub fn multipart_suggestion_with_style(
855 &mut self,
856 msg: impl Into<DiagMessage>,
857 mut suggestion: Vec<(Span, String)>,
858 applicability: Applicability,
859 style: SuggestionStyle,
860 ) -> &mut Self {
861 let mut seen = crate::FxHashSet::default();
862 suggestion.retain(|(span, msg)| seen.insert((span.lo(), span.hi(), msg.clone())));
863
864 let parts = suggestion
865 .into_iter()
866 .map(|(span, snippet)| SubstitutionPart { snippet, span })
867 .collect::<Vec<_>>();
868
869 if !!parts.is_empty() {
::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
870 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!(
871 parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
872 None,
873 "Span must not be empty and have no suggestion",
874 );
875 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!(
876 parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
877 None,
878 "suggestion must not have overlapping parts",
879 );
880
881 self.push_suggestion(CodeSuggestion {
882 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 }],
883 msg: msg.into(),
884 style,
885 applicability,
886 });
887 self
888 }
889
890 pub fn tool_only_multipart_suggestion(
897 &mut self,
898 msg: impl Into<DiagMessage>,
899 suggestion: Vec<(Span, String)>,
900 applicability: Applicability,
901 ) -> &mut Self {
902 self.multipart_suggestion_with_style(
903 msg,
904 suggestion,
905 applicability,
906 SuggestionStyle::CompletelyHidden,
907 )
908 }
909
910 "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,
911 pub fn span_suggestion(
929 &mut self,
930 sp: Span,
931 msg: impl Into<DiagMessage>,
932 suggestion: impl ToString,
933 applicability: Applicability,
934 ) -> &mut Self {
935 self.span_suggestion_with_style(
936 sp,
937 msg,
938 suggestion,
939 applicability,
940 SuggestionStyle::ShowCode,
941 );
942 self
943 } }
944
945 pub fn span_suggestion_with_style(
947 &mut self,
948 sp: Span,
949 msg: impl Into<DiagMessage>,
950 suggestion: impl ToString,
951 applicability: Applicability,
952 style: SuggestionStyle,
953 ) -> &mut Self {
954 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!(
955 !(sp.is_empty() && suggestion.to_string().is_empty()),
956 "Span must not be empty and have no suggestion"
957 );
958 self.push_suggestion(CodeSuggestion {
959 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 {
960 parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
961 }],
962 msg: msg.into(),
963 style,
964 applicability,
965 });
966 self
967 }
968
969 "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,
970 pub fn span_suggestion_verbose(
972 &mut self,
973 sp: Span,
974 msg: impl Into<DiagMessage>,
975 suggestion: impl ToString,
976 applicability: Applicability,
977 ) -> &mut Self {
978 self.span_suggestion_with_style(
979 sp,
980 msg,
981 suggestion,
982 applicability,
983 SuggestionStyle::ShowAlways,
984 );
985 self
986 } }
987
988 "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,
989 pub fn span_suggestions(
992 &mut self,
993 sp: Span,
994 msg: impl Into<DiagMessage>,
995 suggestions: impl IntoIterator<Item = String>,
996 applicability: Applicability,
997 ) -> &mut Self {
998 self.span_suggestions_with_style(
999 sp,
1000 msg,
1001 suggestions,
1002 applicability,
1003 SuggestionStyle::ShowCode,
1004 )
1005 } }
1006
1007 pub fn span_suggestions_with_style(
1008 &mut self,
1009 sp: Span,
1010 msg: impl Into<DiagMessage>,
1011 suggestions: impl IntoIterator<Item = String>,
1012 applicability: Applicability,
1013 style: SuggestionStyle,
1014 ) -> &mut Self {
1015 let substitutions = suggestions
1016 .into_iter()
1017 .map(|snippet| {
1018 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!(
1019 !(sp.is_empty() && snippet.is_empty()),
1020 "Span `{sp:?}` must not be empty and have no suggestion"
1021 );
1022 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 }] }
1023 })
1024 .collect();
1025 self.push_suggestion(CodeSuggestion {
1026 substitutions,
1027 msg: msg.into(),
1028 style,
1029 applicability,
1030 });
1031 self
1032 }
1033
1034 pub fn multipart_suggestions(
1038 &mut self,
1039 msg: impl Into<DiagMessage>,
1040 suggestions: impl IntoIterator<Item = Vec<(Span, String)>>,
1041 applicability: Applicability,
1042 ) -> &mut Self {
1043 let substitutions = suggestions
1044 .into_iter()
1045 .map(|sugg| {
1046 let mut parts = sugg
1047 .into_iter()
1048 .map(|(span, snippet)| SubstitutionPart { snippet, span })
1049 .collect::<Vec<_>>();
1050
1051 parts.sort_unstable_by_key(|part| part.span);
1052
1053 if !!parts.is_empty() {
::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
1054 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!(
1055 parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
1056 None,
1057 "Span must not be empty and have no suggestion",
1058 );
1059 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!(
1060 parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
1061 None,
1062 "suggestion must not have overlapping parts",
1063 );
1064
1065 Substitution { parts }
1066 })
1067 .collect();
1068
1069 self.push_suggestion(CodeSuggestion {
1070 substitutions,
1071 msg: msg.into(),
1072 style: SuggestionStyle::ShowAlways,
1073 applicability,
1074 });
1075 self
1076 }
1077
1078 "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,
1079 pub fn span_suggestion_short(
1084 &mut self,
1085 sp: Span,
1086 msg: impl Into<DiagMessage>,
1087 suggestion: impl ToString,
1088 applicability: Applicability,
1089 ) -> &mut Self {
1090 self.span_suggestion_with_style(
1091 sp,
1092 msg,
1093 suggestion,
1094 applicability,
1095 SuggestionStyle::HideCodeInline,
1096 );
1097 self
1098 } }
1099
1100 pub fn span_suggestion_hidden(
1107 &mut self,
1108 sp: Span,
1109 msg: impl Into<DiagMessage>,
1110 suggestion: impl ToString,
1111 applicability: Applicability,
1112 ) -> &mut Self {
1113 self.span_suggestion_with_style(
1114 sp,
1115 msg,
1116 suggestion,
1117 applicability,
1118 SuggestionStyle::HideCodeAlways,
1119 );
1120 self
1121 }
1122
1123 "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,
1124 pub fn tool_only_span_suggestion(
1129 &mut self,
1130 sp: Span,
1131 msg: impl Into<DiagMessage>,
1132 suggestion: impl ToString,
1133 applicability: Applicability,
1134 ) -> &mut Self {
1135 self.span_suggestion_with_style(
1136 sp,
1137 msg,
1138 suggestion,
1139 applicability,
1140 SuggestionStyle::CompletelyHidden,
1141 );
1142 self
1143 } }
1144
1145 pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self {
1150 subdiagnostic.add_to_diag(self);
1151 self
1152 }
1153
1154 pub fn eagerly_translate(&self, msg: impl Into<DiagMessage>) -> DiagMessage {
1160 let args = self.args.iter();
1161 self.dcx.eagerly_translate(msg.into(), args)
1162 }
1163
1164 "See [`Diag::span()`]."
&mut Self
self
sp
&mut Self
"See [`Diag::span()`]."
mut self
sp
Self
self.span(sp);
self;with_fn! { with_span,
1165 pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self {
1167 self.span = sp.into();
1168 if let Some(span) = self.span.primary_span() {
1169 self.sort_span = span;
1170 }
1171 self
1172 } }
1173
1174 pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
1175 self.is_lint = Some(IsLint { name, has_future_breakage });
1176 self
1177 }
1178
1179 "See [`Diag::code()`]."
&mut Self
self
code
&mut Self
"See [`Diag::code()`]."
mut self
code
Self
self.code(code);
self;with_fn! { with_code,
1180 pub fn code(&mut self, code: ErrCode) -> &mut Self {
1182 self.code = Some(code);
1183 self
1184 } }
1185
1186 "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,
1187 pub fn lint_id(
1189 &mut self,
1190 id: LintExpectationId,
1191 ) -> &mut Self {
1192 self.lint_id = Some(id);
1193 self
1194 } }
1195
1196 "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,
1197 pub fn primary_message(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
1199 self.messages[0] = (msg.into(), Style::NoStyle);
1200 self
1201 } }
1202
1203 "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,
1204 pub fn arg(
1206 &mut self,
1207 name: impl Into<DiagArgName>,
1208 arg: impl IntoDiagArg,
1209 ) -> &mut Self {
1210 self.deref_mut().arg(name, arg);
1211 self
1212 } }
1213
1214 pub fn sub(&mut self, level: Level, message: impl Into<DiagMessage>, span: MultiSpan) {
1219 self.deref_mut().sub(level, message, span);
1220 }
1221
1222 fn sub_with_highlights(&mut self, level: Level, messages: Vec<StringPart>, span: MultiSpan) {
1225 let messages = messages.into_iter().map(|m| (m.content.into(), m.style)).collect();
1226 let sub = Subdiag { level, messages, span };
1227 self.children.push(sub);
1228 }
1229
1230 fn take_diag(&mut self) -> DiagInner {
1234 if let Some(path) = &self.long_ty_path {
1235 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!(
1236 "the full name for the type has been written to '{}'",
1237 path.display()
1238 ));
1239 self.note("consider using `--verbose` to print the full type name to the console");
1240 }
1241 *self.diag.take().unwrap()
1242 }
1243
1244 pub fn long_ty_path(&mut self) -> &mut Option<PathBuf> {
1262 &mut self.long_ty_path
1263 }
1264
1265 pub fn with_long_ty_path(mut self, long_ty_path: Option<PathBuf>) -> Self {
1266 self.long_ty_path = long_ty_path;
1267 self
1268 }
1269
1270 fn emit_producing_nothing(mut self) {
1272 let diag = self.take_diag();
1273 self.dcx.emit_diagnostic(diag);
1274 }
1275
1276 fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed {
1278 let diag = self.take_diag();
1279
1280 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!(
1289 matches!(diag.level, Level::Error | Level::DelayedBug),
1290 "invalid diagnostic level ({:?})",
1291 diag.level,
1292 );
1293
1294 let guar = self.dcx.emit_diagnostic(diag);
1295 guar.unwrap()
1296 }
1297
1298 #[track_caller]
1300 pub fn emit(self) -> G::EmitResult {
1301 G::emit_producing_guarantee(self)
1302 }
1303
1304 #[track_caller]
1309 pub fn emit_unless_delay(mut self, delay: bool) -> G::EmitResult {
1310 if delay {
1311 self.downgrade_to_delayed_bug();
1312 }
1313 self.emit()
1314 }
1315
1316 pub fn cancel(mut self) {
1319 self.diag = None;
1320 drop(self);
1321 }
1322
1323 pub fn cancel_into_message(self) -> Option<String> {
1325 let s = self.diag.as_ref()?.messages.get(0)?.0.as_str().map(ToString::to_string);
1326 self.cancel();
1327 s
1328 }
1329
1330 pub fn stash(mut self, span: Span, key: StashKey) -> Option<ErrorGuaranteed> {
1332 let diag = self.take_diag();
1333 self.dcx.stash_diagnostic(span, key, diag)
1334 }
1335
1336 #[track_caller]
1347 pub fn delay_as_bug(mut self) -> G::EmitResult {
1348 self.downgrade_to_delayed_bug();
1349 self.emit()
1350 }
1351
1352 pub fn remove_arg(&mut self, name: &str) {
1353 if let Some(diag) = self.diag.as_mut() {
1354 diag.remove_arg(name);
1355 }
1356 }
1357}
1358
1359impl<G: EmissionGuarantee> Drop for Diag<'_, G> {
1362 fn drop(&mut self) {
1363 match self.diag.take() {
1364 Some(diag) if !panicking() => {
1365 self.dcx.emit_diagnostic(DiagInner::new(
1366 Level::Bug,
1367 DiagMessage::from("the following error was constructed but not emitted"),
1368 ));
1369 self.dcx.emit_diagnostic(*diag);
1370 {
::core::panicking::panic_fmt(format_args!("error was constructed but not emitted"));
};panic!("error was constructed but not emitted");
1371 }
1372 _ => {}
1373 }
1374 }
1375}
1376
1377#[macro_export]
1378macro_rules! struct_span_code_err {
1379 ($dcx:expr, $span:expr, $code:expr, $($message:tt)*) => ({
1380 $dcx.struct_span_err($span, format!($($message)*)).with_code($code)
1381 })
1382}