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, DynSync};
11use rustc_error_messages::{DiagArgMap, DiagArgName, DiagArgValue, IntoDiagArg};
12use rustc_lint_defs::{Applicability, LintExpectationId};
13use rustc_macros::{Decodable, Encodable};
14use rustc_span::{DUMMY_SP, Span, Spanned, Symbol};
15use tracing::debug;
16
17use crate::{
18 CodeSuggestion, DiagCtxtHandle, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level,
19 MultiSpan, StashKey, Style, Substitution, SubstitutionPart, SuggestionStyle, Suggestions,
20};
21
22pub trait EmissionGuarantee: Sized {
25 type EmitResult = Self;
28
29 #[track_caller]
33 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult;
34}
35
36impl EmissionGuarantee for ErrorGuaranteed {
37 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
38 diag.emit_producing_error_guaranteed()
39 }
40}
41
42impl EmissionGuarantee for () {
43 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
44 diag.emit_producing_nothing();
45 }
46}
47
48#[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)]
51pub struct BugAbort;
52
53impl EmissionGuarantee for BugAbort {
54 type EmitResult = !;
55
56 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
57 diag.emit_producing_nothing();
58 panic::panic_any(ExplicitBug);
59 }
60}
61
62#[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)]
65pub struct FatalAbort;
66
67impl EmissionGuarantee for FatalAbort {
68 type EmitResult = !;
69
70 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
71 diag.emit_producing_nothing();
72 crate::FatalError.raise()
73 }
74}
75
76impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
77 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
78 diag.emit_producing_nothing();
79 rustc_span::fatal_error::FatalError
80 }
81}
82
83#[rustc_diagnostic_item = "Diagnostic"]
105pub trait Diagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> {
106 #[must_use]
108 #[track_caller]
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<
124 dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level) -> Diag<'b, ()> + DynSync + DynSend + 'static,
125 >
126{
127 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
128 self(dcx, level)
129 }
130}
131
132pub struct DiagCallback<'a>(
133 pub &'a Box<
134 dyn for<'b> Fn(DiagCtxtHandle<'b>, Level) -> Diag<'b, ()> + DynSend + DynSync + 'static,
135 >,
136);
137
138impl<'a, 'b> Diagnostic<'a, ()> for DiagCallback<'b> {
139 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
140 (self.0)(dcx, level)
141 }
142}
143
144pub struct DiagDecorator<F: FnOnce(&mut Diag<'_, ()>)>(pub F);
146
147impl<'a, F: FnOnce(&mut Diag<'_, ()>)> Diagnostic<'a, ()> for DiagDecorator<F> {
148 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
149 let mut diag = Diag::new(dcx, level, "");
150 (self.0)(&mut diag);
151 diag
152 }
153}
154
155#[rustc_diagnostic_item = "Subdiagnostic"]
158pub trait Subdiagnostic
159where
160 Self: Sized,
161{
162 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
164}
165
166#[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)]
167pub struct DiagLocation {
168 file: Cow<'static, str>,
169 line: u32,
170 col: u32,
171}
172
173impl DiagLocation {
174 #[track_caller]
175 pub fn caller() -> Self {
176 let loc = panic::Location::caller();
177 DiagLocation { file: loc.file().into(), line: loc.line(), col: loc.column() }
178 }
179}
180
181impl fmt::Display for DiagLocation {
182 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183 f.write_fmt(format_args!("{0}:{1}:{2}", self.file, self.line, self.col))write!(f, "{}:{}:{}", self.file, self.line, self.col)
184 }
185}
186
187#[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)]
188pub struct IsLint {
189 pub(crate) name: String,
191 has_future_breakage: bool,
193}
194
195#[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)]
196pub struct DiagStyledString(pub Vec<StringPart>);
197
198impl DiagStyledString {
199 pub fn new() -> DiagStyledString {
200 DiagStyledString(::alloc::vec::Vec::new()vec![])
201 }
202 pub fn push_normal<S: Into<String>>(&mut self, t: S) {
203 self.0.push(StringPart::normal(t));
204 }
205 pub fn push_highlighted<S: Into<String>>(&mut self, t: S) {
206 self.0.push(StringPart::highlighted(t));
207 }
208 pub fn push<S: Into<String>>(&mut self, t: S, highlight: bool) {
209 if highlight {
210 self.push_highlighted(t);
211 } else {
212 self.push_normal(t);
213 }
214 }
215 pub fn normal<S: Into<String>>(t: S) -> DiagStyledString {
216 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)])
217 }
218
219 pub fn highlighted<S: Into<String>>(t: S) -> DiagStyledString {
220 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)])
221 }
222
223 pub fn content(&self) -> String {
224 self.0.iter().map(|x| x.content.as_str()).collect::<String>()
225 }
226}
227
228#[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)]
229pub struct StringPart {
230 content: String,
231 style: Style,
232}
233
234impl StringPart {
235 pub fn normal<S: Into<String>>(content: S) -> StringPart {
236 StringPart { content: content.into(), style: Style::NoStyle }
237 }
238
239 pub fn highlighted<S: Into<String>>(content: S) -> StringPart {
240 StringPart { content: content.into(), style: Style::Highlight }
241 }
242}
243
244#[must_use]
249#[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),
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", "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.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,
sort_span: ref __binding_8,
is_lint: ref __binding_9,
long_ty_path: ref __binding_10,
emitted_at: ref __binding_11 } => {
::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);
}
}
}
}
};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),
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)]
250pub struct DiagInner {
251 pub(crate) level: Level,
254
255 pub messages: Vec<(DiagMessage, Style)>,
256 pub code: Option<ErrCode>,
257 pub lint_id: Option<LintExpectationId>,
258 pub span: MultiSpan,
259 pub children: Vec<Subdiag>,
260 pub suggestions: Suggestions,
261 pub args: DiagArgMap,
262
263 pub sort_span: Span,
267
268 pub is_lint: Option<IsLint>,
269
270 pub long_ty_path: Option<PathBuf>,
271 pub emitted_at: DiagLocation,
274}
275
276impl DiagInner {
277 #[track_caller]
278 pub fn new<M: Into<DiagMessage>>(level: Level, message: M) -> Self {
279 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)])
280 }
281
282 #[track_caller]
283 pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self {
284 DiagInner {
285 level,
286 lint_id: None,
287 messages,
288 code: None,
289 span: MultiSpan::new(),
290 children: ::alloc::vec::Vec::new()vec![],
291 suggestions: Suggestions::Enabled(::alloc::vec::Vec::new()vec![]),
292 args: Default::default(),
293 sort_span: DUMMY_SP,
294 is_lint: None,
295 long_ty_path: None,
296 emitted_at: DiagLocation::caller(),
297 }
298 }
299
300 #[inline(always)]
301 pub fn level(&self) -> Level {
302 self.level
303 }
304
305 pub fn is_error(&self) -> bool {
306 match self.level {
307 Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true,
308
309 Level::ForceWarning
310 | Level::Warning
311 | Level::Note
312 | Level::OnceNote
313 | Level::Help
314 | Level::OnceHelp
315 | Level::FailureNote
316 | Level::Allow
317 | Level::Expect => false,
318 }
319 }
320
321 pub(crate) fn has_future_breakage(&self) -> bool {
323 #[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, .. }))
324 }
325
326 pub(crate) fn is_force_warn(&self) -> bool {
327 match self.level {
328 Level::ForceWarning => {
329 if !self.is_lint.is_some() {
::core::panicking::panic("assertion failed: self.is_lint.is_some()")
};assert!(self.is_lint.is_some());
330 true
331 }
332 _ => false,
333 }
334 }
335
336 pub(crate) fn sub(&mut self, level: Level, message: impl Into<DiagMessage>, span: MultiSpan) {
337 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 };
338 self.children.push(sub);
339 }
340
341 pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) {
342 let name = name.into();
343 let value = arg.into_diag_arg(&mut self.long_ty_path);
344 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!(
346 !self.args.contains_key(&name) || self.args.get(&name) == Some(&value),
347 "arg {} already exists",
348 name
349 );
350 self.args.insert(name, value);
351 }
352
353 pub fn remove_arg(&mut self, name: &str) {
354 self.args.swap_remove(name);
355 }
356
357 pub fn emitted_at_sub_diag(&self) -> Subdiag {
358 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);
359 Subdiag {
360 level: crate::Level::Note,
361 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)],
362 span: MultiSpan::new(),
363 }
364 }
365
366 fn keys(
368 &self,
369 ) -> (
370 &Level,
371 &[(DiagMessage, Style)],
372 &Option<ErrCode>,
373 &MultiSpan,
374 &[Subdiag],
375 &Suggestions,
376 Vec<(&DiagArgName, &DiagArgValue)>,
377 &Option<IsLint>,
378 ) {
379 (
380 &self.level,
381 &self.messages,
382 &self.code,
383 &self.span,
384 &self.children,
385 &self.suggestions,
386 self.args.iter().collect(),
387 &self.is_lint,
389 )
391 }
392}
393
394impl Hash for DiagInner {
395 fn hash<H>(&self, state: &mut H)
396 where
397 H: Hasher,
398 {
399 self.keys().hash(state);
400 }
401}
402
403impl PartialEq for DiagInner {
404 fn eq(&self, other: &Self) -> bool {
405 self.keys() == other.keys()
406 }
407}
408
409#[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)]
412pub struct Subdiag {
413 pub level: Level,
414 pub messages: Vec<(DiagMessage, Style)>,
415 pub span: MultiSpan,
416}
417
418#[must_use]
431pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> {
432 pub dcx: DiagCtxtHandle<'a>,
433
434 diag: Option<Box<DiagInner>>,
444
445 _marker: PhantomData<G>,
446}
447
448impl<G> !Clone for Diag<'_, G> {}
451
452const _: [(); 3 * size_of::<usize>()] =
[(); ::std::mem::size_of::<Diag<'_, ()>>()];rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * size_of::<usize>());
453
454impl<G: EmissionGuarantee> Deref for Diag<'_, G> {
455 type Target = DiagInner;
456
457 fn deref(&self) -> &DiagInner {
458 self.diag.as_ref().unwrap()
459 }
460}
461
462impl<G: EmissionGuarantee> DerefMut for Diag<'_, G> {
463 fn deref_mut(&mut self) -> &mut DiagInner {
464 self.diag.as_mut().unwrap()
465 }
466}
467
468impl<G: EmissionGuarantee> Debug for Diag<'_, G> {
469 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
470 self.diag.fmt(f)
471 }
472}
473
474macro_rules! with_fn {
493 {
494 $with_f:ident,
495 $(#[$attrs:meta])*
496 pub fn $f:ident(&mut $self:ident, $($name:ident: $ty:ty),* $(,)?) -> &mut Self {
497 $($body:tt)*
498 }
499 } => {
500 $(#[$attrs])*
502 #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
503 pub fn $f(&mut $self, $($name: $ty),*) -> &mut Self {
504 $($body)*
505 }
506
507 $(#[$attrs])*
509 #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
510 pub fn $with_f(mut $self, $($name: $ty),*) -> Self {
511 $self.$f($($name),*);
512 $self
513 }
514 };
515}
516
517impl<'a, G: EmissionGuarantee> Diag<'a, G> {
518 #[track_caller]
519 pub fn new(dcx: DiagCtxtHandle<'a>, level: Level, message: impl Into<DiagMessage>) -> Self {
520 Self::new_diagnostic(dcx, DiagInner::new(level, message))
521 }
522
523 pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_, G> {
525 Diag { dcx, diag: self.diag.take(), _marker: PhantomData }
526 }
527
528 #[track_caller]
530 pub(crate) fn new_diagnostic(dcx: DiagCtxtHandle<'a>, diag: DiagInner) -> Self {
531 {
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:531",
"rustc_errors::diagnostic", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/diagnostic.rs"),
::tracing_core::__macro_support::Option::Some(531u32),
::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");
532 Self { dcx, diag: Some(Box::new(diag)), _marker: PhantomData }
533 }
534
535 #[track_caller]
546 pub fn downgrade_to_delayed_bug(&mut self) {
547 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!(
548 matches!(self.level, Level::Error | Level::DelayedBug),
549 "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
550 self.level
551 );
552 self.level = Level::DelayedBug;
553 }
554
555 #[track_caller]
563 pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> {
564 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!(
565 matches!(self.level, Level::Error),
566 "upgrade_to_fatal: cannot upgrade {:?} to Fatal: not an error",
567 self.level
568 );
569 self.level = Level::Fatal;
570
571 let diag = self.diag.take();
574 Diag { dcx: self.dcx, diag, _marker: PhantomData }
575 }
576
577 "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,
578 pub fn span_label(&mut self, span: Span, label: impl Into<DiagMessage>) -> &mut Self {
591 self.span.push_span_label(span, label.into());
592 self
593 } }
594
595 "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,
596 pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
599 for span in spans {
600 self.span_label(span, label.to_string());
601 }
602 self
603 } }
604
605 pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self {
606 let before = self.span.clone();
607 self.span(after);
608 for span_label in before.span_labels() {
609 if let Some(label) = span_label.label {
610 if span_label.is_primary && keep_label {
611 self.span.push_span_label(after, label);
612 } else {
613 self.span.push_span_label(span_label.span, label);
614 }
615 }
616 }
617 self
618 }
619
620 pub fn note_expected_found(
621 &mut self,
622 expected_label: &str,
623 expected: DiagStyledString,
624 found_label: &str,
625 found: DiagStyledString,
626 ) -> &mut Self {
627 self.note_expected_found_extra(
628 expected_label,
629 expected,
630 found_label,
631 found,
632 DiagStyledString::normal(""),
633 DiagStyledString::normal(""),
634 )
635 }
636
637 pub fn note_expected_found_extra(
638 &mut self,
639 expected_label: &str,
640 expected: DiagStyledString,
641 found_label: &str,
642 found: DiagStyledString,
643 expected_extra: DiagStyledString,
644 found_extra: DiagStyledString,
645 ) -> &mut Self {
646 let expected_label = expected_label.to_string();
647 let expected_label = if expected_label.is_empty() {
648 "expected".to_string()
649 } else {
650 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected {0}", expected_label))
})format!("expected {expected_label}")
651 };
652 let found_label = found_label.to_string();
653 let found_label = if found_label.is_empty() {
654 "found".to_string()
655 } else {
656 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("found {0}", found_label))
})format!("found {found_label}")
657 };
658 let (found_padding, expected_padding) = if expected_label.len() > found_label.len() {
659 (expected_label.len() - found_label.len(), 0)
660 } else {
661 (0, found_label.len() - expected_label.len())
662 };
663 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!(
664 "{}{} `",
665 " ".repeat(expected_padding),
666 expected_label
667 ))];
668 msg.extend(expected.0);
669 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
670 msg.extend(expected_extra.0);
671 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("\n")) })format!("\n")));
672 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)));
673 msg.extend(found.0);
674 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
675 msg.extend(found_extra.0);
676
677 self.highlighted_note(msg);
679 self
680 }
681
682 pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
683 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![
684 StringPart::normal(format!("`{name}` from trait: `")),
685 StringPart::highlighted(signature),
686 StringPart::normal("`"),
687 ]);
688 self
689 }
690
691 "See [`Diag::note()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::note()`]."
mut self
msg
Self
self.note(msg);
self;with_fn! { with_note,
692 pub fn note(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
694 self.sub(Level::Note, msg, MultiSpan::new());
695 self
696 } }
697
698 pub fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self {
699 self.sub_with_highlights(Level::Note, msg, MultiSpan::new());
700 self
701 }
702
703 pub fn highlighted_span_note(
704 &mut self,
705 span: impl Into<MultiSpan>,
706 msg: Vec<StringPart>,
707 ) -> &mut Self {
708 self.sub_with_highlights(Level::Note, msg, span.into());
709 self
710 }
711
712 pub fn note_once(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
714 self.sub(Level::OnceNote, msg, MultiSpan::new());
715 self
716 }
717
718 "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,
719 pub fn span_note(
722 &mut self,
723 sp: impl Into<MultiSpan>,
724 msg: impl Into<DiagMessage>,
725 ) -> &mut Self {
726 self.sub(Level::Note, msg, sp.into());
727 self
728 } }
729
730 pub fn span_note_once<S: Into<MultiSpan>>(
733 &mut self,
734 sp: S,
735 msg: impl Into<DiagMessage>,
736 ) -> &mut Self {
737 self.sub(Level::OnceNote, msg, sp.into());
738 self
739 }
740
741 "See [`Diag::warn()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::warn()`]."
mut self
msg
Self
self.warn(msg);
self;with_fn! { with_warn,
742 pub fn warn(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
744 self.sub(Level::Warning, msg, MultiSpan::new());
745 self
746 } }
747
748 pub fn span_warn<S: Into<MultiSpan>>(
751 &mut self,
752 sp: S,
753 msg: impl Into<DiagMessage>,
754 ) -> &mut Self {
755 self.sub(Level::Warning, msg, sp.into());
756 self
757 }
758
759 "See [`Diag::help()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::help()`]."
mut self
msg
Self
self.help(msg);
self;with_fn! { with_help,
760 pub fn help(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
762 self.sub(Level::Help, msg, MultiSpan::new());
763 self
764 } }
765
766 pub fn help_once(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
768 self.sub(Level::OnceHelp, msg, MultiSpan::new());
769 self
770 }
771
772 pub fn highlighted_help(&mut self, msg: Vec<StringPart>) -> &mut Self {
774 self.sub_with_highlights(Level::Help, msg, MultiSpan::new());
775 self
776 }
777
778 pub fn highlighted_span_help(
780 &mut self,
781 span: impl Into<MultiSpan>,
782 msg: Vec<StringPart>,
783 ) -> &mut Self {
784 self.sub_with_highlights(Level::Help, msg, span.into());
785 self
786 }
787
788 "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,
789 pub fn span_help(
792 &mut self,
793 sp: impl Into<MultiSpan>,
794 msg: impl Into<DiagMessage>,
795 ) -> &mut Self {
796 self.sub(Level::Help, msg, sp.into());
797 self
798 } }
799
800 pub fn disable_suggestions(&mut self) -> &mut Self {
804 self.suggestions = Suggestions::Disabled;
805 self
806 }
807
808 pub fn seal_suggestions(&mut self) -> &mut Self {
813 if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
814 let suggestions_slice = std::mem::take(suggestions).into_boxed_slice();
815 self.suggestions = Suggestions::Sealed(suggestions_slice);
816 }
817 self
818 }
819
820 fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
825 for subst in &suggestion.substitutions {
826 for part in &subst.parts {
827 let span = part.span;
828 let call_site = span.ctxt().outer_expn_data().call_site;
829 if span.in_derive_expansion() && span.overlaps_or_adjacent(call_site) {
830 return;
832 }
833 }
834 }
835
836 if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
837 suggestions.push(suggestion);
838 }
839 }
840
841 "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,
842 pub fn multipart_suggestion(
845 &mut self,
846 msg: impl Into<DiagMessage>,
847 suggestion: Vec<(Span, String)>,
848 applicability: Applicability,
849 ) -> &mut Self {
850 self.multipart_suggestion_with_style(
851 msg,
852 suggestion,
853 applicability,
854 SuggestionStyle::ShowAlways,
855 )
856 } }
857
858 pub fn multipart_suggestion_with_style(
860 &mut self,
861 msg: impl Into<DiagMessage>,
862 mut suggestion: Vec<(Span, String)>,
863 applicability: Applicability,
864 style: SuggestionStyle,
865 ) -> &mut Self {
866 let mut seen = crate::FxHashSet::default();
867 suggestion.retain(|(span, msg)| seen.insert((span.lo(), span.hi(), msg.clone())));
868
869 let parts = suggestion
870 .into_iter()
871 .map(|(span, snippet)| SubstitutionPart { snippet, span })
872 .collect::<Vec<_>>();
873
874 if !!parts.is_empty() {
::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
875 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!(
876 parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
877 None,
878 "Span must not be empty and have no suggestion",
879 );
880 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!(
881 parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
882 None,
883 "suggestion must not have overlapping parts",
884 );
885
886 self.push_suggestion(CodeSuggestion {
887 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 }],
888 msg: msg.into(),
889 style,
890 applicability,
891 });
892 self
893 }
894
895 pub fn tool_only_multipart_suggestion(
902 &mut self,
903 msg: impl Into<DiagMessage>,
904 suggestion: Vec<(Span, String)>,
905 applicability: Applicability,
906 ) -> &mut Self {
907 self.multipart_suggestion_with_style(
908 msg,
909 suggestion,
910 applicability,
911 SuggestionStyle::CompletelyHidden,
912 )
913 }
914
915 "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,
916 pub fn span_suggestion(
934 &mut self,
935 sp: Span,
936 msg: impl Into<DiagMessage>,
937 suggestion: impl ToString,
938 applicability: Applicability,
939 ) -> &mut Self {
940 self.span_suggestion_with_style(
941 sp,
942 msg,
943 suggestion,
944 applicability,
945 SuggestionStyle::ShowCode,
946 );
947 self
948 } }
949
950 "See [`Diag::span_suggestion_with_style()`]."
&mut Self
self
sp
msg
suggestion
applicability
style
&mut Self
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"));
}
};
};
::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,
}])),
}]))
"See [`Diag::span_suggestion_with_style()`]."
mut self
sp
msg
suggestion
applicability
style
Self
self.span_suggestion_with_style(sp, msg, suggestion, applicability, style);
self;with_fn! { with_span_suggestion_with_style,
951 pub fn span_suggestion_with_style(
953 &mut self,
954 sp: Span,
955 msg: impl Into<DiagMessage>,
956 suggestion: impl ToString,
957 applicability: Applicability,
958 style: SuggestionStyle,
959 ) -> &mut Self {
960 debug_assert!(
961 !(sp.is_empty() && suggestion.to_string().is_empty()),
962 "Span must not be empty and have no suggestion"
963 );
964 self.push_suggestion(CodeSuggestion {
965 substitutions: vec![Substitution {
966 parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
967 }],
968 msg: msg.into(),
969 style,
970 applicability,
971 });
972 self
973 } }
974
975 "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,
976 pub fn span_suggestion_verbose(
978 &mut self,
979 sp: Span,
980 msg: impl Into<DiagMessage>,
981 suggestion: impl ToString,
982 applicability: Applicability,
983 ) -> &mut Self {
984 self.span_suggestion_with_style(
985 sp,
986 msg,
987 suggestion,
988 applicability,
989 SuggestionStyle::ShowAlways,
990 );
991 self
992 } }
993
994 "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,
995 pub fn span_suggestions(
998 &mut self,
999 sp: Span,
1000 msg: impl Into<DiagMessage>,
1001 suggestions: impl IntoIterator<Item = String>,
1002 applicability: Applicability,
1003 ) -> &mut Self {
1004 self.span_suggestions_with_style(
1005 sp,
1006 msg,
1007 suggestions,
1008 applicability,
1009 SuggestionStyle::ShowAlways,
1010 )
1011 } }
1012
1013 pub fn span_suggestions_with_style(
1014 &mut self,
1015 sp: Span,
1016 msg: impl Into<DiagMessage>,
1017 suggestions: impl IntoIterator<Item = String>,
1018 applicability: Applicability,
1019 style: SuggestionStyle,
1020 ) -> &mut Self {
1021 let substitutions = suggestions
1022 .into_iter()
1023 .map(|snippet| {
1024 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!(
1025 !(sp.is_empty() && snippet.is_empty()),
1026 "Span `{sp:?}` must not be empty and have no suggestion"
1027 );
1028 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 }] }
1029 })
1030 .collect();
1031 self.push_suggestion(CodeSuggestion {
1032 substitutions,
1033 msg: msg.into(),
1034 style,
1035 applicability,
1036 });
1037 self
1038 }
1039
1040 pub fn multipart_suggestions(
1044 &mut self,
1045 msg: impl Into<DiagMessage>,
1046 suggestions: impl IntoIterator<Item = Vec<(Span, String)>>,
1047 applicability: Applicability,
1048 ) -> &mut Self {
1049 let substitutions = suggestions
1050 .into_iter()
1051 .map(|sugg| {
1052 let mut parts = sugg
1053 .into_iter()
1054 .map(|(span, snippet)| SubstitutionPart { snippet, span })
1055 .collect::<Vec<_>>();
1056
1057 parts.sort_unstable_by_key(|part| part.span);
1058
1059 if !!parts.is_empty() {
::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
1060 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!(
1061 parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
1062 None,
1063 "Span must not be empty and have no suggestion",
1064 );
1065 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!(
1066 parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
1067 None,
1068 "suggestion must not have overlapping parts",
1069 );
1070
1071 Substitution { parts }
1072 })
1073 .collect();
1074
1075 self.push_suggestion(CodeSuggestion {
1076 substitutions,
1077 msg: msg.into(),
1078 style: SuggestionStyle::ShowAlways,
1079 applicability,
1080 });
1081 self
1082 }
1083
1084 "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,
1085 pub fn span_suggestion_short(
1090 &mut self,
1091 sp: Span,
1092 msg: impl Into<DiagMessage>,
1093 suggestion: impl ToString,
1094 applicability: Applicability,
1095 ) -> &mut Self {
1096 self.span_suggestion_with_style(
1097 sp,
1098 msg,
1099 suggestion,
1100 applicability,
1101 SuggestionStyle::HideCodeInline,
1102 );
1103 self
1104 } }
1105
1106 pub fn span_suggestion_hidden(
1113 &mut self,
1114 sp: Span,
1115 msg: impl Into<DiagMessage>,
1116 suggestion: impl ToString,
1117 applicability: Applicability,
1118 ) -> &mut Self {
1119 self.span_suggestion_with_style(
1120 sp,
1121 msg,
1122 suggestion,
1123 applicability,
1124 SuggestionStyle::HideCodeAlways,
1125 );
1126 self
1127 }
1128
1129 "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,
1130 pub fn tool_only_span_suggestion(
1135 &mut self,
1136 sp: Span,
1137 msg: impl Into<DiagMessage>,
1138 suggestion: impl ToString,
1139 applicability: Applicability,
1140 ) -> &mut Self {
1141 self.span_suggestion_with_style(
1142 sp,
1143 msg,
1144 suggestion,
1145 applicability,
1146 SuggestionStyle::CompletelyHidden,
1147 );
1148 self
1149 } }
1150
1151 pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self {
1156 subdiagnostic.add_to_diag(self);
1157 self
1158 }
1159
1160 "See [`Diag::span()`]."
&mut Self
self
sp
&mut Self
"See [`Diag::span()`]."
mut self
sp
Self
self.span(sp);
self;with_fn! { with_span,
1161 pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self {
1163 self.span = sp.into();
1164 if let Some(span) = self.span.primary_span() {
1165 self.sort_span = span;
1166 }
1167 self
1168 } }
1169
1170 pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
1171 self.is_lint = Some(IsLint { name, has_future_breakage });
1172 self
1173 }
1174
1175 "See [`Diag::code()`]."
&mut Self
self
code
&mut Self
"See [`Diag::code()`]."
mut self
code
Self
self.code(code);
self;with_fn! { with_code,
1176 pub fn code(&mut self, code: ErrCode) -> &mut Self {
1178 self.code = Some(code);
1179 self
1180 } }
1181
1182 "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,
1183 pub fn lint_id(
1185 &mut self,
1186 id: LintExpectationId,
1187 ) -> &mut Self {
1188 self.lint_id = Some(id);
1189 self
1190 } }
1191
1192 "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,
1193 pub fn primary_message(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
1195 self.messages[0] = (msg.into(), Style::NoStyle);
1196 self
1197 } }
1198
1199 "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,
1200 pub fn arg(
1202 &mut self,
1203 name: impl Into<DiagArgName>,
1204 arg: impl IntoDiagArg,
1205 ) -> &mut Self {
1206 self.deref_mut().arg(name, arg);
1207 self
1208 } }
1209
1210 pub fn sub(&mut self, level: Level, message: impl Into<DiagMessage>, span: MultiSpan) {
1215 self.deref_mut().sub(level, message, span);
1216 }
1217
1218 fn sub_with_highlights(&mut self, level: Level, messages: Vec<StringPart>, span: MultiSpan) {
1221 let messages = messages.into_iter().map(|m| (m.content.into(), m.style)).collect();
1222 let sub = Subdiag { level, messages, span };
1223 self.children.push(sub);
1224 }
1225
1226 fn take_diag(&mut self) -> DiagInner {
1230 if let Some(path) = &self.long_ty_path {
1231 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!(
1232 "the full name for the type has been written to '{}'",
1233 path.display()
1234 ));
1235 self.note("consider using `--verbose` to print the full type name to the console");
1236 }
1237 *self.diag.take().unwrap()
1238 }
1239
1240 pub fn long_ty_path(&mut self) -> &mut Option<PathBuf> {
1258 &mut self.long_ty_path
1259 }
1260
1261 pub fn with_long_ty_path(mut self, long_ty_path: Option<PathBuf>) -> Self {
1262 self.long_ty_path = long_ty_path;
1263 self
1264 }
1265
1266 fn emit_producing_nothing(mut self) {
1268 let diag = self.take_diag();
1269 self.dcx.emit_diagnostic(diag);
1270 }
1271
1272 fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed {
1274 let diag = self.take_diag();
1275
1276 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!(
1285 matches!(diag.level, Level::Error | Level::DelayedBug),
1286 "invalid diagnostic level ({:?})",
1287 diag.level,
1288 );
1289
1290 let guar = self.dcx.emit_diagnostic(diag);
1291 guar.unwrap()
1292 }
1293
1294 #[track_caller]
1296 pub fn emit(self) -> G::EmitResult {
1297 G::emit_producing_guarantee(self)
1298 }
1299
1300 #[track_caller]
1305 pub fn emit_unless_delay(mut self, delay: bool) -> G::EmitResult {
1306 if delay {
1307 self.downgrade_to_delayed_bug();
1308 }
1309 self.emit()
1310 }
1311
1312 pub fn cancel(mut self) {
1315 self.diag = None;
1316 drop(self);
1317 }
1318
1319 pub fn cancel_into_message(self) -> Option<String> {
1321 let s = self.diag.as_ref()?.messages.get(0)?.0.as_str().map(ToString::to_string);
1322 self.cancel();
1323 s
1324 }
1325
1326 pub fn stash(mut self, span: Span, key: StashKey) -> Option<ErrorGuaranteed> {
1328 let diag = self.take_diag();
1329 self.dcx.stash_diagnostic(span, key, diag)
1330 }
1331
1332 #[track_caller]
1343 pub fn delay_as_bug(mut self) -> G::EmitResult {
1344 self.downgrade_to_delayed_bug();
1345 self.emit()
1346 }
1347}
1348
1349impl<G: EmissionGuarantee> Drop for Diag<'_, G> {
1352 fn drop(&mut self) {
1353 match self.diag.take() {
1354 Some(diag) if !panicking() => {
1355 self.dcx.emit_diagnostic(DiagInner::new(
1356 Level::Bug,
1357 DiagMessage::from("the following error was constructed but not emitted"),
1358 ));
1359 self.dcx.emit_diagnostic(*diag);
1360 {
::core::panicking::panic_fmt(format_args!("error was constructed but not emitted"));
};panic!("error was constructed but not emitted");
1361 }
1362 _ => {}
1363 }
1364 }
1365}
1366
1367#[macro_export]
1368macro_rules! struct_span_code_err {
1369 ($dcx:expr, $span:expr, $code:expr, $($message:tt)*) => ({
1370 $dcx.struct_span_err($span, format!($($message)*)).with_code($code)
1371 })
1372}