Skip to main content

rustc_trait_selection/error_reporting/traits/
on_unimplemented.rs

1use std::iter;
2use std::path::PathBuf;
3
4use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit};
5use rustc_errors::codes::*;
6use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
7use rustc_hir as hir;
8use rustc_hir::def::DefKind;
9use rustc_hir::def_id::{DefId, LocalDefId};
10use rustc_hir::{AttrArgs, Attribute};
11use rustc_macros::LintDiagnostic;
12use rustc_middle::bug;
13use rustc_middle::ty::print::PrintTraitRefExt;
14use rustc_middle::ty::{self, GenericArgsRef, GenericParamDef, GenericParamDefKind, TyCtxt};
15use rustc_session::lint::builtin::{
16    MALFORMED_DIAGNOSTIC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
17};
18use rustc_span::{Span, Symbol, sym};
19use tracing::{debug, info};
20
21use super::{ObligationCauseCode, PredicateObligation};
22use crate::error_reporting::TypeErrCtxt;
23use crate::error_reporting::traits::on_unimplemented_condition::{
24    ConditionOptions, OnUnimplementedCondition,
25};
26use crate::error_reporting::traits::on_unimplemented_format::{
27    Ctx, FormatArgs, FormatString, FormatWarning,
28};
29use crate::errors::{InvalidOnClause, NoValueInOnUnimplemented};
30use crate::infer::InferCtxtExt;
31
32impl<'tcx> TypeErrCtxt<'_, 'tcx> {
33    fn impl_similar_to(
34        &self,
35        trait_pred: ty::PolyTraitPredicate<'tcx>,
36        obligation: &PredicateObligation<'tcx>,
37    ) -> Option<(DefId, GenericArgsRef<'tcx>)> {
38        let tcx = self.tcx;
39        let param_env = obligation.param_env;
40        self.enter_forall(trait_pred, |trait_pred| {
41            let trait_self_ty = trait_pred.self_ty();
42
43            let mut self_match_impls = ::alloc::vec::Vec::new()vec![];
44            let mut fuzzy_match_impls = ::alloc::vec::Vec::new()vec![];
45
46            self.tcx.for_each_relevant_impl(trait_pred.def_id(), trait_self_ty, |def_id| {
47                let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id);
48                let impl_trait_ref = tcx.impl_trait_ref(def_id).instantiate(tcx, impl_args);
49
50                let impl_self_ty = impl_trait_ref.self_ty();
51
52                if self.can_eq(param_env, trait_self_ty, impl_self_ty) {
53                    self_match_impls.push((def_id, impl_args));
54
55                    if iter::zip(
56                        trait_pred.trait_ref.args.types().skip(1),
57                        impl_trait_ref.args.types().skip(1),
58                    )
59                    .all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some())
60                    {
61                        fuzzy_match_impls.push((def_id, impl_args));
62                    }
63                }
64            });
65
66            let impl_def_id_and_args = if let [impl_] = self_match_impls[..] {
67                impl_
68            } else if let [impl_] = fuzzy_match_impls[..] {
69                impl_
70            } else {
71                return None;
72            };
73
74            #[allow(deprecated)]
75            tcx.has_attr(impl_def_id_and_args.0, sym::rustc_on_unimplemented)
76                .then_some(impl_def_id_and_args)
77        })
78    }
79
80    /// Used to set on_unimplemented's `ItemContext`
81    /// to be the enclosing (async) block/function/closure
82    fn describe_enclosure(&self, def_id: LocalDefId) -> Option<&'static str> {
83        match self.tcx.hir_node_by_def_id(def_id) {
84            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { .. }, .. }) => Some("a function"),
85            hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) => {
86                Some("a trait method")
87            }
88            hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
89                Some("a method")
90            }
91            hir::Node::Expr(hir::Expr {
92                kind: hir::ExprKind::Closure(hir::Closure { kind, .. }),
93                ..
94            }) => Some(self.describe_closure(*kind)),
95            _ => None,
96        }
97    }
98
99    pub fn on_unimplemented_note(
100        &self,
101        trait_pred: ty::PolyTraitPredicate<'tcx>,
102        obligation: &PredicateObligation<'tcx>,
103        long_ty_path: &mut Option<PathBuf>,
104    ) -> OnUnimplementedNote {
105        if trait_pred.polarity() != ty::PredicatePolarity::Positive {
106            return OnUnimplementedNote::default();
107        }
108        let (condition_options, format_args) =
109            self.on_unimplemented_components(trait_pred, obligation, long_ty_path);
110        if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, trait_pred.def_id())
111        {
112            command.evaluate(
113                self.tcx,
114                trait_pred.skip_binder().trait_ref,
115                &condition_options,
116                &format_args,
117            )
118        } else {
119            OnUnimplementedNote::default()
120        }
121    }
122
123    pub(crate) fn on_unimplemented_components(
124        &self,
125        trait_pred: ty::PolyTraitPredicate<'tcx>,
126        obligation: &PredicateObligation<'tcx>,
127        long_ty_path: &mut Option<PathBuf>,
128    ) -> (ConditionOptions, FormatArgs<'tcx>) {
129        let (def_id, args) = self
130            .impl_similar_to(trait_pred, obligation)
131            .unwrap_or_else(|| (trait_pred.def_id(), trait_pred.skip_binder().trait_ref.args));
132        let trait_pred = trait_pred.skip_binder();
133
134        let mut self_types = ::alloc::vec::Vec::new()vec![];
135        let mut generic_args: Vec<(Symbol, String)> = ::alloc::vec::Vec::new()vec![];
136        let mut crate_local = false;
137        // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs,
138        // but I guess we could synthesize one here. We don't see any errors that rely on
139        // that yet, though.
140        let item_context = self.describe_enclosure(obligation.cause.body_id).unwrap_or("");
141
142        let direct = match obligation.cause.code() {
143            ObligationCauseCode::BuiltinDerived(..)
144            | ObligationCauseCode::ImplDerived(..)
145            | ObligationCauseCode::WellFormedDerived(..) => false,
146            _ => {
147                // this is a "direct", user-specified, rather than derived,
148                // obligation.
149                true
150            }
151        };
152
153        let from_desugaring = obligation.cause.span.desugaring_kind();
154
155        let cause = if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
156            Some("MainFunctionType".to_string())
157        } else {
158            None
159        };
160
161        // Add all types without trimmed paths or visible paths, ensuring they end up with
162        // their "canonical" def path.
163        {
    let _guard = NoTrimmedGuard::new();
    {
        let _guard = NoVisibleGuard::new();
        {
            let generics = self.tcx.generics_of(def_id);
            let self_ty = trait_pred.self_ty();
            self_types.push(self_ty.to_string());
            if let Some(def) = self_ty.ty_adt_def() {
                self_types.push(self.tcx.type_of(def.did()).instantiate_identity().to_string());
            }
            for GenericParamDef { name, kind, index, .. } in
                generics.own_params.iter() {
                let value =
                    match kind {
                        GenericParamDefKind::Type { .. } |
                            GenericParamDefKind::Const { .. } => {
                            args[*index as usize].to_string()
                        }
                        GenericParamDefKind::Lifetime => continue,
                    };
                generic_args.push((*name, value));
                if let GenericParamDefKind::Type { .. } = kind {
                    let param_ty = args[*index as usize].expect_ty();
                    if let Some(def) = param_ty.ty_adt_def() {
                        generic_args.push((*name,
                                self.tcx.type_of(def.did()).instantiate_identity().to_string()));
                    }
                }
            }
            if let Some(true) =
                    self_ty.ty_adt_def().map(|def| def.did().is_local()) {
                crate_local = true;
            }
            if self_ty.is_integral() {
                self_types.push("{integral}".to_owned());
            }
            if self_ty.is_array_slice() { self_types.push("&[]".to_owned()); }
            if self_ty.is_fn() {
                let fn_sig = self_ty.fn_sig(self.tcx);
                let shortname =
                    if let ty::FnDef(def_id, _) = self_ty.kind() &&
                            self.tcx.codegen_fn_attrs(def_id).safe_target_features {
                        "#[target_feature] fn"
                    } else {
                        match fn_sig.safety() {
                            hir::Safety::Safe => "fn",
                            hir::Safety::Unsafe => "unsafe fn",
                        }
                    };
                self_types.push(shortname.to_owned());
            }
            if let ty::Slice(aty) = self_ty.kind() {
                self_types.push("[]".to_owned());
                if let Some(def) = aty.ty_adt_def() {
                    self_types.push(::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!("[{0}]",
                                        self.tcx.type_of(def.did()).instantiate_identity()))
                            }));
                }
                if aty.is_integral() {
                    self_types.push("[{integral}]".to_string());
                }
            }
            if let ty::Array(aty, len) = self_ty.kind() {
                self_types.push("[]".to_string());
                let len = len.try_to_target_usize(self.tcx);
                self_types.push(::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("[{0}; _]", aty))
                        }));
                if let Some(n) = len {
                    self_types.push(::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!("[{0}; {1}]", aty, n))
                            }));
                }
                if let Some(def) = aty.ty_adt_def() {
                    let def_ty =
                        self.tcx.type_of(def.did()).instantiate_identity();
                    self_types.push(::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!("[{0}; _]", def_ty))
                            }));
                    if let Some(n) = len {
                        self_types.push(::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("[{0}; {1}]", def_ty, n))
                                }));
                    }
                }
                if aty.is_integral() {
                    self_types.push("[{integral}; _]".to_string());
                    if let Some(n) = len {
                        self_types.push(::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("[{{integral}}; {0}]", n))
                                }));
                    }
                }
            }
            if let ty::Dynamic(traits, _) = self_ty.kind() {
                for t in traits.iter() {
                    if let ty::ExistentialPredicate::Trait(trait_ref) =
                            t.skip_binder() {
                        self_types.push(self.tcx.def_path_str(trait_ref.def_id));
                    }
                }
            }
            if let ty::Ref(_, ref_ty, rustc_ast::Mutability::Not) =
                            self_ty.kind() && let ty::Slice(sty) = ref_ty.kind() &&
                    sty.is_integral() {
                self_types.push("&[{integral}]".to_owned());
            }
        }
    }
};ty::print::with_no_trimmed_paths!(ty::print::with_no_visible_paths!({
164            let generics = self.tcx.generics_of(def_id);
165            let self_ty = trait_pred.self_ty();
166            self_types.push(self_ty.to_string());
167            if let Some(def) = self_ty.ty_adt_def() {
168                // We also want to be able to select self's original
169                // signature with no type arguments resolved
170                self_types.push(self.tcx.type_of(def.did()).instantiate_identity().to_string());
171            }
172
173            for GenericParamDef { name, kind, index, .. } in generics.own_params.iter() {
174                let value = match kind {
175                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
176                        args[*index as usize].to_string()
177                    }
178                    GenericParamDefKind::Lifetime => continue,
179                };
180                generic_args.push((*name, value));
181
182                if let GenericParamDefKind::Type { .. } = kind {
183                    let param_ty = args[*index as usize].expect_ty();
184                    if let Some(def) = param_ty.ty_adt_def() {
185                        // We also want to be able to select the parameter's
186                        // original signature with no type arguments resolved
187                        generic_args.push((
188                            *name,
189                            self.tcx.type_of(def.did()).instantiate_identity().to_string(),
190                        ));
191                    }
192                }
193            }
194
195            if let Some(true) = self_ty.ty_adt_def().map(|def| def.did().is_local()) {
196                crate_local = true;
197            }
198
199            // Allow targeting all integers using `{integral}`, even if the exact type was resolved
200            if self_ty.is_integral() {
201                self_types.push("{integral}".to_owned());
202            }
203
204            if self_ty.is_array_slice() {
205                self_types.push("&[]".to_owned());
206            }
207
208            if self_ty.is_fn() {
209                let fn_sig = self_ty.fn_sig(self.tcx);
210                let shortname = if let ty::FnDef(def_id, _) = self_ty.kind()
211                    && self.tcx.codegen_fn_attrs(def_id).safe_target_features
212                {
213                    "#[target_feature] fn"
214                } else {
215                    match fn_sig.safety() {
216                        hir::Safety::Safe => "fn",
217                        hir::Safety::Unsafe => "unsafe fn",
218                    }
219                };
220                self_types.push(shortname.to_owned());
221            }
222
223            // Slices give us `[]`, `[{ty}]`
224            if let ty::Slice(aty) = self_ty.kind() {
225                self_types.push("[]".to_owned());
226                if let Some(def) = aty.ty_adt_def() {
227                    // We also want to be able to select the slice's type's original
228                    // signature with no type arguments resolved
229                    self_types
230                        .push(format!("[{}]", self.tcx.type_of(def.did()).instantiate_identity()));
231                }
232                if aty.is_integral() {
233                    self_types.push("[{integral}]".to_string());
234                }
235            }
236
237            // Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
238            if let ty::Array(aty, len) = self_ty.kind() {
239                self_types.push("[]".to_string());
240                let len = len.try_to_target_usize(self.tcx);
241                self_types.push(format!("[{aty}; _]"));
242                if let Some(n) = len {
243                    self_types.push(format!("[{aty}; {n}]"));
244                }
245                if let Some(def) = aty.ty_adt_def() {
246                    // We also want to be able to select the array's type's original
247                    // signature with no type arguments resolved
248                    let def_ty = self.tcx.type_of(def.did()).instantiate_identity();
249                    self_types.push(format!("[{def_ty}; _]"));
250                    if let Some(n) = len {
251                        self_types.push(format!("[{def_ty}; {n}]"));
252                    }
253                }
254                if aty.is_integral() {
255                    self_types.push("[{integral}; _]".to_string());
256                    if let Some(n) = len {
257                        self_types.push(format!("[{{integral}}; {n}]"));
258                    }
259                }
260            }
261            if let ty::Dynamic(traits, _) = self_ty.kind() {
262                for t in traits.iter() {
263                    if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() {
264                        self_types.push(self.tcx.def_path_str(trait_ref.def_id));
265                    }
266                }
267            }
268
269            // `&[{integral}]` - `FromIterator` needs that.
270            if let ty::Ref(_, ref_ty, rustc_ast::Mutability::Not) = self_ty.kind()
271                && let ty::Slice(sty) = ref_ty.kind()
272                && sty.is_integral()
273            {
274                self_types.push("&[{integral}]".to_owned());
275            }
276        }));
277
278        let this = self.tcx.def_path_str(trait_pred.trait_ref.def_id);
279        let trait_sugared = trait_pred.trait_ref.print_trait_sugared();
280
281        let condition_options = ConditionOptions {
282            self_types,
283            from_desugaring,
284            cause,
285            crate_local,
286            direct,
287            generic_args,
288        };
289
290        // Unlike the generic_args earlier,
291        // this one is *not* collected under `with_no_trimmed_paths!`
292        // for printing the type to the user
293        //
294        // This includes `Self`, as it is the first parameter in `own_params`.
295        let generic_args = self
296            .tcx
297            .generics_of(trait_pred.trait_ref.def_id)
298            .own_params
299            .iter()
300            .filter_map(|param| {
301                let value = match param.kind {
302                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
303                        if let Some(ty) = trait_pred.trait_ref.args[param.index as usize].as_type()
304                        {
305                            self.tcx.short_string(ty, long_ty_path)
306                        } else {
307                            trait_pred.trait_ref.args[param.index as usize].to_string()
308                        }
309                    }
310                    GenericParamDefKind::Lifetime => return None,
311                };
312                let name = param.name;
313                Some((name, value))
314            })
315            .collect();
316
317        let format_args = FormatArgs { this, trait_sugared, generic_args, item_context };
318        (condition_options, format_args)
319    }
320}
321
322/// Represents a format string in a on_unimplemented attribute,
323/// like the "content" in `#[diagnostic::on_unimplemented(message = "content")]`
324#[derive(#[automatically_derived]
impl ::core::clone::Clone for OnUnimplementedFormatString {
    #[inline]
    fn clone(&self) -> OnUnimplementedFormatString {
        OnUnimplementedFormatString {
            symbol: ::core::clone::Clone::clone(&self.symbol),
            span: ::core::clone::Clone::clone(&self.span),
            is_diagnostic_namespace_variant: ::core::clone::Clone::clone(&self.is_diagnostic_namespace_variant),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for OnUnimplementedFormatString {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "OnUnimplementedFormatString", "symbol", &self.symbol, "span",
            &self.span, "is_diagnostic_namespace_variant",
            &&self.is_diagnostic_namespace_variant)
    }
}Debug)]
325pub struct OnUnimplementedFormatString {
326    /// Symbol of the format string, i.e. `"content"`
327    symbol: Symbol,
328    /// The span of the format string, i.e. `"content"`
329    span: Span,
330    is_diagnostic_namespace_variant: bool,
331}
332
333#[derive(#[automatically_derived]
impl ::core::fmt::Debug for OnUnimplementedDirective {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["condition", "subcommands", "message", "label", "notes",
                        "parent_label", "append_const_msg"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.condition, &self.subcommands, &self.message, &self.label,
                        &self.notes, &self.parent_label, &&self.append_const_msg];
        ::core::fmt::Formatter::debug_struct_fields_finish(f,
            "OnUnimplementedDirective", names, values)
    }
}Debug)]
334pub struct OnUnimplementedDirective {
335    condition: Option<OnUnimplementedCondition>,
336    subcommands: Vec<OnUnimplementedDirective>,
337    message: Option<(Span, OnUnimplementedFormatString)>,
338    label: Option<(Span, OnUnimplementedFormatString)>,
339    notes: Vec<OnUnimplementedFormatString>,
340    parent_label: Option<OnUnimplementedFormatString>,
341    append_const_msg: Option<AppendConstMessage>,
342}
343
344/// For the `#[rustc_on_unimplemented]` attribute
345#[derive(#[automatically_derived]
impl ::core::default::Default for OnUnimplementedNote {
    #[inline]
    fn default() -> OnUnimplementedNote {
        OnUnimplementedNote {
            message: ::core::default::Default::default(),
            label: ::core::default::Default::default(),
            notes: ::core::default::Default::default(),
            parent_label: ::core::default::Default::default(),
            append_const_msg: ::core::default::Default::default(),
        }
    }
}Default, #[automatically_derived]
impl ::core::fmt::Debug for OnUnimplementedNote {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field5_finish(f,
            "OnUnimplementedNote", "message", &self.message, "label",
            &self.label, "notes", &self.notes, "parent_label",
            &self.parent_label, "append_const_msg", &&self.append_const_msg)
    }
}Debug)]
346pub struct OnUnimplementedNote {
347    pub message: Option<String>,
348    pub label: Option<String>,
349    pub notes: Vec<String>,
350    pub parent_label: Option<String>,
351    // If none, should fall back to a generic message
352    pub append_const_msg: Option<AppendConstMessage>,
353}
354
355/// Append a message for `[const] Trait` errors.
356#[derive(#[automatically_derived]
impl ::core::clone::Clone for AppendConstMessage {
    #[inline]
    fn clone(&self) -> AppendConstMessage {
        let _: ::core::clone::AssertParamIsClone<Symbol>;
        let _: ::core::clone::AssertParamIsClone<Span>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for AppendConstMessage { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for AppendConstMessage {
    #[inline]
    fn eq(&self, other: &AppendConstMessage) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (AppendConstMessage::Custom(__self_0, __self_1),
                    AppendConstMessage::Custom(__arg1_0, __arg1_1)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for AppendConstMessage {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Symbol>;
        let _: ::core::cmp::AssertParamIsEq<Span>;
    }
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for AppendConstMessage {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            AppendConstMessage::Default =>
                ::core::fmt::Formatter::write_str(f, "Default"),
            AppendConstMessage::Custom(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f, "Custom",
                    __self_0, &__self_1),
        }
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for AppendConstMessage {
    #[inline]
    fn default() -> AppendConstMessage { Self::Default }
}Default)]
357pub enum AppendConstMessage {
358    #[default]
359    Default,
360    Custom(Symbol, Span),
361}
362
363#[derive(const _: () =
    {
        impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for
            MalformedOnUnimplementedAttrLint {
            #[track_caller]
            fn decorate_lint<'__b>(self,
                diag: &'__b mut rustc_errors::Diag<'__a, ()>) {
                match self {
                    MalformedOnUnimplementedAttrLint { span: __binding_0 } => {
                        diag.primary_message(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("malformed `on_unimplemented` attribute")));
                        diag.help(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("only `message`, `note` and `label` are allowed as options")));
                        ;
                        diag.span_label(__binding_0,
                            rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("invalid option found here")));
                        diag
                    }
                };
            }
        }
    };LintDiagnostic)]
