1use std::borrow::Cow;
2use std::fmt::{self, Debug};
3use std::hash::{Hash, Hasher};
4use std::marker::PhantomData;
5use std::ops::{Deref, DerefMut};
6use std::panic;
7use std::path::PathBuf;
8use std::thread::panicking;
9
10use rustc_data_structures::fx::FxIndexMap;
11use rustc_error_messages::{DiagArgName, DiagArgValue, IntoDiagArg};
12use rustc_lint_defs::{Applicability, LintExpectationId};
13use rustc_macros::{Decodable, Encodable};
14use rustc_span::source_map::Spanned;
15use rustc_span::{DUMMY_SP, Span, Symbol};
16use tracing::debug;
17
18use crate::snippet::Style;
19use crate::{
20 CodeSuggestion, DiagCtxtHandle, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level,
21 MultiSpan, StashKey, SubdiagMessage, Substitution, SubstitutionPart, SuggestionStyle,
22 Suggestions,
23};
24
25pub type DiagArgMap = FxIndexMap<DiagArgName, DiagArgValue>;
26
27pub trait EmissionGuarantee: Sized {
30 type EmitResult = Self;
33
34 #[track_caller]
38 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult;
39}
40
41impl EmissionGuarantee for ErrorGuaranteed {
42 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
43 diag.emit_producing_error_guaranteed()
44 }
45}
46
47impl EmissionGuarantee for () {
48 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
49 diag.emit_producing_nothing();
50 }
51}
52
53#[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)]
56pub struct BugAbort;
57
58impl EmissionGuarantee for BugAbort {
59 type EmitResult = !;
60
61 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
62 diag.emit_producing_nothing();
63 panic::panic_any(ExplicitBug);
64 }
65}
66
67#[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)]
70pub struct FatalAbort;
71
72impl EmissionGuarantee for FatalAbort {
73 type EmitResult = !;
74
75 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
76 diag.emit_producing_nothing();
77 crate::FatalError.raise()
78 }
79}
80
81impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
82 fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
83 diag.emit_producing_nothing();
84 rustc_span::fatal_error::FatalError
85 }
86}
87
88#[rustc_diagnostic_item = "Diagnostic"]
110pub trait Diagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> {
111 #[must_use]
113 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G>;
114}
115
116impl<'a, T, G> Diagnostic<'a, G> for Spanned<T>
117where
118 T: Diagnostic<'a, G>,
119 G: EmissionGuarantee,
120{
121 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
122 self.node.into_diag(dcx, level).with_span(self.span)
123 }
124}
125
126#[rustc_diagnostic_item = "Subdiagnostic"]
129pub trait Subdiagnostic
130where
131 Self: Sized,
132{
133 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
135}
136
137#[rustc_diagnostic_item = "LintDiagnostic"]
140pub trait LintDiagnostic<'a, G: EmissionGuarantee> {
141 fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>);
143}
144
145pub trait LintDiagnosticBox<'a, G: EmissionGuarantee> {
146 fn decorate_lint_box<'b>(self: Box<Self>, diag: &'b mut Diag<'a, G>);
147}
148
149impl<'a, G: EmissionGuarantee, D: LintDiagnostic<'a, G>> LintDiagnosticBox<'a, G> for D {
150 fn decorate_lint_box<'b>(self: Box<Self>, diag: &'b mut Diag<'a, G>) {
151 self.decorate_lint(diag);
152 }
153}
154
155#[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)]
156pub(crate) struct DiagLocation {
157 file: Cow<'static, str>,
158 line: u32,
159 col: u32,
160}
161
162impl DiagLocation {
163 #[track_caller]
164 fn caller() -> Self {
165 let loc = panic::Location::caller();
166 DiagLocation { file: loc.file().into(), line: loc.line(), col: loc.column() }
167 }
168}
169
170impl fmt::Display for DiagLocation {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 f.write_fmt(format_args!("{0}:{1}:{2}", self.file, self.line, self.col))write!(f, "{}:{}:{}", self.file, self.line, self.col)
173 }
174}
175
176#[derive(#[automatically_derived]
impl ::core::clone::Clone for IsLint {
#[inline]
fn clone(&self) -> IsLint {
IsLint {
name: ::core::clone::Clone::clone(&self.name),
has_future_breakage: ::core::clone::Clone::clone(&self.has_future_breakage),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for IsLint {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "IsLint",
"name", &self.name, "has_future_breakage",
&&self.has_future_breakage)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for IsLint {
#[inline]
fn eq(&self, other: &IsLint) -> bool {
self.has_future_breakage == other.has_future_breakage &&
self.name == other.name
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for IsLint {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<bool>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for IsLint {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
::core::hash::Hash::hash(&self.name, state);
::core::hash::Hash::hash(&self.has_future_breakage, state)
}
}Hash, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for IsLint {
fn encode(&self, __encoder: &mut __E) {
match *self {
IsLint {
name: ref __binding_0, has_future_breakage: ref __binding_1
} => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for IsLint {
fn decode(__decoder: &mut __D) -> Self {
IsLint {
name: ::rustc_serialize::Decodable::decode(__decoder),
has_future_breakage: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
177pub struct IsLint {
178 pub(crate) name: String,
180 has_future_breakage: bool,
182}
183
184#[derive(#[automatically_derived]
impl ::core::fmt::Debug for DiagStyledString {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"DiagStyledString", &&self.0)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for DiagStyledString {
#[inline]
fn eq(&self, other: &DiagStyledString) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DiagStyledString {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<Vec<StringPart>>;
}
}Eq)]
185pub struct DiagStyledString(pub Vec<StringPart>);
186
187impl DiagStyledString {
188 pub fn new() -> DiagStyledString {
189 DiagStyledString(::alloc::vec::Vec::new()vec![])
190 }
191 pub fn push_normal<S: Into<String>>(&mut self, t: S) {
192 self.0.push(StringPart::normal(t));
193 }
194 pub fn push_highlighted<S: Into<String>>(&mut self, t: S) {
195 self.0.push(StringPart::highlighted(t));
196 }
197 pub fn push<S: Into<String>>(&mut self, t: S, highlight: bool) {
198 if highlight {
199 self.push_highlighted(t);
200 } else {
201 self.push_normal(t);
202 }
203 }
204 pub fn normal<S: Into<String>>(t: S) -> DiagStyledString {
205 DiagStyledString(<[_]>::into_vec(::alloc::boxed::box_new([StringPart::normal(t)]))vec![StringPart::normal(t)])
206 }
207
208 pub fn highlighted<S: Into<String>>(t: S) -> DiagStyledString {
209 DiagStyledString(<[_]>::into_vec(::alloc::boxed::box_new([StringPart::highlighted(t)]))vec![StringPart::highlighted(t)])
210 }
211
212 pub fn content(&self) -> String {
213 self.0.iter().map(|x| x.content.as_str()).collect::<String>()
214 }
215}
216
217#[derive(#[automatically_derived]
impl ::core::fmt::Debug for StringPart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "StringPart",
"content", &self.content, "style", &&self.style)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for StringPart {
#[inline]
fn eq(&self, other: &StringPart) -> bool {
self.content == other.content && self.style == other.style
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for StringPart {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<Style>;
}
}Eq)]
218pub struct StringPart {
219 content: String,
220 style: Style,
221}
222
223impl StringPart {
224 pub fn normal<S: Into<String>>(content: S) -> StringPart {
225 StringPart { content: content.into(), style: Style::NoStyle }
226 }
227
228 pub fn highlighted<S: Into<String>>(content: S) -> StringPart {
229 StringPart { content: content.into(), style: Style::Highlight }
230 }
231}
232
233#[must_use]
238#[derive(#[automatically_derived]
impl ::core::clone::Clone for DiagInner {
#[inline]
fn clone(&self) -> DiagInner {
DiagInner {
level: ::core::clone::Clone::clone(&self.level),
messages: ::core::clone::Clone::clone(&self.messages),
code: ::core::clone::Clone::clone(&self.code),
lint_id: ::core::clone::Clone::clone(&self.lint_id),
span: ::core::clone::Clone::clone(&self.span),
children: ::core::clone::Clone::clone(&self.children),
suggestions: ::core::clone::Clone::clone(&self.suggestions),
args: ::core::clone::Clone::clone(&self.args),
reserved_args: ::core::clone::Clone::clone(&self.reserved_args),
sort_span: ::core::clone::Clone::clone(&self.sort_span),
is_lint: ::core::clone::Clone::clone(&self.is_lint),
long_ty_path: ::core::clone::Clone::clone(&self.long_ty_path),
emitted_at: ::core::clone::Clone::clone(&self.emitted_at),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for DiagInner {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["level", "messages", "code", "lint_id", "span", "children",
"suggestions", "args", "reserved_args", "sort_span",
"is_lint", "long_ty_path", "emitted_at"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.level, &self.messages, &self.code, &self.lint_id,
&self.span, &self.children, &self.suggestions, &self.args,
&self.reserved_args, &self.sort_span, &self.is_lint,
&self.long_ty_path, &&self.emitted_at];
::core::fmt::Formatter::debug_struct_fields_finish(f, "DiagInner",
names, values)
}
}Debug, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for DiagInner {
fn encode(&self, __encoder: &mut __E) {
match *self {
DiagInner {
level: ref __binding_0,
messages: ref __binding_1,
code: ref __binding_2,
lint_id: ref __binding_3,
span: ref __binding_4,
children: ref __binding_5,
suggestions: ref __binding_6,
args: ref __binding_7,
reserved_args: ref __binding_8,
sort_span: ref __binding_9,
is_lint: ref __binding_10,
long_ty_path: ref __binding_11,
emitted_at: ref __binding_12 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_2,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_3,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_4,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_5,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_6,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_7,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_8,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_9,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_10,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_11,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_12,
__encoder);
}
}
}
}
};Encodable, const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for DiagInner {
fn decode(__decoder: &mut __D) -> Self {
DiagInner {
level: ::rustc_serialize::Decodable::decode(__decoder),
messages: ::rustc_serialize::Decodable::decode(__decoder),
code: ::rustc_serialize::Decodable::decode(__decoder),
lint_id: ::rustc_serialize::Decodable::decode(__decoder),
span: ::rustc_serialize::Decodable::decode(__decoder),
children: ::rustc_serialize::Decodable::decode(__decoder),
suggestions: ::rustc_serialize::Decodable::decode(__decoder),
args: ::rustc_serialize::Decodable::decode(__decoder),
reserved_args: ::rustc_serialize::Decodable::decode(__decoder),
sort_span: ::rustc_serialize::Decodable::decode(__decoder),
is_lint: ::rustc_serialize::Decodable::decode(__decoder),
long_ty_path: ::rustc_serialize::Decodable::decode(__decoder),
emitted_at: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};Decodable)]
239pub struct DiagInner {
240 pub(crate) level: Level,
243
244 pub messages: Vec<(DiagMessage, Style)>,
245 pub code: Option<ErrCode>,
246 pub lint_id: Option<LintExpectationId>,
247 pub span: MultiSpan,
248 pub children: Vec<Subdiag>,
249 pub suggestions: Suggestions,
250 pub args: DiagArgMap,
251
252 pub reserved_args: DiagArgMap,
254
255 pub sort_span: Span,
259
260 pub is_lint: Option<IsLint>,
261
262 pub long_ty_path: Option<PathBuf>,
263 pub(crate) emitted_at: DiagLocation,
266}
267
268impl DiagInner {
269 #[track_caller]
270 pub fn new<M: Into<DiagMessage>>(level: Level, message: M) -> Self {
271 DiagInner::new_with_messages(level, <[_]>::into_vec(::alloc::boxed::box_new([(message.into(), Style::NoStyle)]))vec![(message.into(), Style::NoStyle)])
272 }
273
274 #[track_caller]
275 pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self {
276 DiagInner {
277 level,
278 lint_id: None,
279 messages,
280 code: None,
281 span: MultiSpan::new(),
282 children: ::alloc::vec::Vec::new()vec![],
283 suggestions: Suggestions::Enabled(::alloc::vec::Vec::new()vec![]),
284 args: Default::default(),
285 reserved_args: Default::default(),
286 sort_span: DUMMY_SP,
287 is_lint: None,
288 long_ty_path: None,
289 emitted_at: DiagLocation::caller(),
290 }
291 }
292
293 #[inline(always)]
294 pub fn level(&self) -> Level {
295 self.level
296 }
297
298 pub fn is_error(&self) -> bool {
299 match self.level {
300 Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true,
301
302 Level::ForceWarning
303 | Level::Warning
304 | Level::Note
305 | Level::OnceNote
306 | Level::Help
307 | Level::OnceHelp
308 | Level::FailureNote
309 | Level::Allow
310 | Level::Expect => false,
311 }
312 }
313
314 pub(crate) fn has_future_breakage(&self) -> bool {
316 #[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, .. }))
317 }
318
319 pub(crate) fn is_force_warn(&self) -> bool {
320 match self.level {
321 Level::ForceWarning => {
322 if !self.is_lint.is_some() {
::core::panicking::panic("assertion failed: self.is_lint.is_some()")
};assert!(self.is_lint.is_some());
323 true
324 }
325 _ => false,
326 }
327 }
328
329 pub(crate) fn subdiagnostic_message_to_diagnostic_message(
331 &self,
332 attr: impl Into<SubdiagMessage>,
333 ) -> DiagMessage {
334 let msg =
335 self.messages.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages");
336 msg.with_subdiagnostic_message(attr.into())
337 }
338
339 pub(crate) fn sub(
340 &mut self,
341 level: Level,
342 message: impl Into<SubdiagMessage>,
343 span: MultiSpan,
344 ) {
345 let sub = Subdiag {
346 level,
347 messages: <[_]>::into_vec(::alloc::boxed::box_new([(self.subdiagnostic_message_to_diagnostic_message(message),
Style::NoStyle)]))vec![(
348 self.subdiagnostic_message_to_diagnostic_message(message),
349 Style::NoStyle,
350 )],
351 span,
352 };
353 self.children.push(sub);
354 }
355
356 pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) {
357 let name = name.into();
358 let value = arg.into_diag_arg(&mut self.long_ty_path);
359 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!(
361 !self.args.contains_key(&name) || self.args.get(&name) == Some(&value),
362 "arg {} already exists",
363 name
364 );
365 self.args.insert(name, value);
366 }
367
368 pub fn remove_arg(&mut self, name: &str) {
369 self.args.swap_remove(name);
370 }
371
372 pub fn store_args(&mut self) {
373 self.reserved_args = self.args.clone();
374 }
375
376 pub fn restore_args(&mut self) {
377 self.args = std::mem::take(&mut self.reserved_args);
378 }
379
380 pub fn emitted_at_sub_diag(&self) -> Subdiag {
381 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);
382 Subdiag {
383 level: crate::Level::Note,
384 messages: <[_]>::into_vec(::alloc::boxed::box_new([(DiagMessage::Str(Cow::Owned(track)),
Style::NoStyle)]))vec![(DiagMessage::Str(Cow::Owned(track)), Style::NoStyle)],
385 span: MultiSpan::new(),
386 }
387 }
388
389 fn keys(
391 &self,
392 ) -> (
393 &Level,
394 &[(DiagMessage, Style)],
395 &Option<ErrCode>,
396 &MultiSpan,
397 &[Subdiag],
398 &Suggestions,
399 Vec<(&DiagArgName, &DiagArgValue)>,
400 &Option<IsLint>,
401 ) {
402 (
403 &self.level,
404 &self.messages,
405 &self.code,
406 &self.span,
407 &self.children,
408 &self.suggestions,
409 self.args.iter().collect(),
410 &self.is_lint,
412 )
414 }
415}
416
417impl Hash for DiagInner {
418 fn hash<H>(&self, state: &mut H)
419 where
420 H: Hasher,
421 {
422 self.keys().hash(state);
423 }
424}
425
426impl PartialEq for DiagInner {
427 fn eq(&self, other: &Self) -> bool {
428 self.keys() == other.keys()
429 }
430}
431
432#[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)]
435pub struct Subdiag {
436 pub level: Level,
437 pub messages: Vec<(DiagMessage, Style)>,
438 pub span: MultiSpan,
439}
440
441#[must_use]
454pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> {
455 pub dcx: DiagCtxtHandle<'a>,
456
457 diag: Option<Box<DiagInner>>,
467
468 _marker: PhantomData<G>,
469}
470
471impl<G> !Clone for Diag<'_, G> {}
474
475const _: [(); 3 * size_of::<usize>()] =
[(); ::std::mem::size_of::<Diag<'_, ()>>()];rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * size_of::<usize>());
476
477impl<G: EmissionGuarantee> Deref for Diag<'_, G> {
478 type Target = DiagInner;
479
480 fn deref(&self) -> &DiagInner {
481 self.diag.as_ref().unwrap()
482 }
483}
484
485impl<G: EmissionGuarantee> DerefMut for Diag<'_, G> {
486 fn deref_mut(&mut self) -> &mut DiagInner {
487 self.diag.as_mut().unwrap()
488 }
489}
490
491impl<G: EmissionGuarantee> Debug for Diag<'_, G> {
492 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493 self.diag.fmt(f)
494 }
495}
496
497macro_rules! with_fn {
516 {
517 $with_f:ident,
518 $(#[$attrs:meta])*
519 pub fn $f:ident(&mut $self:ident, $($name:ident: $ty:ty),* $(,)?) -> &mut Self {
520 $($body:tt)*
521 }
522 } => {
523 $(#[$attrs])*
525 #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
526 pub fn $f(&mut $self, $($name: $ty),*) -> &mut Self {
527 $($body)*
528 }
529
530 $(#[$attrs])*
532 #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
533 pub fn $with_f(mut $self, $($name: $ty),*) -> Self {
534 $self.$f($($name),*);
535 $self
536 }
537 };
538}
539
540impl<'a, G: EmissionGuarantee> Diag<'a, G> {
541 #[rustc_lint_diagnostics]
542 #[track_caller]
543 pub fn new(dcx: DiagCtxtHandle<'a>, level: Level, message: impl Into<DiagMessage>) -> Self {
544 Self::new_diagnostic(dcx, DiagInner::new(level, message))
545 }
546
547 pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_, G> {
549 Diag { dcx, diag: self.diag.take(), _marker: PhantomData }
550 }
551
552 #[track_caller]
554 pub(crate) fn new_diagnostic(dcx: DiagCtxtHandle<'a>, diag: DiagInner) -> Self {
555 {
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:555",
"rustc_errors::diagnostic", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/diagnostic.rs"),
::tracing_core::__macro_support::Option::Some(555u32),
::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");
556 Self { dcx, diag: Some(Box::new(diag)), _marker: PhantomData }
557 }
558
559 #[rustc_lint_diagnostics]
570 #[track_caller]
571 pub fn downgrade_to_delayed_bug(&mut self) {
572 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!(
573 matches!(self.level, Level::Error | Level::DelayedBug),
574 "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
575 self.level
576 );
577 self.level = Level::DelayedBug;
578 }
579
580 #[rustc_lint_diagnostics]
588 #[track_caller]
589 pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> {
590 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!(
591 matches!(self.level, Level::Error),
592 "upgrade_to_fatal: cannot upgrade {:?} to Fatal: not an error",
593 self.level
594 );
595 self.level = Level::Fatal;
596
597 let diag = self.diag.take();
600 Diag { dcx: self.dcx, diag, _marker: PhantomData }
601 }
602
603 "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,
604 #[rustc_lint_diagnostics]
617 pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagMessage>) -> &mut Self {
618 let msg = self.subdiagnostic_message_to_diagnostic_message(label);
619 self.span.push_span_label(span, msg);
620 self
621 } }
622
623 "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,
624 #[rustc_lint_diagnostics]
627 pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
628 for span in spans {
629 self.span_label(span, label.to_string());
630 }
631 self
632 } }
633
634 #[rustc_lint_diagnostics]
635 pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self {
636 let before = self.span.clone();
637 self.span(after);
638 for span_label in before.span_labels() {
639 if let Some(label) = span_label.label {
640 if span_label.is_primary && keep_label {
641 self.span.push_span_label(after, label);
642 } else {
643 self.span.push_span_label(span_label.span, label);
644 }
645 }
646 }
647 self
648 }
649
650 #[rustc_lint_diagnostics]
651 pub fn note_expected_found(
652 &mut self,
653 expected_label: &str,
654 expected: DiagStyledString,
655 found_label: &str,
656 found: DiagStyledString,
657 ) -> &mut Self {
658 self.note_expected_found_extra(
659 expected_label,
660 expected,
661 found_label,
662 found,
663 DiagStyledString::normal(""),
664 DiagStyledString::normal(""),
665 )
666 }
667
668 #[rustc_lint_diagnostics]
669 pub fn note_expected_found_extra(
670 &mut self,
671 expected_label: &str,
672 expected: DiagStyledString,
673 found_label: &str,
674 found: DiagStyledString,
675 expected_extra: DiagStyledString,
676 found_extra: DiagStyledString,
677 ) -> &mut Self {
678 let expected_label = expected_label.to_string();
679 let expected_label = if expected_label.is_empty() {
680 "expected".to_string()
681 } else {
682 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected {0}", expected_label))
})format!("expected {expected_label}")
683 };
684 let found_label = found_label.to_string();
685 let found_label = if found_label.is_empty() {
686 "found".to_string()
687 } else {
688 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("found {0}", found_label))
})format!("found {found_label}")
689 };
690 let (found_padding, expected_padding) = if expected_label.len() > found_label.len() {
691 (expected_label.len() - found_label.len(), 0)
692 } else {
693 (0, found_label.len() - expected_label.len())
694 };
695 let mut msg = <[_]>::into_vec(::alloc::boxed::box_new([StringPart::normal(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1} `",
" ".repeat(expected_padding), expected_label))
}))]))vec![StringPart::normal(format!(
696 "{}{} `",
697 " ".repeat(expected_padding),
698 expected_label
699 ))];
700 msg.extend(expected.0);
701 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
702 msg.extend(expected_extra.0);
703 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("\n")) })format!("\n")));
704 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)));
705 msg.extend(found.0);
706 msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
707 msg.extend(found_extra.0);
708
709 self.highlighted_note(msg);
711 self
712 }
713
714 #[rustc_lint_diagnostics]
715 pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
716 self.highlighted_note(<[_]>::into_vec(::alloc::boxed::box_new([StringPart::normal(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` from trait: `",
name))
})), StringPart::highlighted(signature),
StringPart::normal("`")]))vec![
717 StringPart::normal(format!("`{name}` from trait: `")),
718 StringPart::highlighted(signature),
719 StringPart::normal("`"),
720 ]);
721 self
722 }
723
724 "See [`Diag::note()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::note()`]."
mut self
msg
Self
self.note(msg);
self;with_fn! { with_note,
725 #[rustc_lint_diagnostics]
727 pub fn note(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
728 self.sub(Level::Note, msg, MultiSpan::new());
729 self
730 } }
731
732 #[rustc_lint_diagnostics]
733 pub fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self {
734 self.sub_with_highlights(Level::Note, msg, MultiSpan::new());
735 self
736 }
737
738 #[rustc_lint_diagnostics]
739 pub fn highlighted_span_note(
740 &mut self,
741 span: impl Into<MultiSpan>,
742 msg: Vec<StringPart>,
743 ) -> &mut Self {
744 self.sub_with_highlights(Level::Note, msg, span.into());
745 self
746 }
747
748 #[rustc_lint_diagnostics]
750 pub fn note_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
751 self.sub(Level::OnceNote, msg, MultiSpan::new());
752 self
753 }
754
755 "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,
756 #[rustc_lint_diagnostics]
759 pub fn span_note(
760 &mut self,
761 sp: impl Into<MultiSpan>,
762 msg: impl Into<SubdiagMessage>,
763 ) -> &mut Self {
764 self.sub(Level::Note, msg, sp.into());
765 self
766 } }
767
768 #[rustc_lint_diagnostics]
771 pub fn span_note_once<S: Into<MultiSpan>>(
772 &mut self,
773 sp: S,
774 msg: impl Into<SubdiagMessage>,
775 ) -> &mut Self {
776 self.sub(Level::OnceNote, msg, sp.into());
777 self
778 }
779
780 "See [`Diag::warn()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::warn()`]."
mut self
msg
Self
self.warn(msg);
self;with_fn! { with_warn,
781 #[rustc_lint_diagnostics]
783 pub fn warn(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
784 self.sub(Level::Warning, msg, MultiSpan::new());
785 self
786 } }
787
788 #[rustc_lint_diagnostics]
791 pub fn span_warn<S: Into<MultiSpan>>(
792 &mut self,
793 sp: S,
794 msg: impl Into<SubdiagMessage>,
795 ) -> &mut Self {
796 self.sub(Level::Warning, msg, sp.into());
797 self
798 }
799
800 "See [`Diag::help()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::help()`]."
mut self
msg
Self
self.help(msg);
self;with_fn! { with_help,
801 #[rustc_lint_diagnostics]
803 pub fn help(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
804 self.sub(Level::Help, msg, MultiSpan::new());
805 self
806 } }
807
808 #[rustc_lint_diagnostics]
810 pub fn help_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
811 self.sub(Level::OnceHelp, msg, MultiSpan::new());
812 self
813 }
814
815 #[rustc_lint_diagnostics]
817 pub fn highlighted_help(&mut self, msg: Vec<StringPart>) -> &mut Self {
818 self.sub_with_highlights(Level::Help, msg, MultiSpan::new());
819 self
820 }
821
822 #[rustc_lint_diagnostics]
824 pub fn highlighted_span_help(
825 &mut self,
826 span: impl Into<MultiSpan>,
827 msg: Vec<StringPart>,
828 ) -> &mut Self {
829 self.sub_with_highlights(Level::Help, msg, span.into());
830 self
831 }
832
833 "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,
834 #[rustc_lint_diagnostics]
837 pub fn span_help(
838 &mut self,
839 sp: impl Into<MultiSpan>,
840 msg: impl Into<SubdiagMessage>,
841 ) -> &mut Self {
842 self.sub(Level::Help, msg, sp.into());
843 self
844 } }
845
846 #[rustc_lint_diagnostics]
850 pub fn disable_suggestions(&mut self) -> &mut Self {
851 self.suggestions = Suggestions::Disabled;
852 self
853 }
854
855 #[rustc_lint_diagnostics]
860 pub fn seal_suggestions(&mut self) -> &mut Self {
861 if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
862 let suggestions_slice = std::mem::take(suggestions).into_boxed_slice();
863 self.suggestions = Suggestions::Sealed(suggestions_slice);
864 }
865 self
866 }
867
868 #[rustc_lint_diagnostics]
873 fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
874 for subst in &suggestion.substitutions {
875 for part in &subst.parts {
876 let span = part.span;
877 let call_site = span.ctxt().outer_expn_data().call_site;
878 if span.in_derive_expansion() && span.overlaps_or_adjacent(call_site) {
879 return;
881 }
882 }
883 }
884
885 if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
886 suggestions.push(suggestion);
887 }
888 }
889
890 "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,
891 #[rustc_lint_diagnostics]
894 pub fn multipart_suggestion(
895 &mut self,
896 msg: impl Into<SubdiagMessage>,
897 suggestion: Vec<(Span, String)>,
898 applicability: Applicability,
899 ) -> &mut Self {
900 self.multipart_suggestion_with_style(
901 msg,
902 suggestion,
903 applicability,
904 SuggestionStyle::ShowCode,
905 )
906 } }
907
908 #[rustc_lint_diagnostics]
911 pub fn multipart_suggestion_verbose(
912 &mut self,
913 msg: impl Into<SubdiagMessage>,
914 suggestion: Vec<(Span, String)>,
915 applicability: Applicability,
916 ) -> &mut Self {
917 self.multipart_suggestion_with_style(
918 msg,
919 suggestion,
920 applicability,
921 SuggestionStyle::ShowAlways,
922 )
923 }
924
925 #[rustc_lint_diagnostics]
927 pub fn multipart_suggestion_with_style(
928 &mut self,
929 msg: impl Into<SubdiagMessage>,
930 mut suggestion: Vec<(Span, String)>,
931 applicability: Applicability,
932 style: SuggestionStyle,
933 ) -> &mut Self {
934 let mut seen = crate::FxHashSet::default();
935 suggestion.retain(|(span, msg)| seen.insert((span.lo(), span.hi(), msg.clone())));
936
937 let parts = suggestion
938 .into_iter()
939 .map(|(span, snippet)| SubstitutionPart { snippet, span })
940 .collect::<Vec<_>>();
941
942 if !!parts.is_empty() {
::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
943 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!(
944 parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
945 None,
946 "Span must not be empty and have no suggestion",
947 );
948 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!(
949 parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
950 None,
951 "suggestion must not have overlapping parts",
952 );
953
954 self.push_suggestion(CodeSuggestion {
955 substitutions: <[_]>::into_vec(::alloc::boxed::box_new([Substitution { parts }]))vec![Substitution { parts }],
956 msg: self.subdiagnostic_message_to_diagnostic_message(msg),
957 style,
958 applicability,
959 });
960 self
961 }
962
963 #[rustc_lint_diagnostics]
970 pub fn tool_only_multipart_suggestion(
971 &mut self,
972 msg: impl Into<SubdiagMessage>,
973 suggestion: Vec<(Span, String)>,
974 applicability: Applicability,
975 ) -> &mut Self {
976 self.multipart_suggestion_with_style(
977 msg,
978 suggestion,
979 applicability,
980 SuggestionStyle::CompletelyHidden,
981 )
982 }
983
984 "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,
985 #[rustc_lint_diagnostics]
1003 pub fn span_suggestion(
1004 &mut self,
1005 sp: Span,
1006 msg: impl Into<SubdiagMessage>,
1007 suggestion: impl ToString,
1008 applicability: Applicability,
1009 ) -> &mut Self {
1010 self.span_suggestion_with_style(
1011 sp,
1012 msg,
1013 suggestion,
1014 applicability,
1015 SuggestionStyle::ShowCode,
1016 );
1017 self
1018 } }
1019
1020 #[rustc_lint_diagnostics]
1022 pub fn span_suggestion_with_style(
1023 &mut self,
1024 sp: Span,
1025 msg: impl Into<SubdiagMessage>,
1026 suggestion: impl ToString,
1027 applicability: Applicability,
1028 style: SuggestionStyle,
1029 ) -> &mut Self {
1030 if true {
if !!(sp.is_empty() && suggestion.to_string().is_empty()) {
{
::core::panicking::panic_fmt(format_args!("Span must not be empty and have no suggestion"));
}
};
};debug_assert!(
1031 !(sp.is_empty() && suggestion.to_string().is_empty()),
1032 "Span must not be empty and have no suggestion"
1033 );
1034 self.push_suggestion(CodeSuggestion {
1035 substitutions: <[_]>::into_vec(::alloc::boxed::box_new([Substitution {
parts: <[_]>::into_vec(::alloc::boxed::box_new([SubstitutionPart {
snippet: suggestion.to_string(),
span: sp,
}])),
}]))vec![Substitution {
1036 parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
1037 }],
1038 msg: self.subdiagnostic_message_to_diagnostic_message(msg),
1039 style,
1040 applicability,
1041 });
1042 self
1043 }
1044
1045 "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,
1046 #[rustc_lint_diagnostics]
1048 pub fn span_suggestion_verbose(
1049 &mut self,
1050 sp: Span,
1051 msg: impl Into<SubdiagMessage>,
1052 suggestion: impl ToString,
1053 applicability: Applicability,
1054 ) -> &mut Self {
1055 self.span_suggestion_with_style(
1056 sp,
1057 msg,
1058 suggestion,
1059 applicability,
1060 SuggestionStyle::ShowAlways,
1061 );
1062 self
1063 } }
1064
1065 "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,
1066 #[rustc_lint_diagnostics]
1069 pub fn span_suggestions(
1070 &mut self,
1071 sp: Span,
1072 msg: impl Into<SubdiagMessage>,
1073 suggestions: impl IntoIterator<Item = String>,
1074 applicability: Applicability,
1075 ) -> &mut Self {
1076 self.span_suggestions_with_style(
1077 sp,
1078 msg,
1079 suggestions,
1080 applicability,
1081 SuggestionStyle::ShowCode,
1082 )
1083 } }
1084
1085 #[rustc_lint_diagnostics]
1086 pub fn span_suggestions_with_style(
1087 &mut self,
1088 sp: Span,
1089 msg: impl Into<SubdiagMessage>,
1090 suggestions: impl IntoIterator<Item = String>,
1091 applicability: Applicability,
1092 style: SuggestionStyle,
1093 ) -> &mut Self {
1094 let substitutions = suggestions
1095 .into_iter()
1096 .map(|snippet| {
1097 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!(
1098 !(sp.is_empty() && snippet.is_empty()),
1099 "Span `{sp:?}` must not be empty and have no suggestion"
1100 );
1101 Substitution { parts: <[_]>::into_vec(::alloc::boxed::box_new([SubstitutionPart {
snippet,
span: sp,
}]))vec![SubstitutionPart { snippet, span: sp }] }
1102 })
1103 .collect();
1104 self.push_suggestion(CodeSuggestion {
1105 substitutions,
1106 msg: self.subdiagnostic_message_to_diagnostic_message(msg),
1107 style,
1108 applicability,
1109 });
1110 self
1111 }
1112
1113 #[rustc_lint_diagnostics]
1117 pub fn multipart_suggestions(
1118 &mut self,
1119 msg: impl Into<SubdiagMessage>,
1120 suggestions: impl IntoIterator<Item = Vec<(Span, String)>>,
1121 applicability: Applicability,
1122 ) -> &mut Self {
1123 let substitutions = suggestions
1124 .into_iter()
1125 .map(|sugg| {
1126 let mut parts = sugg
1127 .into_iter()
1128 .map(|(span, snippet)| SubstitutionPart { snippet, span })
1129 .collect::<Vec<_>>();
1130
1131 parts.sort_unstable_by_key(|part| part.span);
1132
1133 if !!parts.is_empty() {
::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
1134 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!(
1135 parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
1136 None,
1137 "Span must not be empty and have no suggestion",
1138 );
1139 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!(
1140 parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
1141 None,
1142 "suggestion must not have overlapping parts",
1143 );
1144
1145 Substitution { parts }
1146 })
1147 .collect();
1148
1149 self.push_suggestion(CodeSuggestion {
1150 substitutions,
1151 msg: self.subdiagnostic_message_to_diagnostic_message(msg),
1152 style: SuggestionStyle::ShowAlways,
1153 applicability,
1154 });
1155 self
1156 }
1157
1158 "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,
1159 #[rustc_lint_diagnostics]
1164 pub fn span_suggestion_short(
1165 &mut self,
1166 sp: Span,
1167 msg: impl Into<SubdiagMessage>,
1168 suggestion: impl ToString,
1169 applicability: Applicability,
1170 ) -> &mut Self {
1171 self.span_suggestion_with_style(
1172 sp,
1173 msg,
1174 suggestion,
1175 applicability,
1176 SuggestionStyle::HideCodeInline,
1177 );
1178 self
1179 } }
1180
1181 #[rustc_lint_diagnostics]
1188 pub fn span_suggestion_hidden(
1189 &mut self,
1190 sp: Span,
1191 msg: impl Into<SubdiagMessage>,
1192 suggestion: impl ToString,
1193 applicability: Applicability,
1194 ) -> &mut Self {
1195 self.span_suggestion_with_style(
1196 sp,
1197 msg,
1198 suggestion,
1199 applicability,
1200 SuggestionStyle::HideCodeAlways,
1201 );
1202 self
1203 }
1204
1205 "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,
1206 #[rustc_lint_diagnostics]
1211 pub fn tool_only_span_suggestion(
1212 &mut self,
1213 sp: Span,
1214 msg: impl Into<SubdiagMessage>,
1215 suggestion: impl ToString,
1216 applicability: Applicability,
1217 ) -> &mut Self {
1218 self.span_suggestion_with_style(
1219 sp,
1220 msg,
1221 suggestion,
1222 applicability,
1223 SuggestionStyle::CompletelyHidden,
1224 );
1225 self
1226 } }
1227
1228 #[rustc_lint_diagnostics]
1233 pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self {
1234 subdiagnostic.add_to_diag(self);
1235 self
1236 }
1237
1238 pub fn eagerly_translate(&self, msg: impl Into<SubdiagMessage>) -> SubdiagMessage {
1244 let args = self.args.iter();
1245 let msg = self.subdiagnostic_message_to_diagnostic_message(msg.into());
1246 self.dcx.eagerly_translate(msg, args)
1247 }
1248
1249 "See [`Diag::span()`]."
&mut Self
self
sp
&mut Self
"See [`Diag::span()`]."
mut self
sp
Self
self.span(sp);
self;with_fn! { with_span,
1250 #[rustc_lint_diagnostics]
1252 pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self {
1253 self.span = sp.into();
1254 if let Some(span) = self.span.primary_span() {
1255 self.sort_span = span;
1256 }
1257 self
1258 } }
1259
1260 #[rustc_lint_diagnostics]
1261 pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
1262 self.is_lint = Some(IsLint { name, has_future_breakage });
1263 self
1264 }
1265
1266 "See [`Diag::code()`]."
&mut Self
self
code
&mut Self
"See [`Diag::code()`]."
mut self
code
Self
self.code(code);
self;with_fn! { with_code,
1267 #[rustc_lint_diagnostics]
1269 pub fn code(&mut self, code: ErrCode) -> &mut Self {
1270 self.code = Some(code);
1271 self
1272 } }
1273
1274 "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,
1275 #[rustc_lint_diagnostics]
1277 pub fn lint_id(
1278 &mut self,
1279 id: LintExpectationId,
1280 ) -> &mut Self {
1281 self.lint_id = Some(id);
1282 self
1283 } }
1284
1285 "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,
1286 #[rustc_lint_diagnostics]
1288 pub fn primary_message(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
1289 self.messages[0] = (msg.into(), Style::NoStyle);
1290 self
1291 } }
1292
1293 "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,
1294 #[rustc_lint_diagnostics]
1296 pub fn arg(
1297 &mut self,
1298 name: impl Into<DiagArgName>,
1299 arg: impl IntoDiagArg,
1300 ) -> &mut Self {
1301 self.deref_mut().arg(name, arg);
1302 self
1303 } }
1304
1305 pub(crate) fn subdiagnostic_message_to_diagnostic_message(
1309 &self,
1310 attr: impl Into<SubdiagMessage>,
1311 ) -> DiagMessage {
1312 self.deref().subdiagnostic_message_to_diagnostic_message(attr)
1313 }
1314
1315 pub fn sub(&mut self, level: Level, message: impl Into<SubdiagMessage>, span: MultiSpan) {
1320 self.deref_mut().sub(level, message, span);
1321 }
1322
1323 fn sub_with_highlights(&mut self, level: Level, messages: Vec<StringPart>, span: MultiSpan) {
1326 let messages = messages
1327 .into_iter()
1328 .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.content), m.style))
1329 .collect();
1330 let sub = Subdiag { level, messages, span };
1331 self.children.push(sub);
1332 }
1333
1334 fn take_diag(&mut self) -> DiagInner {
1338 if let Some(path) = &self.long_ty_path {
1339 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!(
1340 "the full name for the type has been written to '{}'",
1341 path.display()
1342 ));
1343 self.note("consider using `--verbose` to print the full type name to the console");
1344 }
1345 *self.diag.take().unwrap()
1346 }
1347
1348 pub fn long_ty_path(&mut self) -> &mut Option<PathBuf> {
1366 &mut self.long_ty_path
1367 }
1368
1369 pub fn with_long_ty_path(mut self, long_ty_path: Option<PathBuf>) -> Self {
1370 self.long_ty_path = long_ty_path;
1371 self
1372 }
1373
1374 fn emit_producing_nothing(mut self) {
1376 let diag = self.take_diag();
1377 self.dcx.emit_diagnostic(diag);
1378 }
1379
1380 fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed {
1382 let diag = self.take_diag();
1383
1384 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!(
1393 matches!(diag.level, Level::Error | Level::DelayedBug),
1394 "invalid diagnostic level ({:?})",
1395 diag.level,
1396 );
1397
1398 let guar = self.dcx.emit_diagnostic(diag);
1399 guar.unwrap()
1400 }
1401
1402 #[track_caller]
1404 pub fn emit(self) -> G::EmitResult {
1405 G::emit_producing_guarantee(self)
1406 }
1407
1408 #[track_caller]
1413 pub fn emit_unless_delay(mut self, delay: bool) -> G::EmitResult {
1414 if delay {
1415 self.downgrade_to_delayed_bug();
1416 }
1417 self.emit()
1418 }
1419
1420 pub fn cancel(mut self) {
1423 self.diag = None;
1424 drop(self);
1425 }
1426
1427 pub fn stash(mut self, span: Span, key: StashKey) -> Option<ErrorGuaranteed> {
1429 let diag = self.take_diag();
1430 self.dcx.stash_diagnostic(span, key, diag)
1431 }
1432
1433 #[track_caller]
1444 pub fn delay_as_bug(mut self) -> G::EmitResult {
1445 self.downgrade_to_delayed_bug();
1446 self.emit()
1447 }
1448
1449 pub fn remove_arg(&mut self, name: &str) {
1450 if let Some(diag) = self.diag.as_mut() {
1451 diag.remove_arg(name);
1452 }
1453 }
1454}
1455
1456impl<G: EmissionGuarantee> Drop for Diag<'_, G> {
1459 fn drop(&mut self) {
1460 match self.diag.take() {
1461 Some(diag) if !panicking() => {
1462 self.dcx.emit_diagnostic(DiagInner::new(
1463 Level::Bug,
1464 DiagMessage::from("the following error was constructed but not emitted"),
1465 ));
1466 self.dcx.emit_diagnostic(*diag);
1467 {
::core::panicking::panic_fmt(format_args!("error was constructed but not emitted"));
};panic!("error was constructed but not emitted");
1468 }
1469 _ => {}
1470 }
1471 }
1472}
1473
1474#[macro_export]
1475macro_rules! struct_span_code_err {
1476 ($dcx:expr, $span:expr, $code:expr, $($message:tt)*) => ({
1477 $dcx.struct_span_err($span, format!($($message)*)).with_code($code)
1478 })
1479}