Skip to main content

rustc_errors/
diagnostic.rs

1use std::borrow::Cow;
2use std::fmt::{self, Debug};
3use std::hash::{Hash, Hasher};
4use std::marker::PhantomData;
5use std::ops::{Deref, DerefMut};
6use std::panic;
7use std::path::PathBuf;
8use std::thread::panicking;
9
10use rustc_data_structures::fx::FxIndexMap;
11use rustc_error_messages::{DiagArgName, DiagArgValue, IntoDiagArg};
12use rustc_lint_defs::{Applicability, LintExpectationId};
13use rustc_macros::{Decodable, Encodable};
14use rustc_span::source_map::Spanned;
15use rustc_span::{DUMMY_SP, Span, Symbol};
16use tracing::debug;
17
18use crate::{
19    CodeSuggestion, DiagCtxtHandle, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level,
20    MultiSpan, StashKey, Style, SubdiagMessage, Substitution, SubstitutionPart, SuggestionStyle,
21    Suggestions,
22};
23
24pub type DiagArgMap = FxIndexMap<DiagArgName, DiagArgValue>;
25
26/// Trait for types that `Diag::emit` can return as a "guarantee" (or "proof")
27/// token that the emission happened.
28pub trait EmissionGuarantee: Sized {
29    /// This exists so that bugs and fatal errors can both result in `!` (an
30    /// abort) when emitted, but have different aborting behaviour.
31    type EmitResult = Self;
32
33    /// Implementation of `Diag::emit`, fully controlled by each `impl` of
34    /// `EmissionGuarantee`, to make it impossible to create a value of
35    /// `Self::EmitResult` without actually performing the emission.
36    #[track_caller]
37    fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult;
38}
39
40impl EmissionGuarantee for ErrorGuaranteed {
41    fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
42        diag.emit_producing_error_guaranteed()
43    }
44}
45
46impl EmissionGuarantee for () {
47    fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
48        diag.emit_producing_nothing();
49    }
50}
51
52/// Marker type which enables implementation of `create_bug` and `emit_bug` functions for
53/// bug diagnostics.
54#[derive(#[automatically_derived]
impl ::core::marker::Copy for BugAbort { }Copy, #[automatically_derived]
impl ::core::clone::Clone for BugAbort {
    #[inline]
    fn clone(&self) -> BugAbort { *self }
}Clone)]
55pub struct BugAbort;
56
57impl EmissionGuarantee for BugAbort {
58    type EmitResult = !;
59
60    fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
61        diag.emit_producing_nothing();
62        panic::panic_any(ExplicitBug);
63    }
64}
65
66/// Marker type which enables implementation of `create_fatal` and `emit_fatal` functions for
67/// fatal diagnostics.
68#[derive(#[automatically_derived]
impl ::core::marker::Copy for FatalAbort { }Copy, #[automatically_derived]
impl ::core::clone::Clone for FatalAbort {
    #[inline]
    fn clone(&self) -> FatalAbort { *self }
}Clone)]
69pub struct FatalAbort;
70
71impl EmissionGuarantee for FatalAbort {
72    type EmitResult = !;
73
74    fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
75        diag.emit_producing_nothing();
76        crate::FatalError.raise()
77    }
78}
79
80impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
81    fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult {
82        diag.emit_producing_nothing();
83        rustc_span::fatal_error::FatalError
84    }
85}
86
87/// Trait implemented by error types. This is rarely implemented manually. Instead, use
88/// `#[derive(Diagnostic)]` -- see [rustc_macros::Diagnostic].
89///
90/// When implemented manually, it should be generic over the emission
91/// guarantee, i.e.:
92/// ```ignore (fragment)
93/// impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for Foo { ... }
94/// ```
95/// rather than being specific:
96/// ```ignore (fragment)
97/// impl<'a> Diagnostic<'a> for Bar { ... }  // the default type param is `ErrorGuaranteed`
98/// impl<'a> Diagnostic<'a, ()> for Baz { ... }
99/// ```
100/// There are two reasons for this.
101/// - A diagnostic like `Foo` *could* be emitted at any level -- `level` is
102///   passed in to `into_diag` from outside. Even if in practice it is
103///   always emitted at a single level, we let the diagnostic creation/emission
104///   site determine the level (by using `create_err`, `emit_warn`, etc.)
105///   rather than the `Diagnostic` impl.
106/// - Derived impls are always generic, and it's good for the hand-written
107///   impls to be consistent with them.
108#[rustc_diagnostic_item = "Diagnostic"]
109pub trait Diagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> {
110    /// Write out as a diagnostic out of `DiagCtxt`.
111    #[must_use]
112    fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G>;
113}
114
115impl<'a, T, G> Diagnostic<'a, G> for Spanned<T>
116where
117    T: Diagnostic<'a, G>,
118    G: EmissionGuarantee,
119{
120    fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
121        self.node.into_diag(dcx, level).with_span(self.span)
122    }
123}
124
125/// Trait implemented by error types. This should not be implemented manually. Instead, use
126/// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic].
127#[rustc_diagnostic_item = "Subdiagnostic"]
128pub trait Subdiagnostic
129where
130    Self: Sized,
131{
132    /// Add a subdiagnostic to an existing diagnostic.
133    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
134}
135
136/// Trait implemented by lint types. This should not be implemented manually. Instead, use
137/// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic].
138#[rustc_diagnostic_item = "LintDiagnostic"]
139pub trait LintDiagnostic<'a, G: EmissionGuarantee> {
140    /// Decorate a lint with the information from this type.
141    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>);
142}
143
144pub trait LintDiagnosticBox<'a, G: EmissionGuarantee> {
145    fn decorate_lint_box<'b>(self: Box<Self>, diag: &'b mut Diag<'a, G>);
146}
147
148impl<'a, G: EmissionGuarantee, D: LintDiagnostic<'a, G>> LintDiagnosticBox<'a, G> for D {
149    fn decorate_lint_box<'b>(self: Box<Self>, diag: &'b mut Diag<'a, G>) {
150        self.decorate_lint(diag);
151    }
152}
153
154#[derive(#[automatically_derived]
impl ::core::clone::Clone for DiagLocation {
    #[inline]
    fn clone(&self) -> DiagLocation {
        DiagLocation {
            file: ::core::clone::Clone::clone(&self.file),
            line: ::core::clone::Clone::clone(&self.line),
            col: ::core::clone::Clone::clone(&self.col),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for DiagLocation {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f, "DiagLocation",
            "file", &self.file, "line", &self.line, "col", &&self.col)
    }
}Debug, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for DiagLocation {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    DiagLocation {
                        file: ref __binding_0,
                        line: ref __binding_1,
                        col: ref __binding_2 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_2,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for DiagLocation {
            fn decode(__decoder: &mut __D) -> Self {
                DiagLocation {
                    file: ::rustc_serialize::Decodable::decode(__decoder),
                    line: ::rustc_serialize::Decodable::decode(__decoder),
                    col: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable)]
155pub(crate) struct DiagLocation {
156    file: Cow<'static, str>,
157    line: u32,
158    col: u32,
159}
160
161impl DiagLocation {
162    #[track_caller]
163    fn caller() -> Self {
164        let loc = panic::Location::caller();
165        DiagLocation { file: loc.file().into(), line: loc.line(), col: loc.column() }
166    }
167}
168
169impl fmt::Display for DiagLocation {
170    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171        f.write_fmt(format_args!("{0}:{1}:{2}", self.file, self.line, self.col))write!(f, "{}:{}:{}", self.file, self.line, self.col)
172    }
173}
174
175#[derive(#[automatically_derived]
impl ::core::clone::Clone for IsLint {
    #[inline]
    fn clone(&self) -> IsLint {
        IsLint {
            name: ::core::clone::Clone::clone(&self.name),
            has_future_breakage: ::core::clone::Clone::clone(&self.has_future_breakage),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for IsLint {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "IsLint",
            "name", &self.name, "has_future_breakage",
            &&self.has_future_breakage)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for IsLint {
    #[inline]
    fn eq(&self, other: &IsLint) -> bool {
        self.has_future_breakage == other.has_future_breakage &&
            self.name == other.name
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for IsLint {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<String>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for IsLint {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.name, state);
        ::core::hash::Hash::hash(&self.has_future_breakage, state)
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for IsLint {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    IsLint {
                        name: ref __binding_0, has_future_breakage: ref __binding_1
                        } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for IsLint {
            fn decode(__decoder: &mut __D) -> Self {
                IsLint {
                    name: ::rustc_serialize::Decodable::decode(__decoder),
                    has_future_breakage: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable)]
176pub struct IsLint {
177    /// The lint name.
178    pub(crate) name: String,
179    /// Indicates whether this lint should show up in cargo's future breakage report.
180    has_future_breakage: bool,
181}
182
183#[derive(#[automatically_derived]
impl ::core::fmt::Debug for DiagStyledString {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f,
            "DiagStyledString", &&self.0)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for DiagStyledString {
    #[inline]
    fn eq(&self, other: &DiagStyledString) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DiagStyledString {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Vec<StringPart>>;
    }
}Eq)]
184pub struct DiagStyledString(pub Vec<StringPart>);
185
186impl DiagStyledString {
187    pub fn new() -> DiagStyledString {
188        DiagStyledString(::alloc::vec::Vec::new()vec![])
189    }
190    pub fn push_normal<S: Into<String>>(&mut self, t: S) {
191        self.0.push(StringPart::normal(t));
192    }
193    pub fn push_highlighted<S: Into<String>>(&mut self, t: S) {
194        self.0.push(StringPart::highlighted(t));
195    }
196    pub fn push<S: Into<String>>(&mut self, t: S, highlight: bool) {
197        if highlight {
198            self.push_highlighted(t);
199        } else {
200            self.push_normal(t);
201        }
202    }
203    pub fn normal<S: Into<String>>(t: S) -> DiagStyledString {
204        DiagStyledString(<[_]>::into_vec(::alloc::boxed::box_new([StringPart::normal(t)]))vec![StringPart::normal(t)])
205    }
206
207    pub fn highlighted<S: Into<String>>(t: S) -> DiagStyledString {
208        DiagStyledString(<[_]>::into_vec(::alloc::boxed::box_new([StringPart::highlighted(t)]))vec![StringPart::highlighted(t)])
209    }
210
211    pub fn content(&self) -> String {
212        self.0.iter().map(|x| x.content.as_str()).collect::<String>()
213    }
214}
215
216#[derive(#[automatically_derived]
impl ::core::fmt::Debug for StringPart {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "StringPart",
            "content", &self.content, "style", &&self.style)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for StringPart {
    #[inline]
    fn eq(&self, other: &StringPart) -> bool {
        self.content == other.content && self.style == other.style
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for StringPart {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<String>;
        let _: ::core::cmp::AssertParamIsEq<Style>;
    }
}Eq)]
217pub struct StringPart {
218    content: String,
219    style: Style,
220}
221
222impl StringPart {
223    pub fn normal<S: Into<String>>(content: S) -> StringPart {
224        StringPart { content: content.into(), style: Style::NoStyle }
225    }
226
227    pub fn highlighted<S: Into<String>>(content: S) -> StringPart {
228        StringPart { content: content.into(), style: Style::Highlight }
229    }
230}
231
232/// The main part of a diagnostic. Note that `Diag`, which wraps this type, is
233/// used for most operations, and should be used instead whenever possible.
234/// This type should only be used when `Diag`'s lifetime causes difficulties,
235/// e.g. when storing diagnostics within `DiagCtxt`.
236#[must_use]
237#[derive(#[automatically_derived]
impl ::core::clone::Clone for DiagInner {
    #[inline]
    fn clone(&self) -> DiagInner {
        DiagInner {
            level: ::core::clone::Clone::clone(&self.level),
            messages: ::core::clone::Clone::clone(&self.messages),
            code: ::core::clone::Clone::clone(&self.code),
            lint_id: ::core::clone::Clone::clone(&self.lint_id),
            span: ::core::clone::Clone::clone(&self.span),
            children: ::core::clone::Clone::clone(&self.children),
            suggestions: ::core::clone::Clone::clone(&self.suggestions),
            args: ::core::clone::Clone::clone(&self.args),
            reserved_args: ::core::clone::Clone::clone(&self.reserved_args),
            sort_span: ::core::clone::Clone::clone(&self.sort_span),
            is_lint: ::core::clone::Clone::clone(&self.is_lint),
            long_ty_path: ::core::clone::Clone::clone(&self.long_ty_path),
            emitted_at: ::core::clone::Clone::clone(&self.emitted_at),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for DiagInner {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["level", "messages", "code", "lint_id", "span", "children",
                        "suggestions", "args", "reserved_args", "sort_span",
                        "is_lint", "long_ty_path", "emitted_at"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.level, &self.messages, &self.code, &self.lint_id,
                        &self.span, &self.children, &self.suggestions, &self.args,
                        &self.reserved_args, &self.sort_span, &self.is_lint,
                        &self.long_ty_path, &&self.emitted_at];
        ::core::fmt::Formatter::debug_struct_fields_finish(f, "DiagInner",
            names, values)
    }
}Debug, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for DiagInner {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    DiagInner {
                        level: ref __binding_0,
                        messages: ref __binding_1,
                        code: ref __binding_2,
                        lint_id: ref __binding_3,
                        span: ref __binding_4,
                        children: ref __binding_5,
                        suggestions: ref __binding_6,
                        args: ref __binding_7,
                        reserved_args: ref __binding_8,
                        sort_span: ref __binding_9,
                        is_lint: ref __binding_10,
                        long_ty_path: ref __binding_11,
                        emitted_at: ref __binding_12 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_2,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_3,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_4,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_5,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_6,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_7,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_8,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_9,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_10,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_11,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_12,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for DiagInner {
            fn decode(__decoder: &mut __D) -> Self {
                DiagInner {
                    level: ::rustc_serialize::Decodable::decode(__decoder),
                    messages: ::rustc_serialize::Decodable::decode(__decoder),
                    code: ::rustc_serialize::Decodable::decode(__decoder),
                    lint_id: ::rustc_serialize::Decodable::decode(__decoder),
                    span: ::rustc_serialize::Decodable::decode(__decoder),
                    children: ::rustc_serialize::Decodable::decode(__decoder),
                    suggestions: ::rustc_serialize::Decodable::decode(__decoder),
                    args: ::rustc_serialize::Decodable::decode(__decoder),
                    reserved_args: ::rustc_serialize::Decodable::decode(__decoder),
                    sort_span: ::rustc_serialize::Decodable::decode(__decoder),
                    is_lint: ::rustc_serialize::Decodable::decode(__decoder),
                    long_ty_path: ::rustc_serialize::Decodable::decode(__decoder),
                    emitted_at: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable)]
238pub struct DiagInner {
239    // NOTE(eddyb) this is private to disallow arbitrary after-the-fact changes,
240    // outside of what methods in this crate themselves allow.
241    pub(crate) level: Level,
242
243    pub messages: Vec<(DiagMessage, Style)>,
244    pub code: Option<ErrCode>,
245    pub lint_id: Option<LintExpectationId>,
246    pub span: MultiSpan,
247    pub children: Vec<Subdiag>,
248    pub suggestions: Suggestions,
249    pub args: DiagArgMap,
250
251    // This is used to store args and restore them after a subdiagnostic is rendered.
252    pub reserved_args: DiagArgMap,
253
254    /// This is not used for highlighting or rendering any error message. Rather, it can be used
255    /// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of
256    /// `span` if there is one. Otherwise, it is `DUMMY_SP`.
257    pub sort_span: Span,
258
259    pub is_lint: Option<IsLint>,
260
261    pub long_ty_path: Option<PathBuf>,
262    /// With `-Ztrack_diagnostics` enabled,
263    /// we print where in rustc this error was emitted.
264    pub(crate) emitted_at: DiagLocation,
265}
266
267impl DiagInner {
268    #[track_caller]
269    pub fn new<M: Into<DiagMessage>>(level: Level, message: M) -> Self {
270        DiagInner::new_with_messages(level, <[_]>::into_vec(::alloc::boxed::box_new([(message.into(), Style::NoStyle)]))vec![(message.into(), Style::NoStyle)])
271    }
272
273    #[track_caller]
274    pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self {
275        DiagInner {
276            level,
277            lint_id: None,
278            messages,
279            code: None,
280            span: MultiSpan::new(),
281            children: ::alloc::vec::Vec::new()vec![],
282            suggestions: Suggestions::Enabled(::alloc::vec::Vec::new()vec![]),
283            args: Default::default(),
284            reserved_args: Default::default(),
285            sort_span: DUMMY_SP,
286            is_lint: None,
287            long_ty_path: None,
288            emitted_at: DiagLocation::caller(),
289        }
290    }
291
292    #[inline(always)]
293    pub fn level(&self) -> Level {
294        self.level
295    }
296
297    pub fn is_error(&self) -> bool {
298        match self.level {
299            Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true,
300
301            Level::ForceWarning
302            | Level::Warning
303            | Level::Note
304            | Level::OnceNote
305            | Level::Help
306            | Level::OnceHelp
307            | Level::FailureNote
308            | Level::Allow
309            | Level::Expect => false,
310        }
311    }
312
313    /// Indicates whether this diagnostic should show up in cargo's future breakage report.
314    pub(crate) fn has_future_breakage(&self) -> bool {
315        #[allow(non_exhaustive_omitted_patterns)] match self.is_lint {
    Some(IsLint { has_future_breakage: true, .. }) => true,
    _ => false,
}matches!(self.is_lint, Some(IsLint { has_future_breakage: true, .. }))
316    }
317
318    pub(crate) fn is_force_warn(&self) -> bool {
319        match self.level {
320            Level::ForceWarning => {
321                if !self.is_lint.is_some() {
    ::core::panicking::panic("assertion failed: self.is_lint.is_some()")
};assert!(self.is_lint.is_some());
322                true
323            }
324            _ => false,
325        }
326    }
327
328    // See comment on `Diag::subdiagnostic_message_to_diagnostic_message`.
329    pub(crate) fn subdiagnostic_message_to_diagnostic_message(
330        &self,
331        attr: impl Into<SubdiagMessage>,
332    ) -> DiagMessage {
333        let msg =
334            self.messages.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages");
335        msg.with_subdiagnostic_message(attr.into())
336    }
337
338    pub(crate) fn sub(
339        &mut self,
340        level: Level,
341        message: impl Into<SubdiagMessage>,
342        span: MultiSpan,
343    ) {
344        let sub = Subdiag {
345            level,
346            messages: <[_]>::into_vec(::alloc::boxed::box_new([(self.subdiagnostic_message_to_diagnostic_message(message),
                    Style::NoStyle)]))vec![(
347                self.subdiagnostic_message_to_diagnostic_message(message),
348                Style::NoStyle,
349            )],
350            span,
351        };
352        self.children.push(sub);
353    }
354
355    pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) {
356        let name = name.into();
357        let value = arg.into_diag_arg(&mut self.long_ty_path);
358        // This assertion is to avoid subdiagnostics overwriting an existing diagnostic arg.
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!(
360            !self.args.contains_key(&name) || self.args.get(&name) == Some(&value),
361            "arg {} already exists",
362            name
363        );
364        self.args.insert(name, value);
365    }
366
367    pub fn remove_arg(&mut self, name: &str) {
368        self.args.swap_remove(name);
369    }
370
371    pub fn store_args(&mut self) {
372        self.reserved_args = self.args.clone();
373    }
374
375    pub fn restore_args(&mut self) {
376        self.args = std::mem::take(&mut self.reserved_args);
377    }
378
379    pub fn emitted_at_sub_diag(&self) -> Subdiag {
380        let track = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("-Ztrack-diagnostics: created at {0}",
                self.emitted_at))
    })format!("-Ztrack-diagnostics: created at {}", self.emitted_at);
381        Subdiag {
382            level: crate::Level::Note,
383            messages: <[_]>::into_vec(::alloc::boxed::box_new([(DiagMessage::Str(Cow::Owned(track)),
                    Style::NoStyle)]))vec![(DiagMessage::Str(Cow::Owned(track)), Style::NoStyle)],
384            span: MultiSpan::new(),
385        }
386    }
387
388    /// Fields used for Hash, and PartialEq trait.
389    fn keys(
390        &self,
391    ) -> (
392        &Level,
393        &[(DiagMessage, Style)],
394        &Option<ErrCode>,
395        &MultiSpan,
396        &[Subdiag],
397        &Suggestions,
398        Vec<(&DiagArgName, &DiagArgValue)>,
399        &Option<IsLint>,
400    ) {
401        (
402            &self.level,
403            &self.messages,
404            &self.code,
405            &self.span,
406            &self.children,
407            &self.suggestions,
408            self.args.iter().collect(),
409            // omit self.sort_span
410            &self.is_lint,
411            // omit self.emitted_at
412        )
413    }
414}
415
416impl Hash for DiagInner {
417    fn hash<H>(&self, state: &mut H)
418    where
419        H: Hasher,
420    {
421        self.keys().hash(state);
422    }
423}
424
425impl PartialEq for DiagInner {
426    fn eq(&self, other: &Self) -> bool {
427        self.keys() == other.keys()
428    }
429}
430
431/// A "sub"-diagnostic attached to a parent diagnostic.
432/// For example, a note attached to an error.
433#[derive(#[automatically_derived]
impl ::core::clone::Clone for Subdiag {
    #[inline]
    fn clone(&self) -> Subdiag {
        Subdiag {
            level: ::core::clone::Clone::clone(&self.level),
            messages: ::core::clone::Clone::clone(&self.messages),
            span: ::core::clone::Clone::clone(&self.span),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Subdiag {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f, "Subdiag",
            "level", &self.level, "messages", &self.messages, "span",
            &&self.span)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Subdiag {
    #[inline]
    fn eq(&self, other: &Subdiag) -> bool {
        self.level == other.level && self.messages == other.messages &&
            self.span == other.span
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for Subdiag {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.level, state);
        ::core::hash::Hash::hash(&self.messages, state);
        ::core::hash::Hash::hash(&self.span, state)
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for Subdiag {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    Subdiag {
                        level: ref __binding_0,
                        messages: ref __binding_1,
                        span: ref __binding_2 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_2,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for Subdiag {
            fn decode(__decoder: &mut __D) -> Self {
                Subdiag {
                    level: ::rustc_serialize::Decodable::decode(__decoder),
                    messages: ::rustc_serialize::Decodable::decode(__decoder),
                    span: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable)]
434pub struct Subdiag {
435    pub level: Level,
436    pub messages: Vec<(DiagMessage, Style)>,
437    pub span: MultiSpan,
438}
439
440/// Used for emitting structured error messages and other diagnostic information.
441/// Wraps a `DiagInner`, adding some useful things.
442/// - The `dcx` field, allowing it to (a) emit itself, and (b) do a drop check
443///   that it has been emitted or cancelled.
444/// - The `EmissionGuarantee`, which determines the type returned from `emit`.
445///
446/// Each constructed `Diag` must be consumed by a function such as `emit`,
447/// `cancel`, `delay_as_bug`, or `into_diag`. A panic occurs if a `Diag`
448/// is dropped without being consumed by one of these functions.
449///
450/// If there is some state in a downstream crate you would like to access in
451/// the methods of `Diag` here, consider extending `DiagCtxtFlags`.
452#[must_use]
453pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> {
454    pub dcx: DiagCtxtHandle<'a>,
455
456    /// Why the `Option`? It is always `Some` until the `Diag` is consumed via
457    /// `emit`, `cancel`, etc. At that point it is consumed and replaced with
458    /// `None`. Then `drop` checks that it is `None`; if not, it panics because
459    /// a diagnostic was built but not used.
460    ///
461    /// Why the Box? `DiagInner` is a large type, and `Diag` is often used as a
462    /// return value, especially within the frequently-used `PResult` type. In
463    /// theory, return value optimization (RVO) should avoid unnecessary
464    /// copying. In practice, it does not (at the time of writing).
465    diag: Option<Box<DiagInner>>,
466
467    _marker: PhantomData<G>,
468}
469
470// Cloning a `Diag` is a recipe for a diagnostic being emitted twice, which
471// would be bad.
472impl<G> !Clone for Diag<'_, G> {}
473
474const _: [(); 3 * size_of::<usize>()] =
    [(); ::std::mem::size_of::<Diag<'_, ()>>()];rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * size_of::<usize>());
475
476impl<G: EmissionGuarantee> Deref for Diag<'_, G> {
477    type Target = DiagInner;
478
479    fn deref(&self) -> &DiagInner {
480        self.diag.as_ref().unwrap()
481    }
482}
483
484impl<G: EmissionGuarantee> DerefMut for Diag<'_, G> {
485    fn deref_mut(&mut self) -> &mut DiagInner {
486        self.diag.as_mut().unwrap()
487    }
488}
489
490impl<G: EmissionGuarantee> Debug for Diag<'_, G> {
491    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
492        self.diag.fmt(f)
493    }
494}
495
496/// `Diag` impls many `&mut self -> &mut Self` methods. Each one modifies an
497/// existing diagnostic, either in a standalone fashion, e.g.
498/// `err.code(code);`, or in a chained fashion to make multiple modifications,
499/// e.g. `err.code(code).span(span);`.
500///
501/// This macro creates an equivalent `self -> Self` method, with a `with_`
502/// prefix. This can be used in a chained fashion when making a new diagnostic,
503/// e.g. `let err = struct_err(msg).with_code(code);`, or emitting a new
504/// diagnostic, e.g. `struct_err(msg).with_code(code).emit();`.
505///
506/// Although the latter method can be used to modify an existing diagnostic,
507/// e.g. `err = err.with_code(code);`, this should be avoided because the former
508/// method gives shorter code, e.g. `err.code(code);`.
509///
510/// Note: the `with_` methods are added only when needed. If you want to use
511/// one and it's not defined, feel free to add it.
512///
513/// Note: any doc comments must be within the `with_fn!` call.
514macro_rules! with_fn {
515    {
516        $with_f:ident,
517        $(#[$attrs:meta])*
518        pub fn $f:ident(&mut $self:ident, $($name:ident: $ty:ty),* $(,)?) -> &mut Self {
519            $($body:tt)*
520        }
521    } => {
522        // The original function.
523        $(#[$attrs])*
524        #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
525        pub fn $f(&mut $self, $($name: $ty),*) -> &mut Self {
526            $($body)*
527        }
528
529        // The `with_*` variant.
530        $(#[$attrs])*
531        #[doc = concat!("See [`Diag::", stringify!($f), "()`].")]
532        pub fn $with_f(mut $self, $($name: $ty),*) -> Self {
533            $self.$f($($name),*);
534            $self
535        }
536    };
537}
538
539impl<'a, G: EmissionGuarantee> Diag<'a, G> {
540    #[track_caller]
541    pub fn new(dcx: DiagCtxtHandle<'a>, level: Level, message: impl Into<DiagMessage>) -> Self {
542        Self::new_diagnostic(dcx, DiagInner::new(level, message))
543    }
544
545    /// Allow moving diagnostics between different error tainting contexts
546    pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_, G> {
547        Diag { dcx, diag: self.diag.take(), _marker: PhantomData }
548    }
549
550    /// Creates a new `Diag` with an already constructed diagnostic.
551    #[track_caller]
552    pub(crate) fn new_diagnostic(dcx: DiagCtxtHandle<'a>, diag: DiagInner) -> Self {
553        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/diagnostic.rs:553",
                        "rustc_errors::diagnostic", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/diagnostic.rs"),
                        ::tracing_core::__macro_support::Option::Some(553u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_errors::diagnostic"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("Created new diagnostic")
                                            as &dyn Value))])
            });
    } else { ; }
};debug!("Created new diagnostic");
554        Self { dcx, diag: Some(Box::new(diag)), _marker: PhantomData }
555    }
556
557    /// Delay emission of this diagnostic as a bug.
558    ///
559    /// This can be useful in contexts where an error indicates a bug but
560    /// typically this only happens when other compilation errors have already
561    /// happened. In those cases this can be used to defer emission of this
562    /// diagnostic as a bug in the compiler only if no other errors have been
563    /// emitted.
564    ///
565    /// In the meantime, though, callsites are required to deal with the "bug"
566    /// locally in whichever way makes the most sense.
567    #[track_caller]
568    pub fn downgrade_to_delayed_bug(&mut self) {
569        if !#[allow(non_exhaustive_omitted_patterns)] match self.level {
            Level::Error | Level::DelayedBug => true,
            _ => false,
        } {
    {
        ::core::panicking::panic_fmt(format_args!("downgrade_to_delayed_bug: cannot downgrade {0:?} to DelayedBug: not an error",
                self.level));
    }
};assert!(
570            matches!(self.level, Level::Error | Level::DelayedBug),
571            "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
572            self.level
573        );
574        self.level = Level::DelayedBug;
575    }
576
577    /// Make emitting this diagnostic fatal
578    ///
579    /// Changes the level of this diagnostic to Fatal, and importantly also changes the emission guarantee.
580    /// This is sound for errors that would otherwise be printed, but now simply exit the process instead.
581    /// This function still gives an emission guarantee, the guarantee is now just that it exits fatally.
582    /// For delayed bugs this is different, since those are buffered. If we upgrade one to fatal, another
583    /// might now be ignored.
584    #[track_caller]
585    pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> {
586        if !#[allow(non_exhaustive_omitted_patterns)] match self.level {
            Level::Error => true,
            _ => false,
        } {
    {
        ::core::panicking::panic_fmt(format_args!("upgrade_to_fatal: cannot upgrade {0:?} to Fatal: not an error",
                self.level));
    }
};assert!(
587            matches!(self.level, Level::Error),
588            "upgrade_to_fatal: cannot upgrade {:?} to Fatal: not an error",
589            self.level
590        );
591        self.level = Level::Fatal;
592
593        // Take is okay since we immediately rewrap it in another diagnostic.
594        // i.e. we do emit it despite defusing the original diagnostic's drop bomb.
595        let diag = self.diag.take();
596        Diag { dcx: self.dcx, diag, _marker: PhantomData }
597    }
598
599    "See [`Diag::span_label()`]."
&mut Self
self
span
label
&mut Self
"See [`Diag::span_label()`]."
mut self
span
label
Self
self.span_label(span, label);
self;with_fn! { with_span_label,
600    /// Appends a labeled span to the diagnostic.
601    ///
602    /// Labels are used to convey additional context for the diagnostic's primary span. They will
603    /// be shown together with the original diagnostic's span, *not* with spans added by
604    /// `span_note`, `span_help`, etc. Therefore, if the primary span is not displayable (because
605    /// the span is `DUMMY_SP` or the source code isn't found), labels will not be displayed
606    /// either.
607    ///
608    /// Implementation-wise, the label span is pushed onto the [`MultiSpan`] that was created when
609    /// the diagnostic was constructed. However, the label span is *not* considered a
610    /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is
611    /// primary.
612    pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagMessage>) -> &mut Self {
613        let msg = self.subdiagnostic_message_to_diagnostic_message(label);
614        self.span.push_span_label(span, msg);
615        self
616    } }
617
618    "See [`Diag::span_labels()`]."
&mut Self
self
spans
label
&mut Self
"See [`Diag::span_labels()`]."
mut self
spans
label
Self
self.span_labels(spans, label);
self;with_fn! { with_span_labels,
619    /// Labels all the given spans with the provided label.
620    /// See [`Self::span_label()`] for more information.
621    pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
622        for span in spans {
623            self.span_label(span, label.to_string());
624        }
625        self
626    } }
627
628    pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self {
629        let before = self.span.clone();
630        self.span(after);
631        for span_label in before.span_labels() {
632            if let Some(label) = span_label.label {
633                if span_label.is_primary && keep_label {
634                    self.span.push_span_label(after, label);
635                } else {
636                    self.span.push_span_label(span_label.span, label);
637                }
638            }
639        }
640        self
641    }
642
643    pub fn note_expected_found(
644        &mut self,
645        expected_label: &str,
646        expected: DiagStyledString,
647        found_label: &str,
648        found: DiagStyledString,
649    ) -> &mut Self {
650        self.note_expected_found_extra(
651            expected_label,
652            expected,
653            found_label,
654            found,
655            DiagStyledString::normal(""),
656            DiagStyledString::normal(""),
657        )
658    }
659
660    pub fn note_expected_found_extra(
661        &mut self,
662        expected_label: &str,
663        expected: DiagStyledString,
664        found_label: &str,
665        found: DiagStyledString,
666        expected_extra: DiagStyledString,
667        found_extra: DiagStyledString,
668    ) -> &mut Self {
669        let expected_label = expected_label.to_string();
670        let expected_label = if expected_label.is_empty() {
671            "expected".to_string()
672        } else {
673            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected {0}", expected_label))
    })format!("expected {expected_label}")
674        };
675        let found_label = found_label.to_string();
676        let found_label = if found_label.is_empty() {
677            "found".to_string()
678        } else {
679            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("found {0}", found_label))
    })format!("found {found_label}")
680        };
681        let (found_padding, expected_padding) = if expected_label.len() > found_label.len() {
682            (expected_label.len() - found_label.len(), 0)
683        } else {
684            (0, found_label.len() - expected_label.len())
685        };
686        let mut msg = <[_]>::into_vec(::alloc::boxed::box_new([StringPart::normal(::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("{0}{1} `",
                                    " ".repeat(expected_padding), expected_label))
                        }))]))vec![StringPart::normal(format!(
687            "{}{} `",
688            " ".repeat(expected_padding),
689            expected_label
690        ))];
691        msg.extend(expected.0);
692        msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
693        msg.extend(expected_extra.0);
694        msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("\n")) })format!("\n")));
695        msg.push(StringPart::normal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1} `",
                " ".repeat(found_padding), found_label))
    })format!("{}{} `", " ".repeat(found_padding), found_label)));
