Skip to main content

rustc_errors/
diagnostic.rs

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