Skip to main content

rustc_error_messages/
lib.rs

1// tidy-alphabetical-start
2#![allow(internal_features)]
3#![feature(rustc_attrs)]
4// tidy-alphabetical-end
5
6use std::borrow::Cow;
7use std::error::Error;
8use std::path::Path;
9use std::sync::{Arc, LazyLock};
10use std::{fmt, fs, io};
11
12use fluent_bundle::FluentResource;
13pub use fluent_bundle::types::FluentType;
14pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue};
15use fluent_syntax::parser::ParserError;
16use intl_memoizer::concurrent::IntlLangMemoizer;
17use rustc_data_structures::sync::{DynSend, IntoDynSyncSend};
18use rustc_macros::{Decodable, Encodable};
19use rustc_span::Span;
20use tracing::{instrument, trace};
21pub use unic_langid::{LanguageIdentifier, langid};
22
23mod diagnostic_impls;
24pub use diagnostic_impls::DiagArgFromDisplay;
25
26pub type FluentBundle =
27    IntoDynSyncSend<fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>>;
28
29fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
30    IntoDynSyncSend(fluent_bundle::bundle::FluentBundle::new_concurrent(locales))
31}
32
33#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TranslationBundleError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            TranslationBundleError::ReadFtl(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ReadFtl", &__self_0),
            TranslationBundleError::ParseFtl(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ParseFtl", &__self_0),
            TranslationBundleError::AddResource(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "AddResource", &__self_0),
            TranslationBundleError::MissingLocale =>
                ::core::fmt::Formatter::write_str(f, "MissingLocale"),
            TranslationBundleError::ReadLocalesDir(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ReadLocalesDir", &__self_0),
            TranslationBundleError::ReadLocalesDirEntry(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ReadLocalesDirEntry", &__self_0),
            TranslationBundleError::LocaleIsNotDir =>
                ::core::fmt::Formatter::write_str(f, "LocaleIsNotDir"),
        }
    }
}Debug)]
34pub enum TranslationBundleError {
35    /// Failed to read from `.ftl` file.
36    ReadFtl(io::Error),
37    /// Failed to parse contents of `.ftl` file.
38    ParseFtl(ParserError),
39    /// Failed to add `FluentResource` to `FluentBundle`.
40    AddResource(FluentError),
41    /// `$sysroot/share/locale/$locale` does not exist.
42    MissingLocale,
43    /// Cannot read directory entries of `$sysroot/share/locale/$locale`.
44    ReadLocalesDir(io::Error),
45    /// Cannot read directory entry of `$sysroot/share/locale/$locale`.
46    ReadLocalesDirEntry(io::Error),
47    /// `$sysroot/share/locale/$locale` is not a directory.
48    LocaleIsNotDir,
49}
50
51impl fmt::Display for TranslationBundleError {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        match self {
54            TranslationBundleError::ReadFtl(e) => f.write_fmt(format_args!("could not read ftl file: {0}", e))write!(f, "could not read ftl file: {e}"),
55            TranslationBundleError::ParseFtl(e) => {
56                f.write_fmt(format_args!("could not parse ftl file: {0}", e))write!(f, "could not parse ftl file: {e}")
57            }
58            TranslationBundleError::AddResource(e) => f.write_fmt(format_args!("failed to add resource: {0}", e))write!(f, "failed to add resource: {e}"),
59            TranslationBundleError::MissingLocale => f.write_fmt(format_args!("missing locale directory"))write!(f, "missing locale directory"),
60            TranslationBundleError::ReadLocalesDir(e) => {
61                f.write_fmt(format_args!("could not read locales dir: {0}", e))write!(f, "could not read locales dir: {e}")
62            }
63            TranslationBundleError::ReadLocalesDirEntry(e) => {
64                f.write_fmt(format_args!("could not read locales dir entry: {0}", e))write!(f, "could not read locales dir entry: {e}")
65            }
66            TranslationBundleError::LocaleIsNotDir => {
67                f.write_fmt(format_args!("`$sysroot/share/locales/$locale` is not a directory"))write!(f, "`$sysroot/share/locales/$locale` is not a directory")
68            }
69        }
70    }
71}
72
73impl Error for TranslationBundleError {
74    fn source(&self) -> Option<&(dyn Error + 'static)> {
75        match self {
76            TranslationBundleError::ReadFtl(e) => Some(e),
77            TranslationBundleError::ParseFtl(e) => Some(e),
78            TranslationBundleError::AddResource(e) => Some(e),
79            TranslationBundleError::MissingLocale => None,
80            TranslationBundleError::ReadLocalesDir(e) => Some(e),
81            TranslationBundleError::ReadLocalesDirEntry(e) => Some(e),
82            TranslationBundleError::LocaleIsNotDir => None,
83        }
84    }
85}
86
87impl From<(FluentResource, Vec<ParserError>)> for TranslationBundleError {
88    fn from((_, mut errs): (FluentResource, Vec<ParserError>)) -> Self {
89        TranslationBundleError::ParseFtl(errs.pop().expect("failed ftl parse with no errors"))
90    }
91}
92
93impl From<Vec<FluentError>> for TranslationBundleError {
94    fn from(mut errs: Vec<FluentError>) -> Self {
95        TranslationBundleError::AddResource(
96            errs.pop().expect("failed adding resource to bundle with no errors"),
97        )
98    }
99}
100
101/// Returns Fluent bundle with the user's locale resources from
102/// `$sysroot/share/locale/$requested_locale/*.ftl`.
103///
104/// If `-Z additional-ftl-path` was provided, load that resource and add it  to the bundle
105/// (overriding any conflicting messages).
106#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("fluent_bundle",
                                    "rustc_error_messages", ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_error_messages/src/lib.rs"),
                                    ::tracing_core::__macro_support::Option::Some(106u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_error_messages"),
                                    ::tracing_core::field::FieldSet::new(&["sysroot_candidates",
                                                    "requested_locale", "additional_ftl_path",
                                                    "with_directionality_markers"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sysroot_candidates)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&requested_locale)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&additional_ftl_path)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&with_directionality_markers
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    Result<Option<Arc<FluentBundle>>, TranslationBundleError> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            if requested_locale.is_none() && additional_ftl_path.is_none() {
                return Ok(None);
            }
            let fallback_locale =
                {
                    #[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)
                    }
                };
            let requested_fallback_locale =
                requested_locale.as_ref() == Some(&fallback_locale);
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_error_messages/src/lib.rs:119",
                                    "rustc_error_messages", ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_error_messages/src/lib.rs"),
                                    ::tracing_core::__macro_support::Option::Some(119u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_error_messages"),
                                    ::tracing_core::field::FieldSet::new(&["requested_fallback_locale"],
                                        ::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};
                            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(&requested_fallback_locale)
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            if requested_fallback_locale && additional_ftl_path.is_none() {
                return Ok(None);
            }
            let locale = requested_locale.clone().unwrap_or(fallback_locale);
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_error_messages/src/lib.rs:126",
                                    "rustc_error_messages", ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_error_messages/src/lib.rs"),
                                    ::tracing_core::__macro_support::Option::Some(126u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_error_messages"),
                                    ::tracing_core::field::FieldSet::new(&["locale"],
                                        ::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};
                            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(&locale) as
                                                        &dyn Value))])
                        });
                } else { ; }
            };
            let mut bundle =
                new_bundle(<[_]>::into_vec(::alloc::boxed::box_new([locale])));
            register_functions(&mut bundle);
            bundle.set_use_isolating(with_directionality_markers);
            if let Some(requested_locale) = requested_locale {
                let mut found_resources = false;
                for sysroot in sysroot_candidates {
                    let mut sysroot = sysroot.to_path_buf();
                    sysroot.push("share");
                    sysroot.push("locale");
                    sysroot.push(requested_locale.to_string());
                    {
                        use ::tracing::__macro_support::Callsite as _;
                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                            {
                                static META: ::tracing::Metadata<'static> =
                                    {
                                        ::tracing_core::metadata::Metadata::new("event compiler/rustc_error_messages/src/lib.rs:147",
                                            "rustc_error_messages", ::tracing::Level::TRACE,
                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_error_messages/src/lib.rs"),
                                            ::tracing_core::__macro_support::Option::Some(147u32),
                                            ::tracing_core::__macro_support::Option::Some("rustc_error_messages"),
                                            ::tracing_core::field::FieldSet::new(&["sysroot"],
                                                ::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};
                                    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(&sysroot) as
                                                                &dyn Value))])
                                });
                        } else { ; }
                    };
                    if !sysroot.exists() {
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_error_messages/src/lib.rs:150",
                                                "rustc_error_messages", ::tracing::Level::TRACE,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_error_messages/src/lib.rs"),
                                                ::tracing_core::__macro_support::Option::Some(150u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_error_messages"),
                                                ::tracing_core::field::FieldSet::new(&["message"],
                                                    ::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};
                                        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!("skipping")
                                                                    as &dyn Value))])
                                    });
                            } else { ; }
                        };
                        continue;
                    }
                    if !sysroot.is_dir() {
                        return Err(TranslationBundleError::LocaleIsNotDir);
                    }
                    for entry in
                        sysroot.read_dir().map_err(TranslationBundleError::ReadLocalesDir)?
                        {
                        let entry =
                            entry.map_err(TranslationBundleError::ReadLocalesDirEntry)?;
                        let path = entry.path();
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_error_messages/src/lib.rs:161",
                                                "rustc_error_messages", ::tracing::Level::TRACE,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_error_messages/src/lib.rs"),
                                                ::tracing_core::__macro_support::Option::Some(161u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_error_messages"),
                                                ::tracing_core::field::FieldSet::new(&["path"],
                                                    ::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};
                                        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(&path) as
                                                                    &dyn Value))])
                                    });
                            } else { ; }
                        };
                        if path.extension().and_then(|s| s.to_str()) != Some("ftl")
                            {
                            {
                                use ::tracing::__macro_support::Callsite as _;
                                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                    {
                                        static META: ::tracing::Metadata<'static> =
                                            {
                                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_error_messages/src/lib.rs:163",
                                                    "rustc_error_messages", ::tracing::Level::TRACE,
                                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_error_messages/src/lib.rs"),
                                                    ::tracing_core::__macro_support::Option::Some(163u32),
                                                    ::tracing_core::__macro_support::Option::Some("rustc_error_messages"),
                                                    ::tracing_core::field::FieldSet::new(&["message"],
                                                        ::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};
                                            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!("skipping")
                                                                        as &dyn Value))])
                                        });
                                } else { ; }
                            };
                            continue;
                        }
                        let resource_str =
                            fs::read_to_string(path).map_err(TranslationBundleError::ReadFtl)?;
                        let resource =
                            FluentResource::try_new(resource_str).map_err(TranslationBundleError::from)?;
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_error_messages/src/lib.rs:171",
                                                "rustc_error_messages", ::tracing::Level::TRACE,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_error_messages/src/lib.rs"),
                                                ::tracing_core::__macro_support::Option::Some(171u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_error_messages"),
                                                ::tracing_core::field::FieldSet::new(&["resource"],
                                                    ::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};
                                        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(&resource)
                                                                    as &dyn Value))])
                                    });
                            } else { ; }
                        };
                        bundle.add_resource(resource).map_err(TranslationBundleError::from)?;
                        found_resources = true;
                    }
                }
                if !found_resources {
                    return Err(TranslationBundleError::MissingLocale);
                }
            }
            if let Some(additional_ftl_path) = additional_ftl_path {
                let resource_str =
                    fs::read_to_string(additional_ftl_path).map_err(TranslationBundleError::ReadFtl)?;
                let resource =
                    FluentResource::try_new(resource_str).map_err(TranslationBundleError::from)?;
                {
                    use ::tracing::__macro_support::Callsite as _;
                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                        {
                            static META: ::tracing::Metadata<'static> =
                                {
                                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_error_messages/src/lib.rs:187",
                                        "rustc_error_messages", ::tracing::Level::TRACE,
                                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_error_messages/src/lib.rs"),
                                        ::tracing_core::__macro_support::Option::Some(187u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_error_messages"),
                                        ::tracing_core::field::FieldSet::new(&["resource"],
                                            ::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};
                                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(&resource)
                                                            as &dyn Value))])
                            });
                    } else { ; }
                };
                bundle.add_resource_overriding(resource);
            }
            let bundle = Arc::new(bundle);
            Ok(Some(bundle))
        }
    }
}#[instrument(level = "trace")]
107pub fn fluent_bundle(
108    sysroot_candidates: &[&Path],
109    requested_locale: Option<LanguageIdentifier>,
110    additional_ftl_path: Option<&Path>,
111    with_directionality_markers: bool,
112) -> Result<Option<Arc<FluentBundle>>, TranslationBundleError> {
113    if requested_locale.is_none() && additional_ftl_path.is_none() {
114        return Ok(None);
115    }
116
117    let fallback_locale = langid!("en-US");
118    let requested_fallback_locale = requested_locale.as_ref() == Some(&fallback_locale);
119    trace!(?requested_fallback_locale);
120    if requested_fallback_locale && additional_ftl_path.is_none() {
121        return Ok(None);
122    }
123    // If there is only `-Z additional-ftl-path`, assume locale is "en-US", otherwise use user
124    // provided locale.
125    let locale = requested_locale.clone().unwrap_or(fallback_locale);
126    trace!(?locale);
127    let mut bundle = new_bundle(vec![locale]);
128
129    // Add convenience functions available to ftl authors.
130    register_functions(&mut bundle);
131
132    // Fluent diagnostics can insert directionality isolation markers around interpolated variables
133    // indicating that there may be a shift from right-to-left to left-to-right text (or
134    // vice-versa). These are disabled because they are sometimes visible in the error output, but
135    // may be worth investigating in future (for example: if type names are left-to-right and the
136    // surrounding diagnostic messages are right-to-left, then these might be helpful).
137    bundle.set_use_isolating(with_directionality_markers);
138
139    // If the user requests the default locale then don't try to load anything.
140    if let Some(requested_locale) = requested_locale {
141        let mut found_resources = false;
142        for sysroot in sysroot_candidates {
143            let mut sysroot = sysroot.to_path_buf();
144            sysroot.push("share");
145            sysroot.push("locale");
146            sysroot.push(requested_locale.to_string());
147            trace!(?sysroot);
148
149            if !sysroot.exists() {
150                trace!("skipping");
151                continue;
152            }
153
154            if !sysroot.is_dir() {
155                return Err(TranslationBundleError::LocaleIsNotDir);
156            }
157
158            for entry in sysroot.read_dir().map_err(TranslationBundleError::ReadLocalesDir)? {
159                let entry = entry.map_err(TranslationBundleError::ReadLocalesDirEntry)?;
160                let path = entry.path();
161                trace!(?path);
162                if path.extension().and_then(|s| s.to_str()) != Some("ftl") {
163                    trace!("skipping");
164                    continue;
165                }
166
167                let resource_str =
168                    fs::read_to_string(path).map_err(TranslationBundleError::ReadFtl)?;
169                let resource =
170                    FluentResource::try_new(resource_str).map_err(TranslationBundleError::from)?;
171                trace!(?resource);
172                bundle.add_resource(resource).map_err(TranslationBundleError::from)?;
173                found_resources = true;
174            }
175        }
176
177        if !found_resources {
178            return Err(TranslationBundleError::MissingLocale);
179        }
180    }
181
182    if let Some(additional_ftl_path) = additional_ftl_path {
183        let resource_str =
184            fs::read_to_string(additional_ftl_path).map_err(TranslationBundleError::ReadFtl)?;
185        let resource =
186            FluentResource::try_new(resource_str).map_err(TranslationBundleError::from)?;
187        trace!(?resource);
188        bundle.add_resource_overriding(resource);
189    }
190
191    let bundle = Arc::new(bundle);
192    Ok(Some(bundle))
193}
194
195pub fn register_functions<R, M>(bundle: &mut fluent_bundle::bundle::FluentBundle<R, M>) {
196    bundle
197        .add_function("STREQ", |positional, _named| match positional {
198            [FluentValue::String(a), FluentValue::String(b)] => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}", (a == b)))
    })format!("{}", (a == b)).into(),