696        msg.extend(found.0);
697        msg.push(StringPart::normal(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("`")) })format!("`")));
698        msg.extend(found_extra.0);
699
700        // For now, just attach these as notes.
701        self.highlighted_note(msg);
702        self
703    }
704
705    pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
706        self.highlighted_note(<[_]>::into_vec(::alloc::boxed::box_new([StringPart::normal(::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("`{0}` from trait: `",
                                    name))
                        })), StringPart::highlighted(signature),
                StringPart::normal("`")]))vec![
707            StringPart::normal(format!("`{name}` from trait: `")),
708            StringPart::highlighted(signature),
709            StringPart::normal("`"),
710        ]);
711        self
712    }
713
714    "See [`Diag::note()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::note()`]."
mut self
msg
Self
self.note(msg);
self;with_fn! { with_note,
715    /// Add a note attached to this diagnostic.
716    pub fn note(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
717        self.sub(Level::Note, msg, MultiSpan::new());
718        self
719    } }
720
721    pub fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self {
722        self.sub_with_highlights(Level::Note, msg, MultiSpan::new());
723        self
724    }
725
726    pub fn highlighted_span_note(
727        &mut self,
728        span: impl Into<MultiSpan>,
729        msg: Vec<StringPart>,
730    ) -> &mut Self {
731        self.sub_with_highlights(Level::Note, msg, span.into());
732        self
733    }
734
735    /// This is like [`Diag::note()`], but it's only printed once.
736    pub fn note_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
737        self.sub(Level::OnceNote, msg, MultiSpan::new());
738        self
739    }
740
741    "See [`Diag::span_note()`]."
&mut Self
self
sp
msg
&mut Self
"See [`Diag::span_note()`]."
mut self
sp
msg
Self
self.span_note(sp, msg);
self;with_fn! { with_span_note,
742    /// Prints the span with a note above it.
743    /// This is like [`Diag::note()`], but it gets its own span.
744    pub fn span_note(
745        &mut self,
746        sp: impl Into<MultiSpan>,
747        msg: impl Into<SubdiagMessage>,
748    ) -> &mut Self {
749        self.sub(Level::Note, msg, sp.into());
750        self
751    } }
752
753    /// Prints the span with a note above it.
754    /// This is like [`Diag::note_once()`], but it gets its own span.
755    pub fn span_note_once<S: Into<MultiSpan>>(
756        &mut self,
757        sp: S,
758        msg: impl Into<SubdiagMessage>,
759    ) -> &mut Self {
760        self.sub(Level::OnceNote, msg, sp.into());
761        self
762    }
763
764    "See [`Diag::warn()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::warn()`]."
mut self
msg
Self
self.warn(msg);
self;with_fn! { with_warn,
765    /// Add a warning attached to this diagnostic.
766    pub fn warn(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
767        self.sub(Level::Warning, msg, MultiSpan::new());
768        self
769    } }
770
771    /// Prints the span with a warning above it.
772    /// This is like [`Diag::warn()`], but it gets its own span.
773    pub fn span_warn<S: Into<MultiSpan>>(
774        &mut self,
775        sp: S,
776        msg: impl Into<SubdiagMessage>,
777    ) -> &mut Self {
778        self.sub(Level::Warning, msg, sp.into());
779        self
780    }
781
782    "See [`Diag::help()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::help()`]."
mut self
msg
Self
self.help(msg);
self;with_fn! { with_help,
783    /// Add a help message attached to this diagnostic.
784    pub fn help(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
785        self.sub(Level::Help, msg, MultiSpan::new());
786        self
787    } }
788
789    /// This is like [`Diag::help()`], but it's only printed once.
790    pub fn help_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
791        self.sub(Level::OnceHelp, msg, MultiSpan::new());
792        self
793    }
794
795    /// Add a help message attached to this diagnostic with a customizable highlighted message.
796    pub fn highlighted_help(&mut self, msg: Vec<StringPart>) -> &mut Self {
797        self.sub_with_highlights(Level::Help, msg, MultiSpan::new());
798        self
799    }
800
801    /// Add a help message attached to this diagnostic with a customizable highlighted message.
802    pub fn highlighted_span_help(
803        &mut self,
804        span: impl Into<MultiSpan>,
805        msg: Vec<StringPart>,
806    ) -> &mut Self {
807        self.sub_with_highlights(Level::Help, msg, span.into());
808        self
809    }
810
811    "See [`Diag::span_help()`]."
&mut Self
self
sp
msg
&mut Self
"See [`Diag::span_help()`]."
mut self
sp
msg
Self
self.span_help(sp, msg);
self;with_fn! { with_span_help,
812    /// Prints the span with some help above it.
813    /// This is like [`Diag::help()`], but it gets its own span.
814    pub fn span_help(
815        &mut self,
816        sp: impl Into<MultiSpan>,
817        msg: impl Into<SubdiagMessage>,
818    ) -> &mut Self {
819        self.sub(Level::Help, msg, sp.into());
820        self
821    } }
822
823    /// Disallow attaching suggestions to this diagnostic.
824    /// Any suggestions attached e.g. with the `span_suggestion_*` methods
825    /// (before and after the call to `disable_suggestions`) will be ignored.
826    pub fn disable_suggestions(&mut self) -> &mut Self {
827        self.suggestions = Suggestions::Disabled;
828        self
829    }
830
831    /// Prevent new suggestions from being added to this diagnostic.
832    ///
833    /// Suggestions added before the call to `.seal_suggestions()` will be preserved
834    /// and new suggestions will be ignored.
835    pub fn seal_suggestions(&mut self) -> &mut Self {
836        if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
837            let suggestions_slice = std::mem::take(suggestions).into_boxed_slice();
838            self.suggestions = Suggestions::Sealed(suggestions_slice);
839        }
840        self
841    }
842
843    /// Helper for pushing to `self.suggestions`.
844    ///
845    /// A new suggestion is added if suggestions are enabled for this diagnostic.
846    /// Otherwise, they are ignored.
847    fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
848        for subst in &suggestion.substitutions {
849            for part in &subst.parts {
850                let span = part.span;
851                let call_site = span.ctxt().outer_expn_data().call_site;
852                if span.in_derive_expansion() && span.overlaps_or_adjacent(call_site) {
853                    // Ignore if spans is from derive macro.
854                    return;
855                }
856            }
857        }
858
859        if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
860            suggestions.push(suggestion);
861        }
862    }
863
864    "See [`Diag::multipart_suggestion()`]."
&mut Self
self
msg
suggestion
applicability
&mut Self
"See [`Diag::multipart_suggestion()`]."
mut self
msg
suggestion
applicability
Self
self.multipart_suggestion(msg, suggestion, applicability);
self;with_fn! { with_multipart_suggestion,
865    /// Show a suggestion that has multiple parts to it.
866    /// In other words, multiple changes need to be applied as part of this suggestion.
867    pub fn multipart_suggestion(
868        &mut self,
869        msg: impl Into<SubdiagMessage>,
870        suggestion: Vec<(Span, String)>,
871        applicability: Applicability,
872    ) -> &mut Self {
873        self.multipart_suggestion_with_style(
874            msg,
875            suggestion,
876            applicability,
877            SuggestionStyle::ShowCode,
878        )
879    } }
880
881    /// Show a suggestion that has multiple parts to it, always as its own subdiagnostic.
882    /// In other words, multiple changes need to be applied as part of this suggestion.
883    pub fn multipart_suggestion_verbose(
884        &mut self,
885        msg: impl Into<SubdiagMessage>,
886        suggestion: Vec<(Span, String)>,
887        applicability: Applicability,
888    ) -> &mut Self {
889        self.multipart_suggestion_with_style(
890            msg,
891            suggestion,
892            applicability,
893            SuggestionStyle::ShowAlways,
894        )
895    }
896
897    /// [`Diag::multipart_suggestion()`] but you can set the [`SuggestionStyle`].
898    pub fn multipart_suggestion_with_style(
899        &mut self,
900        msg: impl Into<SubdiagMessage>,
901        mut suggestion: Vec<(Span, String)>,
902        applicability: Applicability,
903        style: SuggestionStyle,
904    ) -> &mut Self {
905        let mut seen = crate::FxHashSet::default();
906        suggestion.retain(|(span, msg)| seen.insert((span.lo(), span.hi(), msg.clone())));
907
908        let parts = suggestion
909            .into_iter()
910            .map(|(span, snippet)| SubstitutionPart { snippet, span })
911            .collect::<Vec<_>>();
912
913        if !!parts.is_empty() {
    ::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
914        if true {
    match (&parts.iter().find(|part|
                        part.span.is_empty() && part.snippet.is_empty()), &None) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("Span must not be empty and have no suggestion")));
            }
        }
    };
};debug_assert_eq!(
915            parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
916            None,
917            "Span must not be empty and have no suggestion",
918        );
919        if true {
    match (&parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
            &None) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("suggestion must not have overlapping parts")));
            }
        }
    };
};debug_assert_eq!(
920            parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
921            None,
922            "suggestion must not have overlapping parts",
923        );
924
925        self.push_suggestion(CodeSuggestion {
926            substitutions: <[_]>::into_vec(::alloc::boxed::box_new([Substitution { parts }]))vec![Substitution { parts }],
927            msg: self.subdiagnostic_message_to_diagnostic_message(msg),
928            style,
929            applicability,
930        });
931        self
932    }
933
934    /// Prints out a message with for a multipart suggestion without showing the suggested code.
935    ///
936    /// This is intended to be used for suggestions that are obvious in what the changes need to
937    /// be from the message, showing the span label inline would be visually unpleasant
938    /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't
939    /// improve understandability.
940    pub fn tool_only_multipart_suggestion(
941        &mut self,
942        msg: impl Into<SubdiagMessage>,
943        suggestion: Vec<(Span, String)>,
944        applicability: Applicability,
945    ) -> &mut Self {
946        self.multipart_suggestion_with_style(
947            msg,
948            suggestion,
949            applicability,
950            SuggestionStyle::CompletelyHidden,
951        )
952    }
953
954    "See [`Diag::span_suggestion()`]."
&mut Self
self
sp
msg
suggestion
applicability
&mut Self
"See [`Diag::span_suggestion()`]."
mut self
sp
msg
suggestion
applicability
Self
self.span_suggestion(sp, msg, suggestion, applicability);
self;with_fn! { with_span_suggestion,
955    /// Prints out a message with a suggested edit of the code.
956    ///
957    /// In case of short messages and a simple suggestion, rustc displays it as a label:
958    ///
959    /// ```text
960    /// try adding parentheses: `(tup.0).1`
961    /// ```
962    ///
963    /// The message
964    ///
965    /// * should not end in any punctuation (a `:` is added automatically)
966    /// * should not be a question (avoid language like "did you mean")
967    /// * should not contain any phrases like "the following", "as shown", etc.
968    /// * may look like "to do xyz, use" or "to do xyz, use abc"
969    /// * may contain a name of a function, variable, or type, but not whole expressions
970    ///
971    /// See [`CodeSuggestion`] for more information.
972    pub fn span_suggestion(
973        &mut self,
974        sp: Span,
975        msg: impl Into<SubdiagMessage>,
976        suggestion: impl ToString,
977        applicability: Applicability,
978    ) -> &mut Self {
979        self.span_suggestion_with_style(
980            sp,
981            msg,
982            suggestion,
983            applicability,
984            SuggestionStyle::ShowCode,
985        );
986        self
987    } }
988
989    /// [`Diag::span_suggestion()`] but you can set the [`SuggestionStyle`].
990    pub fn span_suggestion_with_style(
991        &mut self,
992        sp: Span,
993        msg: impl Into<SubdiagMessage>,
994        suggestion: impl ToString,
995        applicability: Applicability,
996        style: SuggestionStyle,
997    ) -> &mut Self {
998        if true {
    if !!(sp.is_empty() && suggestion.to_string().is_empty()) {
        {
            ::core::panicking::panic_fmt(format_args!("Span must not be empty and have no suggestion"));
        }
    };
};debug_assert!(
999            !(sp.is_empty() && suggestion.to_string().is_empty()),
1000            "Span must not be empty and have no suggestion"
1001        );
1002        self.push_suggestion(CodeSuggestion {
1003            substitutions: <[_]>::into_vec(::alloc::boxed::box_new([Substitution {
                    parts: <[_]>::into_vec(::alloc::boxed::box_new([SubstitutionPart {
                                        snippet: suggestion.to_string(),
                                        span: sp,
                                    }])),
                }]))vec![Substitution {
1004                parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
1005            }],
1006            msg: self.subdiagnostic_message_to_diagnostic_message(msg),
1007            style,
1008            applicability,
1009        });
1010        self
1011    }
1012
1013    "See [`Diag::span_suggestion_verbose()`]."
&mut Self
self
sp
msg
suggestion
applicability
&mut Self
"See [`Diag::span_suggestion_verbose()`]."
mut self
sp
msg
suggestion
applicability
Self
self.span_suggestion_verbose(sp, msg, suggestion, applicability);
self;with_fn! { with_span_suggestion_verbose,
1014    /// Always show the suggested change.
1015    pub fn span_suggestion_verbose(
1016        &mut self,
1017        sp: Span,
1018        msg: impl Into<SubdiagMessage>,
1019        suggestion: impl ToString,
1020        applicability: Applicability,
1021    ) -> &mut Self {
1022        self.span_suggestion_with_style(
1023            sp,
1024            msg,
1025            suggestion,
1026            applicability,
1027            SuggestionStyle::ShowAlways,
1028        );
1029        self
1030    } }
1031
1032    "See [`Diag::span_suggestions()`]."
&mut Self
self
sp
msg
suggestions
applicability
&mut Self
"See [`Diag::span_suggestions()`]."
mut self
sp
msg
suggestions
applicability
Self
self.span_suggestions(sp, msg, suggestions, applicability);
self;with_fn! { with_span_suggestions,
1033    /// Prints out a message with multiple suggested edits of the code.
1034    /// See also [`Diag::span_suggestion()`].
1035    pub fn span_suggestions(
1036        &mut self,
1037        sp: Span,
1038        msg: impl Into<SubdiagMessage>,
1039        suggestions: impl IntoIterator<Item = String>,
1040        applicability: Applicability,
1041    ) -> &mut Self {
1042        self.span_suggestions_with_style(
1043            sp,
1044            msg,
1045            suggestions,
1046            applicability,
1047            SuggestionStyle::ShowCode,
1048        )
1049    } }
1050
1051    pub fn span_suggestions_with_style(
1052        &mut self,
1053        sp: Span,
1054        msg: impl Into<SubdiagMessage>,
1055        suggestions: impl IntoIterator<Item = String>,
1056        applicability: Applicability,
1057        style: SuggestionStyle,
1058    ) -> &mut Self {
1059        let substitutions = suggestions
1060            .into_iter()
1061            .map(|snippet| {
1062                if true {
    if !!(sp.is_empty() && snippet.is_empty()) {
        {
            ::core::panicking::panic_fmt(format_args!("Span `{0:?}` must not be empty and have no suggestion",
                    sp));
        }
    };
};debug_assert!(
1063                    !(sp.is_empty() && snippet.is_empty()),
1064                    "Span `{sp:?}` must not be empty and have no suggestion"
1065                );
1066                Substitution { parts: <[_]>::into_vec(::alloc::boxed::box_new([SubstitutionPart {
                    snippet,
                    span: sp,
                }]))vec![SubstitutionPart { snippet, span: sp }] }
1067            })
1068            .collect();
1069        self.push_suggestion(CodeSuggestion {
1070            substitutions,
1071            msg: self.subdiagnostic_message_to_diagnostic_message(msg),
1072            style,
1073            applicability,
1074        });
1075        self
1076    }
1077
1078    /// Prints out a message with multiple suggested edits of the code, where each edit consists of
1079    /// multiple parts.
1080    /// See also [`Diag::multipart_suggestion()`].
1081    pub fn multipart_suggestions(
1082        &mut self,
1083        msg: impl Into<SubdiagMessage>,
1084        suggestions: impl IntoIterator<Item = Vec<(Span, String)>>,
1085        applicability: Applicability,
1086    ) -> &mut Self {
1087        let substitutions = suggestions
1088            .into_iter()
1089            .map(|sugg| {
1090                let mut parts = sugg
1091                    .into_iter()
1092                    .map(|(span, snippet)| SubstitutionPart { snippet, span })
1093                    .collect::<Vec<_>>();
1094
1095                parts.sort_unstable_by_key(|part| part.span);
1096
1097                if !!parts.is_empty() {
    ::core::panicking::panic("assertion failed: !parts.is_empty()")
};assert!(!parts.is_empty());
1098                if true {
    match (&parts.iter().find(|part|
                        part.span.is_empty() && part.snippet.is_empty()), &None) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("Span must not be empty and have no suggestion")));
            }
        }
    };
};debug_assert_eq!(
1099                    parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
1100                    None,
1101                    "Span must not be empty and have no suggestion",
1102                );
1103                if true {
    match (&parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
            &None) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("suggestion must not have overlapping parts")));
            }
        }
    };
};debug_assert_eq!(
1104                    parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
1105                    None,
1106                    "suggestion must not have overlapping parts",
1107                );
1108
1109                Substitution { parts }
1110            })
1111            .collect();
1112
1113        self.push_suggestion(CodeSuggestion {
1114            substitutions,
1115            msg: self.subdiagnostic_message_to_diagnostic_message(msg),
1116            style: SuggestionStyle::ShowAlways,
1117            applicability,
1118        });
1119        self
1120    }
1121
1122    "See [`Diag::span_suggestion_short()`]."
&mut Self
self
sp
msg
suggestion
applicability
&mut Self
"See [`Diag::span_suggestion_short()`]."
mut self
sp
msg
suggestion
applicability
Self
self.span_suggestion_short(sp, msg, suggestion, applicability);
self;with_fn! { with_span_suggestion_short,
1123    /// Prints out a message with a suggested edit of the code. If the suggestion is presented
1124    /// inline, it will only show the message and not the suggestion.
1125    ///
1126    /// See [`CodeSuggestion`] for more information.
1127    pub fn span_suggestion_short(
1128        &mut self,
1129        sp: Span,
1130        msg: impl Into<SubdiagMessage>,
1131        suggestion: impl ToString,
1132        applicability: Applicability,
1133    ) -> &mut Self {
1134        self.span_suggestion_with_style(
1135            sp,
1136            msg,
1137            suggestion,
1138            applicability,
1139            SuggestionStyle::HideCodeInline,
1140        );
1141        self
1142    } }
1143
1144    /// Prints out a message for a suggestion without showing the suggested code.
1145    ///
1146    /// This is intended to be used for suggestions that are obvious in what the changes need to
1147    /// be from the message, showing the span label inline would be visually unpleasant
1148    /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't
1149    /// improve understandability.
1150    pub fn span_suggestion_hidden(
1151        &mut self,
1152        sp: Span,
1153        msg: impl Into<SubdiagMessage>,
1154        suggestion: impl ToString,
1155        applicability: Applicability,
1156    ) -> &mut Self {
1157        self.span_suggestion_with_style(
1158            sp,
1159            msg,
1160            suggestion,
1161            applicability,
1162            SuggestionStyle::HideCodeAlways,
1163        );
1164        self
1165    }
1166
1167    "See [`Diag::tool_only_span_suggestion()`]."
&mut Self
self
sp
msg
suggestion
applicability
&mut Self
"See [`Diag::tool_only_span_suggestion()`]."
mut self
sp
msg
suggestion
applicability
Self
self.tool_only_span_suggestion(sp, msg, suggestion, applicability);
self;with_fn! { with_tool_only_span_suggestion,
1168    /// Adds a suggestion to the JSON output that will not be shown in the CLI.
1169    ///
1170    /// This is intended to be used for suggestions that are *very* obvious in what the changes
1171    /// need to be from the message, but we still want other tools to be able to apply them.
1172    pub fn tool_only_span_suggestion(
1173        &mut self,
1174        sp: Span,
1175        msg: impl Into<SubdiagMessage>,
1176        suggestion: impl ToString,
1177        applicability: Applicability,
1178    ) -> &mut Self {
1179        self.span_suggestion_with_style(
1180            sp,
1181            msg,
1182            suggestion,
1183            applicability,
1184            SuggestionStyle::CompletelyHidden,
1185        );
1186        self
1187    } }
1188
1189    /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see
1190    /// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages
1191    /// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of
1192    /// interpolated variables).
1193    pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self {
1194        subdiagnostic.add_to_diag(self);
1195        self
1196    }
1197
1198    /// Fluent variables are not namespaced from each other, so when
1199    /// `Diagnostic`s and `Subdiagnostic`s use the same variable name,
1200    /// one value will clobber the other. Eagerly translating the
1201    /// diagnostic uses the variables defined right then, before the
1202    /// clobbering occurs.
1203    pub fn eagerly_translate(&self, msg: impl Into<SubdiagMessage>) -> SubdiagMessage {
1204        let args = self.args.iter();
1205        let msg = self.subdiagnostic_message_to_diagnostic_message(msg.into());
1206        self.dcx.eagerly_translate(msg, args)
1207    }
1208
1209    "See [`Diag::span()`]."
&mut Self
self
sp
&mut Self
"See [`Diag::span()`]."
mut self
sp
Self
self.span(sp);
self;with_fn! { with_span,
1210    /// Add a span.
1211    pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self {
1212        self.span = sp.into();
1213        if let Some(span) = self.span.primary_span() {
1214            self.sort_span = span;
1215        }
1216        self
1217    } }
1218
1219    pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
1220        self.is_lint = Some(IsLint { name, has_future_breakage });
1221        self
1222    }
1223
1224    "See [`Diag::code()`]."
&mut Self
self
code
&mut Self
"See [`Diag::code()`]."
mut self
code
Self
self.code(code);
self;with_fn! { with_code,
1225    /// Add an error code.
1226    pub fn code(&mut self, code: ErrCode) -> &mut Self {
1227        self.code = Some(code);
1228        self
1229    } }
1230
1231    "See [`Diag::lint_id()`]."
&mut Self
self
id
&mut Self
"See [`Diag::lint_id()`]."
mut self
id
Self
self.lint_id(id);
self;with_fn! { with_lint_id,
1232    /// Add an argument.
1233    pub fn lint_id(
1234        &mut self,
1235        id: LintExpectationId,
1236    ) -> &mut Self {
1237        self.lint_id = Some(id);
1238        self
1239    } }
1240
1241    "See [`Diag::primary_message()`]."
&mut Self
self
msg
&mut Self
"See [`Diag::primary_message()`]."
mut self
msg
Self
self.primary_message(msg);
self;with_fn! { with_primary_message,
1242    /// Add a primary message.
1243    pub fn primary_message(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
1244        self.messages[0] = (msg.into(), Style::NoStyle);
1245        self
1246    } }
1247
1248    "See [`Diag::arg()`]."
&mut Self
self
name
arg
&mut Self
"See [`Diag::arg()`]."
mut self
name
arg
Self
self.arg(name, arg);
self;with_fn! { with_arg,
1249    /// Add an argument.
1250    pub fn arg(
1251        &mut self,
1252        name: impl Into<DiagArgName>,
1253        arg: impl IntoDiagArg,
1254    ) -> &mut Self {
1255        self.deref_mut().arg(name, arg);
1256        self
1257    } }
1258
1259    /// Helper function that takes a `SubdiagMessage` and returns a `DiagMessage` by
1260    /// combining it with the primary message of the diagnostic (if translatable, otherwise it just
1261    /// passes the user's string along).
1262    pub(crate) fn subdiagnostic_message_to_diagnostic_message(
1263        &self,
1264        attr: impl Into<SubdiagMessage>,
1265    ) -> DiagMessage {
1266        self.deref().subdiagnostic_message_to_diagnostic_message(attr)
1267    }
1268
1269    /// Convenience function for internal use, clients should use one of the
1270    /// public methods above.
1271    ///
1272    /// Used by `proc_macro_server` for implementing `server::Diagnostic`.
1273    pub fn sub(&mut self, level: Level, message: impl Into<SubdiagMessage>, span: MultiSpan) {
1274        self.deref_mut().sub(level, message, span);
1275    }
1276
1277    /// Convenience function for internal use, clients should use one of the
1278    /// public methods above.
1279    fn sub_with_highlights(&mut self, level: Level, messages: Vec<StringPart>, span: MultiSpan) {
1280        let messages = messages
1281            .into_iter()
1282            .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.content), m.style))
1283            .collect();
1284        let sub = Subdiag { level, messages, span };
1285        self.children.push(sub);
1286    }
1287
1288    /// Takes the diagnostic. For use by methods that consume the Diag: `emit`,
1289    /// `cancel`, etc. Afterwards, `drop` is the only code that will be run on
1290    /// `self`.
1291    fn take_diag(&mut self) -> DiagInner {
1292        if let Some(path) = &self.long_ty_path {
1293            self.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the full name for the type has been written to \'{0}\'",
                path.display()))
    })format!(
1294                "the full name for the type has been written to '{}'",
1295                path.display()
1296            ));
1297            self.note("consider using `--verbose` to print the full type name to the console");
1298        }
1299        *self.diag.take().unwrap()
1300    }
1301
1302    /// This method allows us to access the path of the file where "long types" are written to.
1303    ///
1304    /// When calling `Diag::emit`, as part of that we will check if a `long_ty_path` has been set,
1305    /// and if it has been then we add a note mentioning the file where the "long types" were
1306    /// written to.
1307    ///
1308    /// When calling `tcx.short_string()` after a `Diag` is constructed, the preferred way of doing
1309    /// so is `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that
1310    /// keeps the existence of a "long type" anywhere in the diagnostic, so the note telling the
1311    /// user where we wrote the file to is only printed once at most, *and* it makes it much harder
1312    /// to forget to set it.
1313    ///
1314    /// If the diagnostic hasn't been created before a "short ty string" is created, then you should
1315    /// ensure that this method is called to set it `*diag.long_ty_path() = path`.
1316    ///
1317    /// As a rule of thumb, if you see or add at least one `tcx.short_string()` call anywhere, in a
1318    /// scope, `diag.long_ty_path()` should be called once somewhere close by.
1319    pub fn long_ty_path(&mut self) -> &mut Option<PathBuf> {
1320        &mut self.long_ty_path
1321    }
1322
1323    pub fn with_long_ty_path(mut self, long_ty_path: Option<PathBuf>) -> Self {
1324        self.long_ty_path = long_ty_path;
1325        self
1326    }
1327
1328    /// Most `emit_producing_guarantee` functions use this as a starting point.
1329    fn emit_producing_nothing(mut self) {
1330        let diag = self.take_diag();
1331        self.dcx.emit_diagnostic(diag);
1332    }
1333
1334    /// `ErrorGuaranteed::emit_producing_guarantee` uses this.
1335    fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed {
1336        let diag = self.take_diag();
1337
1338        // The only error levels that produce `ErrorGuaranteed` are
1339        // `Error` and `DelayedBug`. But `DelayedBug` should never occur here
1340        // because delayed bugs have their level changed to `Bug` when they are
1341        // actually printed, so they produce an ICE.
1342        //
1343        // (Also, even though `level` isn't `pub`, the whole `DiagInner` could
1344        // be overwritten with a new one thanks to `DerefMut`. So this assert
1345        // protects against that, too.)
1346        if !#[allow(non_exhaustive_omitted_patterns)] match diag.level {
            Level::Error | Level::DelayedBug => true,
            _ => false,
        } {
    {
        ::core::panicking::panic_fmt(format_args!("invalid diagnostic level ({0:?})",
                diag.level));
    }
};assert!(
1347            matches!(diag.level, Level::Error | Level::DelayedBug),
1348            "invalid diagnostic level ({:?})",
1349            diag.level,
1350        );
1351
1352        let guar = self.dcx.emit_diagnostic(diag);
1353        guar.unwrap()
1354    }
1355
1356    /// Emit and consume the diagnostic.
1357    #[track_caller]
1358    pub fn emit(self) -> G::EmitResult {
1359        G::emit_producing_guarantee(self)
1360    }
1361
1362    /// Emit the diagnostic unless `delay` is true,
1363    /// in which case the emission will be delayed as a bug.
1364    ///
1365    /// See `emit` and `delay_as_bug` for details.
1366    #[track_caller]
1367    pub fn emit_unless_delay(mut self, delay: bool) -> G::EmitResult {
1368        if delay {
1369            self.downgrade_to_delayed_bug();
1370        }
1371        self.emit()
1372    }
1373
1374    /// Cancel and consume the diagnostic. (A diagnostic must either be emitted or
1375    /// cancelled or it will panic when dropped).
1376    pub fn cancel(mut self) {
1377        self.diag = None;
1378        drop(self);
1379    }
1380
1381    /// See `DiagCtxt::stash_diagnostic` for details.
1382    pub fn stash(mut self, span: Span, key: StashKey) -> Option<ErrorGuaranteed> {
1383        let diag = self.take_diag();
1384        self.dcx.stash_diagnostic(span, key, diag)
1385    }
1386
1387    /// Delay emission of this diagnostic as a bug.
1388    ///
1389    /// This can be useful in contexts where an error indicates a bug but
1390    /// typically this only happens when other compilation errors have already
1391    /// happened. In those cases this can be used to defer emission of this
1392    /// diagnostic as a bug in the compiler only if no other errors have been
1393    /// emitted.
1394    ///
1395    /// In the meantime, though, callsites are required to deal with the "bug"
1396    /// locally in whichever way makes the most sense.
1397    #[track_caller]
1398    pub fn delay_as_bug(mut self) -> G::EmitResult {
1399        self.downgrade_to_delayed_bug();
1400        self.emit()
1401    }
1402
1403    pub fn remove_arg(&mut self, name: &str) {
1404        if let Some(diag) = self.diag.as_mut() {
1405            diag.remove_arg(name);
1406        }
1407    }
1408}
1409
1410/// Destructor bomb: every `Diag` must be consumed (emitted, cancelled, etc.)
1411/// or we emit a bug.
1412impl<G: EmissionGuarantee> Drop for Diag<'_, G> {
1413    fn drop(&mut self) {
1414        match self.diag.take() {
1415            Some(diag) if !panicking() => {
1416                self.dcx.emit_diagnostic(DiagInner::new(
1417                    Level::Bug,
1418                    DiagMessage::from("the following error was constructed but not emitted"),
1419                ));
1420                self.dcx.emit_diagnostic(*diag);
1421                {
    ::core::panicking::panic_fmt(format_args!("error was constructed but not emitted"));
};panic!("error was constructed but not emitted");
1422            }
1423            _ => {}
1424        }
1425    }
1426}
1427
1428#[macro_export]
1429macro_rules! struct_span_code_err {
1430    ($dcx:expr, $span:expr, $code:expr, $($message:tt)*) => ({
1431        $dcx.struct_span_err($span, format!($($message)*)).with_code($code)
1432    })
1433}