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