364#[diag("malformed `on_unimplemented` attribute")]
365#[help("only `message`, `note` and `label` are allowed as options")]
366pub struct MalformedOnUnimplementedAttrLint {
367    #[label("invalid option found here")]
368    pub span: Span,
369}
370
371impl MalformedOnUnimplementedAttrLint {
372    pub fn new(span: Span) -> Self {
373        Self { span }
374    }
375}
376
377#[derive(const _: () =
    {
        impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for
            MissingOptionsForOnUnimplementedAttr {
            #[track_caller]
            fn decorate_lint<'__b>(self,
                diag: &'__b mut rustc_errors::Diag<'__a, ()>) {
                match self {
                    MissingOptionsForOnUnimplementedAttr => {
                        diag.primary_message(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("missing options for `on_unimplemented` attribute")));
                        diag.help(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("at least one of the `message`, `note` and `label` options are expected")));
                        ;
                        diag
                    }
                };
            }
        }
    };LintDiagnostic)]
378#[diag("missing options for `on_unimplemented` attribute")]
379#[help("at least one of the `message`, `note` and `label` options are expected")]
380pub struct MissingOptionsForOnUnimplementedAttr;
381
382#[derive(const _: () =
    {
        impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for
            IgnoredDiagnosticOption {
            #[track_caller]
            fn decorate_lint<'__b>(self,
                diag: &'__b mut rustc_errors::Diag<'__a, ()>) {
                match self {
                    IgnoredDiagnosticOption {
                        option_name: __binding_0,
                        span: __binding_1,
                        prev_span: __binding_2 } => {
                        diag.primary_message(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("`{$option_name}` is ignored due to previous definition of `{$option_name}`")));
                        ;
                        diag.arg("option_name", __binding_0);
                        diag.span_label(__binding_1,
                            rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("`{$option_name}` is already declared here")));
                        diag.span_label(__binding_2,
                            rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("`{$option_name}` is first declared here")));
                        diag
                    }
                };
            }
        }
    };LintDiagnostic)]
