Skip to main content

rustc_errors/
formatting.rs

1use std::borrow::Cow;
2
3pub use rustc_error_messages::FluentArgs;
4use rustc_error_messages::{DiagArgMap, DiagArgName, IntoDiagArg, langid, register_functions};
5use tracing::{debug, trace};
6
7use crate::fluent_bundle::FluentResource;
8use crate::{DiagArg, DiagMessage, Style, fluent_bundle};
9
10/// Convert diagnostic arguments (a rustc internal type that exists to implement
11/// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform formatting.
12fn to_fluent_args<'iter>(iter: impl Iterator<Item = DiagArg<'iter>>) -> FluentArgs<'static> {
13    let mut args = if let Some(size) = iter.size_hint().1 {
14        FluentArgs::with_capacity(size)
15    } else {
16        FluentArgs::new()
17    };
18
19    for (k, v) in iter {
20        args.set(k.clone(), v.clone());
21    }
22
23    args
24}
25
26/// Convert `DiagMessage`s to a string
27pub fn format_diag_messages(messages: &[(DiagMessage, Style)], args: &DiagArgMap) -> String {
28    messages.iter().map(|(m, _)| format_diag_message(m, args)).collect::<String>()
29}
30
31/// Convert a `DiagMessage` to a string
32pub fn format_diag_message<'a>(message: &'a DiagMessage, args: &DiagArgMap) -> Cow<'a, str> {
33    match message {
34        DiagMessage::Str(msg) => Cow::Borrowed(msg),
35        DiagMessage::Inline(msg) => format_fluent_str(msg, args),
36    }
37}
38
39fn format_fluent_str(message: &str, args: &DiagArgMap) -> Cow<'static, str> {
40    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_errors/src/formatting.rs:40",
                        "rustc_errors::formatting", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_errors/src/formatting.rs"),
                        ::tracing_core::__macro_support::Option::Some(40u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_errors::formatting"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("message")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("message");
                                            NAME.as_str()
                                        },
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("args")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("args");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::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(&::tracing::field::debug(&message)
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&args)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!(?message, ?args);
41    const GENERATED_MSG_ID: &str = "generated_msg";
42    let resource = FluentResource::try_new(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} = {1}\n", GENERATED_MSG_ID,
                message))
    })format!("{GENERATED_MSG_ID} = {message}\n")).unwrap();
43    let mut bundle = fluent_bundle::FluentBundle::new(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [{
                    #[allow(dead_code)]
                    enum ProcMacroHack { Value = ("\"en-US\"", 0).1, }
                    macro_rules! proc_macro_call {
                        () =>
                        {
                            unsafe
                            {
                                $crate :: LanguageIdentifier ::
                                from_raw_parts_unchecked(unsafe
                                {
                                    $crate :: subtags :: Language ::
                                    from_raw_unchecked(28261u64)
                                }, None,
                                Some(unsafe
                                {
                                    $crate :: subtags :: Region :: from_raw_unchecked(21333u32)
                                }), None)
                            }
                        }
                    }
                    unsafe {
                        ::unic_langid_macros::LanguageIdentifier::from_raw_parts_unchecked(unsafe
                                {
                                ::unic_langid_macros::subtags::Language::from_raw_unchecked(28261u64)
                            }, None,
                            Some(unsafe {
                                    ::unic_langid_macros::subtags::Region::from_raw_unchecked(21333u32)
                                }), None)
                    }
                }]))vec![langid!("en-US")]);
44    bundle.set_use_isolating(false);
45    bundle.add_resource(resource).unwrap();
46    register_functions(&mut bundle);
47    let message = bundle.get_message(GENERATED_MSG_ID).unwrap();
48    let value = message.value().unwrap();
49    let args = to_fluent_args(args.iter());
50
51    let mut errs = ::alloc::vec::Vec::new()vec![];
52    let formatted = bundle.format_pattern(value, Some(&args), &mut errs).to_string();
53    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_errors/src/formatting.rs:53",
                        "rustc_errors::formatting", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_errors/src/formatting.rs"),
                        ::tracing_core::__macro_support::Option::Some(53u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_errors::formatting"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("formatted")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("formatted");
                                            NAME.as_str()
                                        },
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("errs")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("errs");
                                            NAME.as_str()
                                        }], ::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(&::tracing::field::debug(&formatted)
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&errs)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?formatted, ?errs);
54    if errs.is_empty() {
55        Cow::Owned(formatted)
56    } else {
57        {
    ::core::panicking::panic_fmt(format_args!("Fluent errors while formatting message: {0:?}",
            errs));
};panic!("Fluent errors while formatting message: {errs:?}");
58    }
59}
60
61pub trait DiagMessageAddArg {
62    fn arg(self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) -> EagerDiagMessageBuilder;
63}
64
65pub struct EagerDiagMessageBuilder {
66    fluent_str: Cow<'static, str>,
67    args: DiagArgMap,
68}
69
70impl DiagMessageAddArg for EagerDiagMessageBuilder {
71    fn arg(
72        mut self,
73        name: impl Into<DiagArgName>,
74        arg: impl IntoDiagArg,
75    ) -> EagerDiagMessageBuilder {
76        let name = name.into();
77        let value = arg.into_diag_arg(&mut None);
78        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!(
79            !self.args.contains_key(&name) || self.args.get(&name) == Some(&value),
80            "arg {} already exists",
81            name
82        );
83        self.args.insert(name, value);
84        self
85    }
86}
87
88impl DiagMessageAddArg for DiagMessage {
89    fn arg(self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) -> EagerDiagMessageBuilder {
90        let DiagMessage::Inline(fluent_str) = self else {
91            {
    ::core::panicking::panic_fmt(format_args!("Tried to eagerly format an already formatted message"));
}panic!("Tried to eagerly format an already formatted message")
92        };
93        EagerDiagMessageBuilder { fluent_str, args: Default::default() }.arg(name, arg)
94    }
95}
96
97impl EagerDiagMessageBuilder {
98    pub fn format(self) -> DiagMessage {
99        DiagMessage::Str(format_fluent_str(&self.fluent_str, &self.args))
100    }
101}