199            _ => FluentValue::Error,
200        })
201        .expect("Failed to add a function to the bundle.");
202}
203
204/// Type alias for the result of `fallback_fluent_bundle` - a reference-counted pointer to a lazily
205/// evaluated fluent bundle.
206pub type LazyFallbackBundle =
207    Arc<LazyLock<FluentBundle, Box<dyn FnOnce() -> FluentBundle + DynSend>>>;
208
209/// Return the default `FluentBundle` with standard "en-US" diagnostic messages.
210#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("fallback_fluent_bundle",
                                    "rustc_error_messages", ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_error_messages/src/lib.rs"),
                                    ::tracing_core::__macro_support::Option::Some(210u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_error_messages"),
                                    ::tracing_core::field::FieldSet::new(&["with_directionality_markers"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&with_directionality_markers
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: LazyFallbackBundle = loop {};
            return __tracing_attr_fake_return;
        }
        {
            Arc::new(LazyLock::new(Box::new(move ||
                            {
                                let mut fallback_bundle =
                                    new_bundle(<[_]>::into_vec(::alloc::boxed::box_new([{
                                                            #[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)
                                                            }
                                                        }])));
                                register_functions(&mut fallback_bundle);
                                fallback_bundle.set_use_isolating(with_directionality_markers);
                                for resource in resources {
                                    let resource =
                                        FluentResource::try_new(resource.to_string()).expect("failed to parse fallback fluent resource");
                                    fallback_bundle.add_resource_overriding(resource);
                                }
                                fallback_bundle
                            })))
        }
    }
}#[instrument(level = "trace", skip(resources))]
211pub fn fallback_fluent_bundle(
212    resources: Vec<&'static str>,
213    with_directionality_markers: bool,
214) -> LazyFallbackBundle {
215    Arc::new(LazyLock::new(Box::new(move || {
216        let mut fallback_bundle = new_bundle(vec![langid!("en-US")]);
217
218        register_functions(&mut fallback_bundle);
219
220        // See comment in `fluent_bundle`.
221        fallback_bundle.set_use_isolating(with_directionality_markers);
222
223        for resource in resources {
224            let resource = FluentResource::try_new(resource.to_string())
225                .expect("failed to parse fallback fluent resource");
226            fallback_bundle.add_resource_overriding(resource);
227        }
228
229        fallback_bundle
230    })))
231}
232
233/// Abstraction over a message in a diagnostic to support both translatable and non-translatable
234/// diagnostic messages.
235///
236/// Intended to be removed once diagnostics are entirely translatable.
237#[derive(#[automatically_derived]
impl ::core::clone::Clone for DiagMessage {
    #[inline]
    fn clone(&self) -> DiagMessage {
        match self {
            DiagMessage::Str(__self_0) =>
                DiagMessage::Str(::core::clone::Clone::clone(__self_0)),
            DiagMessage::Inline(__self_0) =>
                DiagMessage::Inline(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for DiagMessage {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            DiagMessage::Str(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Str",
                    &__self_0),
            DiagMessage::Inline(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Inline",
                    &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for DiagMessage {
    #[inline]
    fn eq(&self, other: &DiagMessage) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (DiagMessage::Str(__self_0), DiagMessage::Str(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (DiagMessage::Inline(__self_0), DiagMessage::Inline(__arg1_0))
                    => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DiagMessage {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Cow<'static, str>>;
        let _: ::core::cmp::AssertParamIsEq<Cow<'static, str>>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for DiagMessage {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            DiagMessage::Str(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            DiagMessage::Inline(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for DiagMessage {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        DiagMessage::Str(ref __binding_0) => { 0usize }
                        DiagMessage::Inline(ref __binding_0) => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    DiagMessage::Str(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    DiagMessage::Inline(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for DiagMessage {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        DiagMessage::Str(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => {
                        DiagMessage::Inline(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `DiagMessage`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
238#[rustc_diagnostic_item = "DiagMessage"]
239pub enum DiagMessage {
240    /// Non-translatable diagnostic message or a message that has been translated eagerly.
241    ///
242    /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
243    /// be instantiated multiple times with different values. These subdiagnostics' messages
244    /// are translated when they are added to the parent diagnostic. This is one of the ways
245    /// this variant of `DiagMessage` is produced.
246    Str(Cow<'static, str>),
247    /// An inline Fluent message, containing the to be translated diagnostic message.
248    Inline(Cow<'static, str>),
249}
250
251impl DiagMessage {
252    pub fn as_str(&self) -> Option<&str> {
253        match self {
254            DiagMessage::Str(s) => Some(s),
255            DiagMessage::Inline(_) => None,
256        }
257    }
258}
259
260impl From<String> for DiagMessage {
261    fn from(s: String) -> Self {
262        DiagMessage::Str(Cow::Owned(s))
263    }
264}
265impl From<&'static str> for DiagMessage {
266    fn from(s: &'static str) -> Self {
267        DiagMessage::Str(Cow::Borrowed(s))
268    }
269}
270impl From<Cow<'static, str>> for DiagMessage {
271    fn from(s: Cow<'static, str>) -> Self {
272        DiagMessage::Str(s)
273    }
274}
275
276/// A span together with some additional data.
277#[derive(#[automatically_derived]
impl ::core::clone::Clone for SpanLabel {
    #[inline]
    fn clone(&self) -> SpanLabel {
        SpanLabel {
            span: ::core::clone::Clone::clone(&self.span),
            is_primary: ::core::clone::Clone::clone(&self.is_primary),
            label: ::core::clone::Clone::clone(&self.label),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for SpanLabel {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f, "SpanLabel",
            "span", &self.span, "is_primary", &self.is_primary, "label",
            &&self.label)
    }
}Debug)]
278pub struct SpanLabel {
279    /// The span we are going to include in the final snippet.
280    pub span: Span,
281
282    /// Is this a primary span? This is the "locus" of the message,
283    /// and is indicated with a `^^^^` underline, versus `----`.
284    pub is_primary: bool,
285
286    /// What label should we attach to this span (if any)?
287    pub label: Option<DiagMessage>,
288}
289
290/// A collection of `Span`s.
291///
292/// Spans have two orthogonal attributes:
293///
294/// - They can be *primary spans*. In this case they are the locus of
295///   the error, and would be rendered with `^^^`.
296/// - They can have a *label*. In this case, the label is written next
297///   to the mark in the snippet when we render.
298#[derive(#[automatically_derived]
impl ::core::clone::Clone for MultiSpan {
    #[inline]
    fn clone(&self) -> MultiSpan {
        MultiSpan {
            primary_spans: ::core::clone::Clone::clone(&self.primary_spans),
            span_labels: ::core::clone::Clone::clone(&self.span_labels),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for MultiSpan {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "MultiSpan",
            "primary_spans", &self.primary_spans, "span_labels",
            &&self.span_labels)
    }
}Debug, #[automatically_derived]
impl ::core::hash::Hash for MultiSpan {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.primary_spans, state);
        ::core::hash::Hash::hash(&self.span_labels, state)
    }
}Hash, #[automatically_derived]
impl ::core::cmp::PartialEq for MultiSpan {
    #[inline]
    fn eq(&self, other: &MultiSpan) -> bool {
        self.primary_spans == other.primary_spans &&
            self.span_labels == other.span_labels
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for MultiSpan {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Vec<Span>>;
        let _: ::core::cmp::AssertParamIsEq<Vec<(Span, DiagMessage)>>;
    }
}Eq, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for MultiSpan {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    MultiSpan {
                        primary_spans: ref __binding_0, span_labels: ref __binding_1
                        } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for MultiSpan {
            fn decode(__decoder: &mut __D) -> Self {
                MultiSpan {
                    primary_spans: ::rustc_serialize::Decodable::decode(__decoder),
                    span_labels: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable)]
299pub struct MultiSpan {
300    primary_spans: Vec<Span>,
301    span_labels: Vec<(Span, DiagMessage)>,
302}
303
304impl MultiSpan {
305    #[inline]
306    pub fn new() -> MultiSpan {
307        MultiSpan { primary_spans: ::alloc::vec::Vec::new()vec![], span_labels: ::alloc::vec::Vec::new()vec![] }
308    }
309
310    pub fn from_span(primary_span: Span) -> MultiSpan {
311        MultiSpan { primary_spans: <[_]>::into_vec(::alloc::boxed::box_new([primary_span]))vec![primary_span], span_labels: ::alloc::vec::Vec::new()vec![] }
312    }
313
314    pub fn from_spans(mut vec: Vec<Span>) -> MultiSpan {
315        vec.sort();
316        MultiSpan { primary_spans: vec, span_labels: ::alloc::vec::Vec::new()vec![] }
317    }
318
319    pub fn push_span_label(&mut self, span: Span, label: impl Into<DiagMessage>) {
320        self.span_labels.push((span, label.into()));
321    }
322
323    /// Selects the first primary span (if any).
324    pub fn primary_span(&self) -> Option<Span> {
325        self.primary_spans.first().cloned()
326    }
327
328    /// Returns all primary spans.
329    pub fn primary_spans(&self) -> &[Span] {
330        &self.primary_spans
331    }
332
333    /// Returns `true` if any of the primary spans are displayable.
334    pub fn has_primary_spans(&self) -> bool {
335        !self.is_dummy()
336    }
337
338    /// Returns `true` if this contains only a dummy primary span with any hygienic context.
339    pub fn is_dummy(&self) -> bool {
340        self.primary_spans.iter().all(|sp| sp.is_dummy())
341    }
342
343    /// Replaces all occurrences of one Span with another. Used to move `Span`s in areas that don't
344    /// display well (like std macros). Returns whether replacements occurred.
345    pub fn replace(&mut self, before: Span, after: Span) -> bool {
346        let mut replacements_occurred = false;
347        for primary_span in &mut self.primary_spans {
348            if *primary_span == before {
349                *primary_span = after;
350                replacements_occurred = true;
351            }
352        }
353        for span_label in &mut self.span_labels {
354            if span_label.0 == before {
355                span_label.0 = after;
356                replacements_occurred = true;
357            }
358        }
359        replacements_occurred
360    }
361
362    /// Returns the strings to highlight. We always ensure that there
363    /// is an entry for each of the primary spans -- for each primary
364    /// span `P`, if there is at least one label with span `P`, we return
365    /// those labels (marked as primary). But otherwise we return
366    /// `SpanLabel` instances with empty labels.
367    pub fn span_labels(&self) -> Vec<SpanLabel> {
368        let is_primary = |span| self.primary_spans.contains(&span);
369
370        let mut span_labels = self
371            .span_labels
372            .iter()
373            .map(|&(span, ref label)| SpanLabel {
374                span,
375                is_primary: is_primary(span),
376                label: Some(label.clone()),
377            })
378            .collect::<Vec<_>>();
379
380        for &span in &self.primary_spans {
381            if !span_labels.iter().any(|sl| sl.span == span) {
382                span_labels.push(SpanLabel { span, is_primary: true, label: None });
383            }
384        }
385
386        span_labels
387    }
388
389    /// Returns `true` if any of the span labels is displayable.
390    pub fn has_span_labels(&self) -> bool {
391        self.span_labels.iter().any(|(sp, _)| !sp.is_dummy())
392    }
393
394    /// Clone this `MultiSpan` without keeping any of the span labels - sometimes a `MultiSpan` is
395    /// to be re-used in another diagnostic, but includes `span_labels` which have translated
396    /// messages. These translated messages would fail to translate without their diagnostic
397    /// arguments which are unlikely to be cloned alongside the `Span`.
398    pub fn clone_ignoring_labels(&self) -> Self {
399        Self { primary_spans: self.primary_spans.clone(), ..MultiSpan::new() }
400    }
401}
402
403impl From<Span> for MultiSpan {
404    fn from(span: Span) -> MultiSpan {
405        MultiSpan::from_span(span)
406    }
407}
408
409impl From<Vec<Span>> for MultiSpan {
410    fn from(spans: Vec<Span>) -> MultiSpan {
411        MultiSpan::from_spans(spans)
412    }
413}
414
415fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locale::Locale> {
416    icu_locale::Locale::try_from_str(&lang.to_string()).ok()
417}
418
419pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValue<'_> {
420    // Fluent requires 'static value here for its AnyEq usages.
421    #[derive(#[automatically_derived]
impl ::core::clone::Clone for FluentStrListSepByAnd {
    #[inline]
    fn clone(&self) -> FluentStrListSepByAnd {
        FluentStrListSepByAnd(::core::clone::Clone::clone(&self.0))
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for FluentStrListSepByAnd {
    #[inline]
    fn eq(&self, other: &FluentStrListSepByAnd) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for FluentStrListSepByAnd {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f,
            "FluentStrListSepByAnd", &&self.0)
    }
}Debug)]
422    struct FluentStrListSepByAnd(Vec<String>);
423
424    impl FluentType for FluentStrListSepByAnd {
425        fn duplicate(&self) -> Box<dyn FluentType + Send> {
426            Box::new(self.clone())
427        }
428
429        fn as_string(&self, intls: &intl_memoizer::IntlLangMemoizer) -> Cow<'static, str> {
430            let result = intls
431                .with_try_get::<MemoizableListFormatter, _, _>((), |list_formatter| {
432                    list_formatter.format_to_string(self.0.iter())
433                })
434                .unwrap();
435            Cow::Owned(result)
436        }
437
438        fn as_string_threadsafe(
439            &self,
440            intls: &intl_memoizer::concurrent::IntlLangMemoizer,
441        ) -> Cow<'static, str> {
442            let result = intls
443                .with_try_get::<MemoizableListFormatter, _, _>((), |list_formatter| {
444                    list_formatter.format_to_string(self.0.iter())
445                })
446                .unwrap();
447            Cow::Owned(result)
448        }
449    }
450
451    struct MemoizableListFormatter(icu_list::ListFormatter);
452
453    impl std::ops::Deref for MemoizableListFormatter {
454        type Target = icu_list::ListFormatter;
455        fn deref(&self) -> &Self::Target {
456            &self.0
457        }
458    }
459
460    impl intl_memoizer::Memoizable for MemoizableListFormatter {
461        type Args = ();
462        type Error = ();
463
464        fn construct(lang: LanguageIdentifier, _args: Self::Args) -> Result<Self, Self::Error>
465        where
466            Self: Sized,
467        {
468            let locale = icu_locale_from_unic_langid(lang)
469                .unwrap_or_else(|| rustc_baked_icu_data::supported_locales::EN);
470            let list_formatter = icu_list::ListFormatter::try_new_and_unstable(
471                &rustc_baked_icu_data::BakedDataProvider,
472                locale.into(),
473                icu_list::options::ListFormatterOptions::default()
474                    .with_length(icu_list::options::ListLength::Wide),
475            )
476            .expect("Failed to create list formatter");
477
478            Ok(MemoizableListFormatter(list_formatter))
479        }
480    }
481
482    let l = l.into_iter().map(|x| x.into_owned()).collect();
483
484    FluentValue::Custom(Box::new(FluentStrListSepByAnd(l)))
485}
486
487/// Simplified version of `FluentArg` that can implement `Encodable` and `Decodable`. Collection of
488/// `DiagArg` are converted to `FluentArgs` (consuming the collection) at the start of diagnostic
489/// emission.
490pub type DiagArg<'iter> = (&'iter DiagArgName, &'iter DiagArgValue);
491
492/// Name of a diagnostic argument.
493pub type DiagArgName = Cow<'static, str>;
494
495/// Simplified version of `FluentValue` that can implement `Encodable` and `Decodable`. Converted
496/// to a `FluentValue` by the emitter to be used in diagnostic translation.
497#[derive(#[automatically_derived]
impl ::core::clone::Clone for DiagArgValue {
    #[inline]
    fn clone(&self) -> DiagArgValue {
        match self {
            DiagArgValue::Str(__self_0) =>
                DiagArgValue::Str(::core::clone::Clone::clone(__self_0)),
            DiagArgValue::Number(__self_0) =>
                DiagArgValue::Number(::core::clone::Clone::clone(__self_0)),
            DiagArgValue::StrListSepByAnd(__self_0) =>
                DiagArgValue::StrListSepByAnd(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for DiagArgValue {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            DiagArgValue::Str(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Str",
                    &__self_0),
            DiagArgValue::Number(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Number",
                    &__self_0),
            DiagArgValue::StrListSepByAnd(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "StrListSepByAnd", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for DiagArgValue {
    #[inline]
    fn eq(&self, other: &DiagArgValue) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (DiagArgValue::Str(__self_0), DiagArgValue::Str(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (DiagArgValue::Number(__self_0),
                    DiagArgValue::Number(__arg1_0)) => __self_0 == __arg1_0,
                (DiagArgValue::StrListSepByAnd(__self_0),
                    DiagArgValue::StrListSepByAnd(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DiagArgValue {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Cow<'static, str>>;
        let _: ::core::cmp::AssertParamIsEq<i32>;
        let _: ::core::cmp::AssertParamIsEq<Vec<Cow<'static, str>>>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for DiagArgValue {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            DiagArgValue::Str(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            DiagArgValue::Number(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            DiagArgValue::StrListSepByAnd(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for DiagArgValue {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        DiagArgValue::Str(ref __binding_0) => { 0usize }
                        DiagArgValue::Number(ref __binding_0) => { 1usize }
                        DiagArgValue::StrListSepByAnd(ref __binding_0) => { 2usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    DiagArgValue::Str(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    DiagArgValue::Number(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    DiagArgValue::StrListSepByAnd(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for DiagArgValue {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        DiagArgValue::Str(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => {
                        DiagArgValue::Number(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    2usize => {
                        DiagArgValue::StrListSepByAnd(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `DiagArgValue`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
498pub enum DiagArgValue {
499    Str(Cow<'static, str>),
500    // This gets converted to a `FluentNumber`, which is an `f64`. An `i32`
501    // safely fits in an `f64`. Any integers bigger than that will be converted
502    // to strings in `into_diag_arg` and stored using the `Str` variant.
503    Number(i32),
504    StrListSepByAnd(Vec<Cow<'static, str>>),
505}
506
507/// Converts a value of a type into a `DiagArg` (typically a field of an `Diag` struct).
508/// Implemented as a custom trait rather than `From` so that it is implemented on the type being
509/// converted rather than on `DiagArgValue`, which enables types from other `rustc_*` crates to
510/// implement this.
511pub trait IntoDiagArg {
512    /// Convert `Self` into a `DiagArgValue` suitable for rendering in a diagnostic.
513    ///
514    /// It takes a `path` where "long values" could be written to, if the `DiagArgValue` is too big
515    /// for displaying on the terminal. This path comes from the `Diag` itself. When rendering
516    /// values that come from `TyCtxt`, like `Ty<'_>`, they can use `TyCtxt::short_string`. If a
517    /// value has no shortening logic that could be used, the argument can be safely ignored.
518    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue;
519}
520
521impl IntoDiagArg for DiagArgValue {
522    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
523        self
524    }
525}
526
527impl From<DiagArgValue> for FluentValue<'static> {
528    fn from(val: DiagArgValue) -> Self {
529        match val {
530            DiagArgValue::Str(s) => From::from(s),
531            DiagArgValue::Number(n) => From::from(n),
532            DiagArgValue::StrListSepByAnd(l) => fluent_value_from_str_list_sep_by_and(l),
533        }
534    }
535}