383#[diag("`{$option_name}` is ignored due to previous definition of `{$option_name}`")]
384pub struct IgnoredDiagnosticOption {
385    pub option_name: &'static str,
386    #[label("`{$option_name}` is already declared here")]
387    pub span: Span,
388    #[label("`{$option_name}` is first declared here")]
389    pub prev_span: Span,
390}
391
392impl IgnoredDiagnosticOption {
393    pub fn maybe_emit_warning<'tcx>(
394        tcx: TyCtxt<'tcx>,
395        item_def_id: DefId,
396        new: Option<Span>,
397        old: Option<Span>,
398        option_name: &'static str,
399    ) {
400        if let (Some(new_item), Some(old_item)) = (new, old)
401            && let Some(item_def_id) = item_def_id.as_local()
402        {
403            tcx.emit_node_span_lint(
404                MALFORMED_DIAGNOSTIC_ATTRIBUTES,
405                tcx.local_def_id_to_hir_id(item_def_id),
406                new_item,
407                IgnoredDiagnosticOption { span: new_item, prev_span: old_item, option_name },
408            );
409        }
410    }
411}
412
413#[derive(const _: () =
    {
        impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for
            WrappedParserError {
            #[track_caller]
            fn decorate_lint<'__b>(self,
                diag: &'__b mut rustc_errors::Diag<'__a, ()>) {
                match self {
                    WrappedParserError {
                        description: __binding_0, label: __binding_1 } => {
                        diag.primary_message(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("{$description}")));
                        ;
                        diag.arg("description", __binding_0);
                        diag.arg("label", __binding_1);
                        diag
                    }
                };
            }
        }
    };LintDiagnostic)]
