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_error_messages::{DiagArgMap, DiagArgName, DiagArgValue, IntoDiagArg};
11use rustc_lint_defs::{Applicability, LintExpectationId};
12use rustc_macros::{Decodable, Encodable};
13use rustc_span::{DUMMY_SP, Span, Spanned, Symbol};
14use tracing::debug;
15
16use crate::{
17 CodeSuggestion, DiagCtxtHandle, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level,
18 MultiSpan, StashKey, Style, Substitution, SubstitutionPart, SuggestionStyle, Suggestions,
19};
20
21pub trait EmissionGuarantee: Sized {
24 type EmitResult = Self;
27
28 #[track_caller]
32 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult;
33}
34
35impl EmissionGuarantee for ErrorGuaranteed {
36 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
37 diag.emit_producing_error_guaranteed()
38 }
39}
40
41impl EmissionGuarantee for () {
42 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
43 diag.emit_producing_nothing();
44 }
45}
46
47#[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)]
50pub struct BugAbort;
51
52impl EmissionGuarantee for BugAbort {
53 type EmitResult = !;
54
55 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
56 diag.emit_producing_nothing();
57 panic::panic_any(ExplicitBug);
58 }
59}
60
61#[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)]
64pub struct FatalAbort;
65
66impl EmissionGuarantee for FatalAbort {
67 type EmitResult = !;
68
69 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
70 diag.emit_producing_nothing();
71 crate::FatalError.raise()
72 }
73}
74
75impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
76 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
77 diag.emit_producing_nothing();
78 rustc_span::fatal_error::FatalError
79 }
80}
81
82#[rustc_diagnostic_item = "Diagnostic"]
104pub trait Diagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> {
105 #[must_use]
107 #[track_caller]
108 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G>;
109}
110
111impl<'a, T, G> Diagnostic<'a, G> for Spanned<T>
112where
113 T: Diagnostic<'a, G>,
114 G: EmissionGuarantee,
115{
116 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
117 self.node.into_diag(dcx, level).with_span(self.span)
118 }
119}
120
121pub struct DiagDecorator<F: FnOnce(&mut Diag<'_, ()>)>(pub F);
123
124impl<'a, F: FnOnce(&mut Diag<'_, ()>)> Diagnostic<'a, ()> for DiagDecorator<F> {
125 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
126 let mut diag = Diag::new(dcx, level, "");
127 (self.0)(&mut diag);
128 diag
129 }
130}
131
132#[rustc_diagnostic_item = "Subdiagnostic"]
135pub trait Subdiagnostic
136where
137 Self: Sized,
138{
139 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
141}
142
143#[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)]
144pub struct DiagLocation {
145 file: Cow<'static, str>,
146 line: u32,
147 col: u32,
148}
149
150impl DiagLocation {
151 #[track_caller]
152 pub fn caller() -> Self {
153 let loc = panic::Location::caller();
154 DiagLocation { file: loc.file().into(), line: loc.line(), col: loc.column() }
155 }
156}
157
158impl fmt::Display for DiagLocation {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 f.write_fmt(format_args!("{0}:{1}:{2}", self.file, self.line, self.col))write!(f, "{}:{}:{}", self.file, self.line, self.col)
161 }
162}
163
164#[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)]
165pub struct IsLint {
166 pub(crate) name: String,
168 has_future_breakage: bool,
170}
171
172#[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)]
173pub struct DiagStyledString(pub Vec<StringPart>);
174
175impl DiagStyledString {
176 pub fn new() -> DiagStyledString {
177 DiagStyledString(::alloc::vec::Vec::new()vec![])
178 }
179 pub fn push_normal<S: Into<String>>(&mut self, t: S) {
180 self.0.push(StringPart::normal(t));
181 }
182 pub fn push_highlighted<S: Into<String>>(&mut self, t: S) {
183 self.0.push(StringPart::highlighted(t));
184 }
185 pub fn push<S: Into<String>>(&mut self, t: S, highlight: bool) {
186 if highlight {
187 self.push_highlighted(t);
188 } else {
189 self.push_normal(t);
190 }
191 }
192 pub fn normal<S: Into<String>>(t: S) -> DiagStyledString {
193 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)])
194 }
195
196 pub fn highlighted<S: Into<String>>(t: S) -> DiagStyledString {
197 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)])
198 }
199
200 pub fn content(&self) -> String {
201 self.0.iter().map(|x| x.content.as_str()).collect::<String>()
202 }
203}
204
205#[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)]
206pub struct StringPart {
207 content: String,
208 style: Style,
209}
210
211impl StringPart {
212 pub fn normal<S: Into<String>>(content: S) -> StringPart {
213 StringPart { content: content.into(), style: Style::NoStyle }
214 }
215
216 pub fn highlighted<S: Into<String>>(content: S) -> StringPart {
217 StringPart { content: content.into(), style: Style::Highlight }
218 }
219}
220
221#[must_use]
226#[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)]
227pub struct DiagInner {
228 pub(crate) level: Level,
231
232 pub messages: Vec<(DiagMessage, Style)>,
233 pub code: Option<ErrCode>,
234 pub lint_id: Option<LintExpectationId>,
235 pub span: MultiSpan,
236 pub children: Vec<Subdiag>,
237 pub suggestions: Suggestions,
238 pub args: DiagArgMap,
239
240 pub sort_span: Span,
244
245 pub is_lint: Option<IsLint>,
246
247 pub long_ty_path: Option<PathBuf>,
248 pub emitted_at: DiagLocation,
251}
252
253impl DiagInner {
254 #[track_caller]
255 pub fn new<M: Into<DiagMessage>>(level: Level, message: M) -> Self {
256 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)])
257 }
258
259 #[track_caller]
260 pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self {
261 DiagInner {
262 level,
263 lint_id: None,
264 messages,
265 code: None,
266 span: MultiSpan::new(),
267 children: ::alloc::vec::Vec::new()vec![],
268 suggestions: Suggestions::Enabled(::alloc::vec::Vec::new()vec![]),
269 args: Default::default(),
270 sort_span: DUMMY_SP,
271 is_lint: None,
272 long_ty_path: None,
273 emitted_at: DiagLocation::caller(),
274 }
275 }
276
277 #[inline(always)]
278 pub fn level(&self) -> Level {
279 self.level
280 }
281
282 pub fn is_error(&self) -> bool {
283 match self.level {
284 Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true,
285
286 Level::ForceWarning
287 | Level::Warning
288 | Level::Note
289 | Level::OnceNote
290 | Level::Help
291 | Level::OnceHelp
292 | Level::FailureNote
293 | Level::Allow
294 | Level::Expect => false,
295 }
296 }
297
298 pub(crate) fn has_future_breakage(&self) -> bool {
300 #[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, .. }))
301 }
302
303 pub(crate) fn is_force_warn(&self) -> bool {
304 match self.level {
305 Level::ForceWarning => {
306 if !self.is_lint.is_some() {
::core::panicking::panic("assertion failed: self.is_lint.is_some()")
};assert!(self.is_lint.is_some());
307 true
308 }
309 _ => false,
310 }
311 }
312
313 pub(crate) fn sub(&mut self, level: Level, message: impl Into<DiagMessage>, span: MultiSpan) {
314 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 };
315 self.children.push(sub);
316 }
317
318 pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) {
319 let name = name.into();
320 let value = arg.into_diag_arg(&mut self.long_ty_path);
321 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!(
323 !self.args.contains_key(&name) || self.args.get(&name) == Some(&value),
324 "arg {} already exists",
325 name
326 );
327 self.args.insert(name, value);
328 }
329
330 pub fn remove_arg(&mut self, name: &str) {
331 self.args.swap_remove(name);
332 }
333
334 pub fn emitted_at_sub_diag(&self) -> Subdiag {
335 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);
336 Subdiag {
337 level: crate::Level::Note,
338 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)],
339 span: MultiSpan::new(),
340 }
341 }
342
343 fn keys(
345 &self,
346 ) -> (
347 &Level,
348 &[(DiagMessage, Style)],
349 &Option<ErrCode>,
350 &MultiSpan,
351 &[Subdiag],
352 &Suggestions,
353 Vec<(&DiagArgName, &DiagArgValue)>,
354 &Option<IsLint>,
355 ) {
356 (
357 &self.level,
358 &self.messages,
359 &self.code,
360 &self.span,
361 &self.children,
362 &self.suggestions,
363 self.args.iter().collect(),
364 &self.is_lint,
366 )
368 }
369}
370
371impl Hash for DiagInner {
372 fn hash<H>(&self, state: &mut H)
373 where
374 H: Hasher,
375 {
376 self.keys().hash(state);
377 }
378}
379
380impl PartialEq for DiagInner {
381 fn eq(&self, other: &Self) -> bool {
382 self.keys() == other.keys()
383 }
384}
385
386#[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)]
389pub struct Subdiag {
390 pub level: Level,
391 pub messages: Vec<(DiagMessage, Style)>,
392 pub span: MultiSpan,
393}
394
395#[must_use]
408pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> {
409 pub dcx: DiagCtxtHandle<'a>,
410
411 diag: Option<Box<DiagInner>>,
421
422 _marker: PhantomData<G>,
423}
424
425impl<G> !Clone for Diag<'_, G> {}
428
429const _: [(); 3 * size_of::<usize>()] =
[(); ::std::mem::size_of::<Diag<'_, ()>>()];rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * size_of::<usize>());
430
431impl<G: EmissionGuarantee> Deref for Diag<'_, G> {
432 type Target = DiagInner;
433
434 fn deref(&self) -> &DiagInner {
435 self.diag.as_ref().unwrap()
436 }
437}
438
439impl<G: EmissionGuarantee> DerefMut for Diag<'_, G> {
440 fn deref_mut(&mut self) -> &mut DiagInner {
441 self.diag.as_mut().unwrap()
442 }
443}
444
445impl<G: EmissionGuarantee> Debug for Diag<'_, G> {
446 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
447 self.diag.fmt(f)
448 }
449}
450
451macro_rules! with_fn {
470 {
471 $with_f:ident,
472 $(#[$attrs:meta])*
473 pub fn $f:ident(&mut $self:ident, $($name:ident: $ty:ty),* $(,)?) -> &mut Self {
474 $($body:tt)*
475 }
476 } => {
477 $(#[$attrs])*
479 #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
480 pub fn $f(&mut $self, $($name: $ty),*) -> &mut Self {
481 $($body)*
482 }
483
484 $(#[$attrs])*
486 #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
487 pub fn $with_f(mut $self, $($name: $ty),*) -> Self {
488 $self.$f($($name),*);
489 $self
490 }
491 };
492}
493
494impl<'a, G: EmissionGuarantee> Diag<'a, G> {
495 #[track_caller]
496 pub fn new(dcx: DiagCtxtHandle<'a>, level: Level, message: impl Into<DiagMessage>) -> Self {
497 Self::new_diagnostic(dcx, DiagInner::new(level, message))
498 }
499
500 pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_, G> {
502 Diag { dcx, diag: self.diag.take(), _marker: PhantomData }
503 }
504
505 #[track_caller]
507 pub(crate) fn new_diagnostic(dcx: DiagCtxtHandle<'a>, diag: DiagInner) -> Self {
508 {
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:508",
"rustc_errors::diagnostic", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/diagnostic.rs"),
::tracing_core::__macro_support::Option::Some(508u32),
::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");
509 Self { dcx, diag: Some(Box::new(diag)), _marker: PhantomData }
510 }
511
512 #[track_caller]
523 pub fn downgrade_to_delayed_bug(&mut self) {
524 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!(
525 matches!(self.level, Level::Error | Level::DelayedBug),
526 "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
527 self.level
528 );
529 self.level = Level::DelayedBug;
530 }
531
532 #[track_caller]
540 pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> {
541 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!(
542 matches!(self.level, Level::Error),
543 "upgrade_to_fatal: cannot upgrade {:?} to Fatal: not an error",
544 self.level
545 );
546 self.level = Level::Fatal;
547
548 let diag = self.diag.take();
551 Diag { dcx: self.dcx, diag, _marker: PhantomData }
552 }
553
554 "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,
555 pub fn span_label(&mut self, span: Span, label: impl Into<DiagMessage>) -> &mut Self {
568 self.span.push_span_label(span, label.into());
569 self
570 } }
571
572 "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,
573 pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
576 for span in spans {
577 self.span_label(span, label.to_string());
578 }
579 self
580 } }
581
582 pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self {
583 let before = self.span.clone();
584 self.span(after);
585 for span_label in before.span_labels() {
586 if let Some(label) = span_label.label {
587 if span_label.is_primary && keep_label {
588 self.span.push_span_label(after, label);
589 } else {
590 self.span.push_span_label(span_label.span, label);
591 }
592 }
593 }
594 self
595 }
596
597 pub fn note_expected_found(
598 &mut self,
599 expected_label: &str,
600 expected: DiagStyledString,
601 found_label: &str,
602 found: DiagStyledString,
603 ) -> &mut Self {
604 self.note_expected_found_extra(
605 expected_label,
606 expected,
607 found_label,
608 found,
609 DiagStyledString::normal(""),
610 DiagStyledString::normal(""),
611 )
612 }
613
614 pub fn note_expected_found_extra(
615 &mut self,
616 expected_label: &str,
617 expected: DiagStyledString,
618 found_label: &str,
619 found: DiagStyledString,
620 expected_extra: DiagStyledString,
621 found_extra: DiagStyledString,
622 ) -> &mut Self {
623 let expected_label = expected_label.to_string();
624 let expected_label = if expected_label.is_empty() {
625 "expected".to_string()
626 } else {
627 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected {0}", expected_label))
})format!("expected {expected_label}")
628 };
629 let found_label = found_label.to_string();
630 let found_label = if found_label.is_empty() {
631 "found".to_string()
632 } else {
633 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("found {0}", found_label))
})format!("found {found_label}")
634 };
635 let (found_padding, expected_padding) = if expected_label.len() > found_label.len() {
636 (expected_label.len() - found_label.len(), 0)
637 } else {
638 (0, found_label.len() - expected_label.len())
639 };
640 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!(
641 "{}{} `",
642 " ".repeat(expected_padding),
643 expected_label
644 ))];
645 msg.extend(expected.0);
646 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
647 msg.extend(expected_extra.0);
648 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("\n")) })format!("\n")));
649 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)));
650 msg.extend(found.0);
651 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
652 msg.extend(found_extra.0);
653
654 self.highlighted_note(msg);
656 self
657 }
658
659 pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
660 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![
661 StringPart::normal(format!("`{name}` from trait: `")),
662 StringPart::highlighted(signature),
663 StringPart::normal("`"),
664 ]);
665 self
666 }
667
668 "See [`Diag::note()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::note()`]."
mut self
msg
Self
self.note(msg);
self;with_fn! { with_note,
669 pub fn note(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
671 self.sub(Level::Note, msg, MultiSpan::new());
672 self
673 } }
674
675 pub fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self {
676 self.sub_with_highlights(Level::Note, msg, MultiSpan::new());
677 self
678 }
679
680 pub fn highlighted_span_note(
681 &mut self,
682 span: impl Into<MultiSpan>,
683 msg: Vec<StringPart>,
684 ) -> &mut Self {
685 self.sub_with_highlights(Level::Note, msg, span.into());
686 self
687 }
688
689 pub fn note_once(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
691 self.sub(Level::OnceNote, msg, MultiSpan::new());
692 self
693 }
694
695 "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,
696 pub fn span_note(
699 &mut self,
700 sp: impl Into<MultiSpan>,
701 msg: impl Into<DiagMessage>,
702 ) -> &mut Self {
703 self.sub(Level::Note, msg, sp.into());
704 self
705 } }
706
707 pub fn span_note_once<S: Into<MultiSpan>>(
710 &mut self,
711 sp: S,
712 msg: impl Into<DiagMessage>,
713 ) -> &mut Self {
714 self.sub(Level::OnceNote, msg, sp.into());
715 self
716 }
717
718 "See [`Diag::warn()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::warn()`]."
mut self
msg
Self
self.warn(msg);
self;with_fn! { with_warn,
719 pub fn warn(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
721 self.sub(Level::Warning, msg, MultiSpan::new());
722 self
723 } }
724
725 pub fn span_warn<S: Into<MultiSpan>>(
728 &mut self,
729 sp: S,
730 msg: impl Into<DiagMessage>,
731 ) -> &mut Self {
732 self.sub(Level::Warning, msg, sp.into());
733 self
734 }
735
736 "See [`Diag::help()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::help()`]."
mut self
msg
Self
self.help(msg);
self;with_fn! { with_help,
737 pub fn help(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
739 self.sub(Level::Help, msg, MultiSpan::new());
740 self
741 } }
742
743 pub fn help_once(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
745 self.sub(Level::OnceHelp, msg, MultiSpan::new());
746 self
747 }
748
749 pub fn highlighted_help(&mut self, msg: Vec<StringPart>) -> &mut Self {
751 self.sub_with_highlights(Level::Help, msg, MultiSpan::new());
752 self
753 }
754
755 pub fn highlighted_span_help(
757 &mut self,
758 span: impl Into<MultiSpan>,
759 msg: Vec<StringPart>,
760 ) -> &mut Self {
761 self.sub_with_highlights(Level::Help, msg, span.into());
762 self
763 }
764
765 "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,
766 pub fn span_help(
769 &mut self,
770 sp: impl Into<MultiSpan>,
771 msg: impl Into<DiagMessage>,
772 ) -> &mut Self {
773 self.sub(Level::Help, msg, sp.into());
774 self
775 } }
776
777 pub fn disable_suggestions(&mut self) -> &mut Self {
781 self.suggestions = Suggestions::Disabled;
782 self
783 }
784
785 pub fn seal_suggestions(&mut self) -> &mut Self {
790 if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
791 let suggestions_slice = std::mem::take(suggestions).into_boxed_slice();
792 self.suggestions = Suggestions::Sealed(suggestions_slice);
793 }
794 self
795 }
796
797 fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
802 for subst in &suggestion.substitutions {
803 for part in &subst.parts {
804 let span = part.span;
805 let call_site = span.ctxt().outer_expn_data().call_site;
806 if span.in_derive_expansion() && span.overlaps_or_adjacent(call_site) {
807 return;
809 }
810 }
811 }
812
813 if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
814 suggestions.push(suggestion);
815 }
816 }
817
818 "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,
819 pub fn multipart_suggestion(
822 &mut self,
823 msg: impl Into<DiagMessage>,
824 suggestion: Vec<(Span, String)>,
825 applicability: Applicability,
826 ) -> &mut Self {
827 self.multipart_suggestion_with_style(
828 msg,
829 suggestion,
830 applicability,
831 SuggestionStyle::ShowAlways,
832 )
833 } }
834
835 pub fn multipart_suggestion_with_style(
837 &mut self,
838 msg: impl Into<DiagMessage>,
839 mut suggestion: Vec<(Span, String)>,
840 applicability: Applicability,
841 style: SuggestionStyle,
842 ) -> &mut Self {
843 let mut seen = crate::FxHashSet::default();
844 suggestion.retain(|(span, msg)| seen.insert((span.lo(), span.hi(), msg.clone())));
845
846 let parts = suggestion
847 .into_iter()
848 .map(|(span, snippet)| SubstitutionPart { snippet, span })
849 .collect::<Vec<_>>();
850
851 if !!parts.is_empty() {
::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
852 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!(
853 parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
854 None,
855 "Span must not be empty and have no suggestion",
856 );
857 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!(
858 parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
859 None,
860 "suggestion must not have overlapping parts",
861 );
862
863 self.push_suggestion(CodeSuggestion {
864 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 }],
865 msg: msg.into(),
866 style,
867 applicability,
868 });
869 self
870 }
871
872 pub fn tool_only_multipart_suggestion(
879 &mut self,
880 msg: impl Into<DiagMessage>,
881 suggestion: Vec<(Span, String)>,
882 applicability: Applicability,
883 ) -> &mut Self {
884 self.multipart_suggestion_with_style(
885 msg,
886 suggestion,
887 applicability,
888 SuggestionStyle::CompletelyHidden,
889 )
890 }
891
892 "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,
893 pub fn span_suggestion(
911 &mut self,
912 sp: Span,
913 msg: impl Into<DiagMessage>,
914 suggestion: impl ToString,
915 applicability: Applicability,
916 ) -> &mut Self {
917 self.span_suggestion_with_style(
918 sp,
919 msg,
920 suggestion,
921 applicability,
922 SuggestionStyle::ShowCode,
923 );
924 self
925 } }
926
927 "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,
928 pub fn span_suggestion_with_style(
930 &mut self,
931 sp: Span,
932 msg: impl Into<DiagMessage>,
933 suggestion: impl ToString,
934 applicability: Applicability,
935 style: SuggestionStyle,
936 ) -> &mut Self {
937 debug_assert!(
938 !(sp.is_empty() && suggestion.to_string().is_empty()),
939 "Span must not be empty and have no suggestion"
940 );
941 self.push_suggestion(CodeSuggestion {
942 substitutions: vec![Substitution {
943 parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
944 }],
945 msg: msg.into(),
946 style,
947 applicability,
948 });
949 self
950 } }
951
952 "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,
953 pub fn span_suggestion_verbose(
955 &mut self,
956 sp: Span,
957 msg: impl Into<DiagMessage>,
958 suggestion: impl ToString,
959 applicability: Applicability,
960 ) -> &mut Self {
961 self.span_suggestion_with_style(
962 sp,
963 msg,
964 suggestion,
965 applicability,
966 SuggestionStyle::ShowAlways,
967 );
968 self
969 } }
970
971 "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,
972 pub fn span_suggestions(
975 &mut self,
976 sp: Span,
977 msg: impl Into<DiagMessage>,
978 suggestions: impl IntoIterator<Item = String>,
979 applicability: Applicability,
980 ) -> &mut Self {
981 self.span_suggestions_with_style(
982 sp,
983 msg,
984 suggestions,
985 applicability,
986 SuggestionStyle::ShowAlways,
987 )
988 } }
989
990 pub fn span_suggestions_with_style(
991 &mut self,
992 sp: Span,
993 msg: impl Into<DiagMessage>,
994 suggestions: impl IntoIterator<Item = String>,
995 applicability: Applicability,
996 style: SuggestionStyle,
997 ) -> &mut Self {
998 let substitutions = suggestions
999 .into_iter()
1000 .map(|snippet| {
1001 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!(
1002 !(sp.is_empty() && snippet.is_empty()),
1003 "Span `{sp:?}` must not be empty and have no suggestion"
1004 );
1005 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 }] }
1006 })
1007 .collect();
1008 self.push_suggestion(CodeSuggestion {
1009 substitutions,
1010 msg: msg.into(),
1011 style,
1012 applicability,
1013 });
1014 self
1015 }
1016
1017 pub fn multipart_suggestions(
1021 &mut self,
1022 msg: impl Into<DiagMessage>,
1023 suggestions: impl IntoIterator<Item = Vec<(Span, String)>>,
1024 applicability: Applicability,
1025 ) -> &mut Self {
1026 let substitutions = suggestions
1027 .into_iter()
1028 .map(|sugg| {
1029 let mut parts = sugg
1030 .into_iter()
1031 .map(|(span, snippet)| SubstitutionPart { snippet, span })
1032 .collect::<Vec<_>>();
1033
1034 parts.sort_unstable_by_key(|part| part.span);
1035
1036 if !!parts.is_empty() {
::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
1037 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!(
1038 parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
1039 None,
1040 "Span must not be empty and have no suggestion",
1041 );
1042 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!(
1043 parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
1044 None,
1045 "suggestion must not have overlapping parts",
1046 );
1047
1048 Substitution { parts }
1049 })
1050 .collect();
1051
1052 self.push_suggestion(CodeSuggestion {
1053 substitutions,
1054 msg: msg.into(),
1055 style: SuggestionStyle::ShowAlways,
1056 applicability,
1057 });
1058 self
1059 }
1060
1061 "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,
1062 pub fn span_suggestion_short(
1067 &mut self,
1068 sp: Span,
1069 msg: impl Into<DiagMessage>,
1070 suggestion: impl ToString,
1071 applicability: Applicability,
1072 ) -> &mut Self {
1073 self.span_suggestion_with_style(
1074 sp,
1075 msg,
1076 suggestion,
1077 applicability,
1078 SuggestionStyle::HideCodeInline,
1079 );
1080 self
1081 } }
1082
1083 pub fn span_suggestion_hidden(
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::HideCodeAlways,
1102 );
1103 self
1104 }
1105
1106 "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,
1107 pub fn tool_only_span_suggestion(
1112 &mut self,
1113 sp: Span,
1114 msg: impl Into<DiagMessage>,
1115 suggestion: impl ToString,
1116 applicability: Applicability,
1117 ) -> &mut Self {
1118 self.span_suggestion_with_style(
1119 sp,
1120 msg,
1121 suggestion,
1122 applicability,
1123 SuggestionStyle::CompletelyHidden,
1124 );
1125 self
1126 } }
1127
1128 pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self {
1133 subdiagnostic.add_to_diag(self);
1134 self
1135 }
1136
1137 "See [`Diag::span()`]."
&mut Self
self
sp
&mut Self
"See [`Diag::span()`]."
mut self
sp
Self
self.span(sp);
self;with_fn! { with_span,
1138 pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self {
1140 self.span = sp.into();
1141 if let Some(span) = self.span.primary_span() {
1142 self.sort_span = span;
1143 }
1144 self
1145 } }
1146
1147 pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
1148 self.is_lint = Some(IsLint { name, has_future_breakage });
1149 self
1150 }
1151
1152 "See [`Diag::code()`]."
&mut Self
self
code
&mut Self
"See [`Diag::code()`]."
mut self
code
Self
self.code(code);
self;with_fn! { with_code,
1153 pub fn code(&mut self, code: ErrCode) -> &mut Self {
1155 self.code = Some(code);
1156 self
1157 } }
1158
1159 "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,
1160 pub fn lint_id(
1162 &mut self,
1163 id: LintExpectationId,
1164 ) -> &mut Self {
1165 self.lint_id = Some(id);
1166 self
1167 } }
1168
1169 "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,
1170 pub fn primary_message(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
1172 self.messages[0] = (msg.into(), Style::NoStyle);
1173 self
1174 } }
1175
1176 "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,
1177 pub fn arg(
1179 &mut self,
1180 name: impl Into<DiagArgName>,
1181 arg: impl IntoDiagArg,
1182 ) -> &mut Self {
1183 self.deref_mut().arg(name, arg);
1184 self
1185 } }
1186
1187 pub fn sub(&mut self, level: Level, message: impl Into<DiagMessage>, span: MultiSpan) {
1192 self.deref_mut().sub(level, message, span);
1193 }
1194
1195 fn sub_with_highlights(&mut self, level: Level, messages: Vec<StringPart>, span: MultiSpan) {
1198 let messages = messages.into_iter().map(|m| (m.content.into(), m.style)).collect();
1199 let sub = Subdiag { level, messages, span };
1200 self.children.push(sub);
1201 }
1202
1203 fn take_diag(&mut self) -> DiagInner {
1207 if let Some(path) = &self.long_ty_path {
1208 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!(
1209 "the full name for the type has been written to '{}'",
1210 path.display()
1211 ));
1212 self.note("consider using `--verbose` to print the full type name to the console");
1213 }
1214 *self.diag.take().unwrap()
1215 }
1216
1217 pub fn long_ty_path(&mut self) -> &mut Option<PathBuf> {
1235 &mut self.long_ty_path
1236 }
1237
1238 pub fn with_long_ty_path(mut self, long_ty_path: Option<PathBuf>) -> Self {
1239 self.long_ty_path = long_ty_path;
1240 self
1241 }
1242
1243 fn emit_producing_nothing(mut self) {
1245 let diag = self.take_diag();
1246 self.dcx.emit_diagnostic(diag);
1247 }
1248
1249 fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed {
1251 let diag = self.take_diag();
1252
1253 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!(
1262 matches!(diag.level, Level::Error | Level::DelayedBug),
1263 "invalid diagnostic level ({:?})",
1264 diag.level,
1265 );
1266
1267 let guar = self.dcx.emit_diagnostic(diag);
1268 guar.unwrap()
1269 }
1270
1271 #[track_caller]
1273 pub fn emit(self) -> G::EmitResult {
1274 G::emit_producing_guarantee(self)
1275 }
1276
1277 #[track_caller]
1282 pub fn emit_unless_delay(mut self, delay: bool) -> G::EmitResult {
1283 if delay {
1284 self.downgrade_to_delayed_bug();
1285 }
1286 self.emit()
1287 }
1288
1289 pub fn cancel(mut self) {
1292 self.diag = None;
1293 drop(self);
1294 }
1295
1296 pub fn cancel_into_message(self) -> Option<String> {
1298 let s = self.diag.as_ref()?.messages.get(0)?.0.as_str().map(ToString::to_string);
1299 self.cancel();
1300 s
1301 }
1302
1303 pub fn stash(mut self, span: Span, key: StashKey) -> Option<ErrorGuaranteed> {
1305 let diag = self.take_diag();
1306 self.dcx.stash_diagnostic(span, key, diag)
1307 }
1308
1309 #[track_caller]
1320 pub fn delay_as_bug(mut self) -> G::EmitResult {
1321 self.downgrade_to_delayed_bug();
1322 self.emit()
1323 }
1324}
1325
1326impl<G: EmissionGuarantee> Drop for Diag<'_, G> {
1329 fn drop(&mut self) {
1330 match self.diag.take() {
1331 Some(diag) if !panicking() => {
1332 self.dcx.emit_diagnostic(DiagInner::new(
1333 Level::Bug,
1334 DiagMessage::from("the following error was constructed but not emitted"),
1335 ));
1336 self.dcx.emit_diagnostic(*diag);
1337 {
::core::panicking::panic_fmt(format_args!("error was constructed but not emitted"));
};panic!("error was constructed but not emitted");
1338 }
1339 _ => {}
1340 }
1341 }
1342}
1343
1344#[macro_export]
1345macro_rules! struct_span_code_err {
1346 ($dcx:expr, $span:expr, $code:expr, $($message:tt)*) => ({
1347 $dcx.struct_span_err($span, format!($($message)*)).with_code($code)
1348 })
1349}