414#[diag("{$description}")]
415pub struct WrappedParserError {
416    pub description: String,
417    pub label: String,
418}
419
420impl<'tcx> OnUnimplementedDirective {
421    fn parse(
422        tcx: TyCtxt<'tcx>,
423        item_def_id: DefId,
424        items: &[MetaItemInner],
425        span: Span,
426        is_root: bool,
427        is_diagnostic_namespace_variant: bool,
428    ) -> Result<Option<Self>, ErrorGuaranteed> {
429        let mut errored = None;
430        let mut item_iter = items.iter();
431
432        let parse_value = |value_str, span| {
433            OnUnimplementedFormatString::try_parse(
434                tcx,
435                item_def_id,
436                value_str,
437                span,
438                is_diagnostic_namespace_variant,
439            )
440            .map(Some)
441        };
442
443        let condition = if is_root {
444            None
445        } else {
446            let cond = item_iter
447                .next()
448                .ok_or_else(|| tcx.dcx().emit_err(InvalidOnClause::Empty { span }))?;
449
450            let generics: Vec<Symbol> = tcx
451                .generics_of(item_def_id)
452                .own_params
453                .iter()
454                .filter_map(|param| {
455                    if #[allow(non_exhaustive_omitted_patterns)] match param.kind {
    GenericParamDefKind::Lifetime => true,
    _ => false,
}matches!(param.kind, GenericParamDefKind::Lifetime) {
456                        None
457                    } else {
458                        Some(param.name)
459                    }
460                })
461                .collect();
462            match OnUnimplementedCondition::parse(cond, &generics) {
463                Ok(condition) => Some(condition),
464                Err(e) => return Err(tcx.dcx().emit_err(e)),
465            }
466        };
467
468        let mut message = None;
469        let mut label = None;
470        let mut notes = Vec::new();
471        let mut parent_label = None;
472        let mut subcommands = ::alloc::vec::Vec::new()vec![];
473        let mut append_const_msg = None;
474
475        let get_value_and_span = |item: &_, key| {
476            if let MetaItemInner::MetaItem(MetaItem {
477                path,
478                kind: MetaItemKind::NameValue(MetaItemLit { span, kind: LitKind::Str(s, _), .. }),
479                ..
480            }) = item
481                && *path == key
482            {
483                Some((*s, *span))
484            } else {
485                None
486            }
487        };
488
489        for item in item_iter {
490            if let Some((message_, span)) = get_value_and_span(item, sym::message)
491                && message.is_none()
492            {
493                message = parse_value(message_, span)?.map(|l| (item.span(), l));
494                continue;
495            } else if let Some((label_, span)) = get_value_and_span(item, sym::label)
496                && label.is_none()
497            {
498                label = parse_value(label_, span)?.map(|l| (item.span(), l));
499                continue;
500            } else if let Some((note_, span)) = get_value_and_span(item, sym::note) {
501                if let Some(note) = parse_value(note_, span)? {
502                    notes.push(note);
503                    continue;
504                }
505            } else if item.has_name(sym::parent_label)
506                && parent_label.is_none()
507                && !is_diagnostic_namespace_variant
508            {
509                if let Some(parent_label_) = item.value_str() {
510                    parent_label = parse_value(parent_label_, item.span())?;
511                    continue;
512                }
513            } else if item.has_name(sym::on)
514                && is_root
515                && message.is_none()
516                && label.is_none()
517                && notes.is_empty()
518                && !is_diagnostic_namespace_variant
519            // FIXME(diagnostic_namespace): disallow filters for now
520            {
521                if let Some(items) = item.meta_item_list() {
522                    match Self::parse(
523                        tcx,
524                        item_def_id,
525                        items,
526                        item.span(),
527                        false,
528                        is_diagnostic_namespace_variant,
529                    ) {
530                        Ok(Some(subcommand)) => subcommands.push(subcommand),
531                        Ok(None) => ::rustc_middle::util::bug::bug_fmt(format_args!("This cannot happen for now as we only reach that if `is_diagnostic_namespace_variant` is false"))bug!(
532                            "This cannot happen for now as we only reach that if `is_diagnostic_namespace_variant` is false"
533                        ),
534                        Err(reported) => errored = Some(reported),
535                    };
536                    continue;
537                }
538            } else if item.has_name(sym::append_const_msg)
539                && append_const_msg.is_none()
540                && !is_diagnostic_namespace_variant
541            {
542                if let Some(msg) = item.value_str() {
543                    append_const_msg = Some(AppendConstMessage::Custom(msg, item.span()));
544                    continue;
545                } else if item.is_word() {
546                    append_const_msg = Some(AppendConstMessage::Default);
547                    continue;
548                }
549            }
550
551            if is_diagnostic_namespace_variant {
552                if let Some(def_id) = item_def_id.as_local() {
553                    tcx.emit_node_span_lint(
554                        MALFORMED_DIAGNOSTIC_ATTRIBUTES,
555                        tcx.local_def_id_to_hir_id(def_id),
556                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [item.span()]))vec![item.span()],
557                        MalformedOnUnimplementedAttrLint::new(item.span()),
558                    );
559                }
560            } else {
561                // nothing found
562                tcx.dcx().emit_err(NoValueInOnUnimplemented { span: item.span() });
563            }
564        }
565
566        if let Some(reported) = errored {
567            if is_diagnostic_namespace_variant { Ok(None) } else { Err(reported) }
568        } else {
569            Ok(Some(OnUnimplementedDirective {
570                condition,
571                subcommands,
572                message,
573                label,
574                notes,
575                parent_label,
576                append_const_msg,
577            }))
578        }
579    }
580
581    pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<Option<Self>, ErrorGuaranteed> {
582        let attr = if tcx.is_trait(item_def_id) {
583            sym::on_unimplemented
584        } else if let DefKind::Impl { of_trait: true } = tcx.def_kind(item_def_id) {
585            sym::on_const
586        } else {
587            // It could be a trait_alias (`trait MyTrait = SomeOtherTrait`)
588            // or an implementation (`impl MyTrait for Foo {}`)
589            //
590            // We don't support those.
591            return Ok(None);
592        };
593        if let Some(attr) = {
594            #[allow(deprecated)]
595            tcx.get_attr(item_def_id, sym::rustc_on_unimplemented)
596        } {
597            return Self::parse_attribute(attr, false, tcx, item_def_id);
598        } else {
599            tcx.get_attrs_by_path(item_def_id, &[sym::diagnostic, attr])
600                .filter_map(|attr| Self::parse_attribute(attr, true, tcx, item_def_id).transpose())
601                .try_fold(None, |aggr: Option<Self>, directive| {
602                    let directive = directive?;
603                    if let Some(aggr) = aggr {
604                        let mut subcommands = aggr.subcommands;
605                        subcommands.extend(directive.subcommands);
606                        let mut notes = aggr.notes;
607                        notes.extend(directive.notes);
608                        IgnoredDiagnosticOption::maybe_emit_warning(
609                            tcx,
610                            item_def_id,
611                            directive.message.as_ref().map(|f| f.0),
612                            aggr.message.as_ref().map(|f| f.0),
613                            "message",
614                        );
615                        IgnoredDiagnosticOption::maybe_emit_warning(
616                            tcx,
617                            item_def_id,
618                            directive.label.as_ref().map(|f| f.0),
619                            aggr.label.as_ref().map(|f| f.0),
620                            "label",
621                        );
622                        IgnoredDiagnosticOption::maybe_emit_warning(
623                            tcx,
624                            item_def_id,
625                            directive.condition.as_ref().map(|i| i.span()),
626                            aggr.condition.as_ref().map(|i| i.span()),
627                            "condition",
628                        );
629                        IgnoredDiagnosticOption::maybe_emit_warning(
630                            tcx,
631                            item_def_id,
632                            directive.parent_label.as_ref().map(|f| f.span),
633                            aggr.parent_label.as_ref().map(|f| f.span),
634                            "parent_label",
635                        );
636                        IgnoredDiagnosticOption::maybe_emit_warning(
637                            tcx,
638                            item_def_id,
639                            directive.append_const_msg.as_ref().and_then(|c| {
640                                if let AppendConstMessage::Custom(_, s) = c {
641                                    Some(*s)
642                                } else {
643                                    None
644                                }
645                            }),
646                            aggr.append_const_msg.as_ref().and_then(|c| {
647                                if let AppendConstMessage::Custom(_, s) = c {
648                                    Some(*s)
649                                } else {
650                                    None
651                                }
652                            }),
653                            "append_const_msg",
654                        );
655
656                        Ok(Some(Self {
657                            condition: aggr.condition.or(directive.condition),
658                            subcommands,
659                            message: aggr.message.or(directive.message),
660                            label: aggr.label.or(directive.label),
661                            notes,
662                            parent_label: aggr.parent_label.or(directive.parent_label),
663                            append_const_msg: aggr.append_const_msg.or(directive.append_const_msg),
664                        }))
665                    } else {
666                        Ok(Some(directive))
667                    }
668                })
669        }
670    }
671
672    fn parse_attribute(
673        attr: &Attribute,
674        is_diagnostic_namespace_variant: bool,
675        tcx: TyCtxt<'tcx>,
676        item_def_id: DefId,
677    ) -> Result<Option<Self>, ErrorGuaranteed> {
678        let result = if let Some(items) = attr.meta_item_list() {
679            Self::parse(
680                tcx,
681                item_def_id,
682                &items,
683                attr.span(),
684                true,
685                is_diagnostic_namespace_variant,
686            )
687        } else if let Some(value) = attr.value_str() {
688            if !is_diagnostic_namespace_variant {
689                Ok(Some(OnUnimplementedDirective {
690                    condition: None,
691                    message: None,
692                    subcommands: ::alloc::vec::Vec::new()vec![],
693                    label: Some((
694                        attr.span(),
695                        OnUnimplementedFormatString::try_parse(
696                            tcx,
697                            item_def_id,
698                            value,
699                            attr.value_span().unwrap_or(attr.span()),
700                            is_diagnostic_namespace_variant,
701                        )?,
702                    )),
703                    notes: Vec::new(),
704                    parent_label: None,
705                    append_const_msg: None,
706                }))
707            } else {
708                let item = attr.get_normal_item();
709                let report_span = match &item.args {
710                    AttrArgs::Empty => item.path.span,
711                    AttrArgs::Delimited(args) => args.dspan.entire(),
712                    AttrArgs::Eq { eq_span, expr } => eq_span.to(expr.span),
713                };
714
715                if let Some(item_def_id) = item_def_id.as_local() {
716                    tcx.emit_node_span_lint(
717                        MALFORMED_DIAGNOSTIC_ATTRIBUTES,
718                        tcx.local_def_id_to_hir_id(item_def_id),
719                        report_span,
720                        MalformedOnUnimplementedAttrLint::new(report_span),
721                    );
722                }
723                Ok(None)
724            }
725        } else if is_diagnostic_namespace_variant {
726            match attr {
727                Attribute::Unparsed(p) if !#[allow(non_exhaustive_omitted_patterns)] match p.args {
    AttrArgs::Empty => true,
    _ => false,
}matches!(p.args, AttrArgs::Empty) => {
728                    if let Some(item_def_id) = item_def_id.as_local() {
729                        tcx.emit_node_span_lint(
730                            MALFORMED_DIAGNOSTIC_ATTRIBUTES,
731                            tcx.local_def_id_to_hir_id(item_def_id),
732                            attr.span(),
733                            MalformedOnUnimplementedAttrLint::new(attr.span()),
734                        );
735                    }
736                }
737                _ => {
738                    if let Some(item_def_id) = item_def_id.as_local() {
739                        tcx.emit_node_span_lint(
740                            MALFORMED_DIAGNOSTIC_ATTRIBUTES,
741                            tcx.local_def_id_to_hir_id(item_def_id),
742                            attr.span(),
743                            MissingOptionsForOnUnimplementedAttr,
744                        )
745                    }
746                }
747            };
748
749            Ok(None)
750        } else {
751            let reported = tcx.dcx().delayed_bug("of_item: neither meta_item_list nor value_str");
752            return Err(reported);
753        };
754        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs:754",
                        "rustc_trait_selection::error_reporting::traits::on_unimplemented",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs"),
                        ::tracing_core::__macro_support::Option::Some(754u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::on_unimplemented"),
                        ::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!("of_item({0:?}) = {1:?}",
                                                    item_def_id, result) as &dyn Value))])
            });
    } else { ; }
};debug!("of_item({:?}) = {:?}", item_def_id, result);
755        result
756    }
757
758    pub(crate) fn evaluate(
759        &self,
760        tcx: TyCtxt<'tcx>,
761        trait_ref: ty::TraitRef<'tcx>,
762        condition_options: &ConditionOptions,
763        args: &FormatArgs<'tcx>,
764    ) -> OnUnimplementedNote {
765        let mut message = None;
766        let mut label = None;
767        let mut notes = Vec::new();
768        let mut parent_label = None;
769        let mut append_const_msg = None;
770        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs:770",
                        "rustc_trait_selection::error_reporting::traits::on_unimplemented",
                        ::tracing::Level::INFO,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs"),
                        ::tracing_core::__macro_support::Option::Some(770u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::on_unimplemented"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::INFO <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::INFO <=
                    ::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!("evaluate({0:?}, trait_ref={1:?}, options={2:?}, args ={3:?})",
                                                    self, trait_ref, condition_options, args) as &dyn Value))])
            });
    } else { ; }
};info!(
771            "evaluate({:?}, trait_ref={:?}, options={:?}, args ={:?})",
772            self, trait_ref, condition_options, args
773        );
774
775        for command in self.subcommands.iter().chain(Some(self)).rev() {
776            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs:776",
                        "rustc_trait_selection::error_reporting::traits::on_unimplemented",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs"),
                        ::tracing_core::__macro_support::Option::Some(776u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::on_unimplemented"),
                        ::tracing_core::field::FieldSet::new(&["command"],
                            ::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(&debug(&command) as
                                            &dyn Value))])
            });
    } else { ; }
};debug!(?command);
777            if let Some(ref condition) = command.condition
778                && !condition.matches_predicate(condition_options)
779            {
780                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs:780",
                        "rustc_trait_selection::error_reporting::traits::on_unimplemented",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs"),
                        ::tracing_core::__macro_support::Option::Some(780u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::on_unimplemented"),
                        ::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!("evaluate: skipping {0:?} due to condition",
                                                    command) as &dyn Value))])
            });
    } else { ; }
};debug!("evaluate: skipping {:?} due to condition", command);
781                continue;
782            }
783            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs:783",
                        "rustc_trait_selection::error_reporting::traits::on_unimplemented",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs"),
                        ::tracing_core::__macro_support::Option::Some(783u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::on_unimplemented"),
                        ::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!("evaluate: {0:?} succeeded",
                                                    command) as &dyn Value))])
            });
    } else { ; }
};debug!("evaluate: {:?} succeeded", command);
784            if let Some(ref message_) = command.message {
785                message = Some(message_.clone());
786            }
787
788            if let Some(ref label_) = command.label {
789                label = Some(label_.clone());
790            }
791
792            notes.extend(command.notes.clone());
793
794            if let Some(ref parent_label_) = command.parent_label {
795                parent_label = Some(parent_label_.clone());
796            }
797
798            append_const_msg = command.append_const_msg;
799        }
800
801        OnUnimplementedNote {
802            label: label.map(|l| l.1.format(tcx, trait_ref, args)),
803            message: message.map(|m| m.1.format(tcx, trait_ref, args)),
804            notes: notes.into_iter().map(|n| n.format(tcx, trait_ref, args)).collect(),
805            parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, args)),
806            append_const_msg,
807        }
808    }
809}
810
811impl<'tcx> OnUnimplementedFormatString {
812    fn try_parse(
813        tcx: TyCtxt<'tcx>,
814        item_def_id: DefId,
815        from: Symbol,
816        span: Span,
817        is_diagnostic_namespace_variant: bool,
818    ) -> Result<Self, ErrorGuaranteed> {
819        let result =
820            OnUnimplementedFormatString { symbol: from, span, is_diagnostic_namespace_variant };
821        result.verify(tcx, item_def_id)?;
822        Ok(result)
823    }
824
825    fn verify(&self, tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> Result<(), ErrorGuaranteed> {
826        if !tcx.is_trait(trait_def_id) {
827            return Ok(());
828        };
829
830        let ctx = if self.is_diagnostic_namespace_variant {
831            Ctx::DiagnosticOnUnimplemented { tcx, trait_def_id }
832        } else {
833            Ctx::RustcOnUnimplemented { tcx, trait_def_id }
834        };
835
836        let mut result = Ok(());
837
838        let snippet = tcx.sess.source_map().span_to_snippet(self.span).ok();
839        match FormatString::parse(self.symbol, snippet, self.span, &ctx) {
840            // Warnings about format specifiers, deprecated parameters, wrong parameters etc.
841            // In other words we'd like to let the author know, but we can still try to format the string later
842            Ok(FormatString { warnings, .. }) => {
843                if self.is_diagnostic_namespace_variant {
844                    for w in warnings {
845                        w.emit_warning(tcx, trait_def_id)
846                    }
847                } else {
848                    for w in warnings {
849                        match w {
850                            FormatWarning::UnknownParam { argument_name, span } => {
851                                let reported = {
    tcx.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("cannot find parameter {0} on this trait",
                            argument_name))
                })).with_code(E0230)
}struct_span_code_err!(
852                                    tcx.dcx(),
853                                    span,
854                                    E0230,
855                                    "cannot find parameter {} on this trait",
856                                    argument_name,
857                                )
858                                .emit();
859                                result = Err(reported);
860                            }
861                            FormatWarning::PositionalArgument { span, .. } => {
862                                let reported = {
    tcx.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("positional format arguments are not allowed here"))
                })).with_code(E0231)
}struct_span_code_err!(
863                                    tcx.dcx(),
864                                    span,
865                                    E0231,
866                                    "positional format arguments are not allowed here"
867                                )
868                                .emit();
869                                result = Err(reported);
870                            }
871                            FormatWarning::InvalidSpecifier { .. }
872                            | FormatWarning::FutureIncompat { .. } => {}
873                        }
874                    }
875                }
876            }
877            // Error from the underlying `rustc_parse_format::Parser`
878            Err(e) => {
879                // we cannot return errors from processing the format string as hard error here
880                // as the diagnostic namespace guarantees that malformed input cannot cause an error
881                //
882                // if we encounter any error while processing we nevertheless want to show it as warning
883                // so that users are aware that something is not correct
884                if self.is_diagnostic_namespace_variant {
885                    if let Some(trait_def_id) = trait_def_id.as_local() {
886                        tcx.emit_node_span_lint(
887                            MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
888                            tcx.local_def_id_to_hir_id(trait_def_id),
889                            self.span,
890                            WrappedParserError { description: e.description, label: e.label },
891                        );
892                    }
893                } else {
894                    let reported =
895                        {
    tcx.dcx().struct_span_err(self.span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("{0}", e.description))
                })).with_code(E0231)
}struct_span_code_err!(tcx.dcx(), self.span, E0231, "{}", e.description)
896                            .emit();
897                    result = Err(reported);
898                }
899            }
900        }
901
902        result
903    }
904
905    pub fn format(
906        &self,
907        tcx: TyCtxt<'tcx>,
908        trait_ref: ty::TraitRef<'tcx>,
909        args: &FormatArgs<'tcx>,
910    ) -> String {
911        let trait_def_id = trait_ref.def_id;
912        let ctx = if self.is_diagnostic_namespace_variant {
913            Ctx::DiagnosticOnUnimplemented { tcx, trait_def_id }
914        } else {
915            Ctx::RustcOnUnimplemented { tcx, trait_def_id }
916        };
917
918        // No point passing a snippet here, we already did that in `verify`
919        if let Ok(s) = FormatString::parse(self.symbol, None, self.span, &ctx) {
920            s.format(args)
921        } else {
922            // we cannot return errors from processing the format string as hard error here
923            // as the diagnostic namespace guarantees that malformed input cannot cause an error
924            //
925            // if we encounter any error while processing the format string
926            // we don't want to show the potentially half assembled formatted string,
927            // therefore we fall back to just showing the input string in this case
928            //
929            // The actual parser errors are emitted earlier
930            // as lint warnings in OnUnimplementedFormatString::verify
931            self.symbol.as_str().into()
932        }
933    }
934}