Skip to content

Commit 76d5c8a

Browse files
committed
Factor out ICU4X list formatter creation
1 parent 9a67715 commit 76d5c8a

File tree

1 file changed

+88
-68
lines changed
  • compiler/rustc_error_messages/src

1 file changed

+88
-68
lines changed

compiler/rustc_error_messages/src/lib.rs

Lines changed: 88 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub use fluent_bundle::types::FluentType;
2020
use fluent_bundle::FluentResource;
2121
pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue};
2222
use fluent_syntax::parser::ParserError;
23+
use icu_list::ListFormatter;
2324
use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
2425
#[cfg(parallel_compiler)]
2526
use intl_memoizer::concurrent::IntlLangMemoizer;
@@ -529,85 +530,104 @@ fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locid::Lo
529530
icu_locid::Locale::try_from_bytes(lang.to_string().as_bytes()).ok()
530531
}
531532

532-
pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValue<'_> {
533-
// Fluent requires 'static value here for its AnyEq usages.
534-
#[derive(Clone, PartialEq, Debug)]
535-
struct FluentStrListSepByAnd(Vec<String>);
533+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
534+
enum Separator {
535+
And,
536+
}
536537

537-
impl FluentType for FluentStrListSepByAnd {
538-
fn duplicate(&self) -> Box<dyn FluentType + Send> {
539-
Box::new(self.clone())
538+
impl Separator {
539+
fn list_formatter(
540+
&self,
541+
data_provider: &LocaleFallbackProvider<rustc_baked_icu_data::BakedDataProvider>,
542+
locale: icu_locid::Locale,
543+
) -> ListFormatter {
544+
match self {
545+
Separator::And => icu_list::ListFormatter::try_new_and_with_length_with_any_provider(
546+
&data_provider,
547+
&locale.into(),
548+
icu_list::ListLength::Wide,
549+
),
540550
}
551+
.expect("Failed to create list formatter")
552+
}
553+
}
541554

542-
fn as_string(&self, intls: &intl_memoizer::IntlLangMemoizer) -> Cow<'static, str> {
543-
let result = intls
544-
.with_try_get::<MemoizableListFormatter, _, _>((), |list_formatter| {
545-
list_formatter.format_to_string(self.0.iter())
546-
})
547-
.unwrap();
548-
Cow::Owned(result)
549-
}
555+
#[derive(Clone, PartialEq, Debug)]
556+
struct FluentStrListSepBy {
557+
sep: Separator,
558+
items: Vec<String>,
559+
}
550560

551-
#[cfg(not(parallel_compiler))]
552-
fn as_string_threadsafe(
553-
&self,
554-
_intls: &intl_memoizer::concurrent::IntlLangMemoizer,
555-
) -> Cow<'static, str> {
556-
unreachable!("`as_string_threadsafe` is not used in non-parallel rustc")
557-
}
561+
impl FluentType for FluentStrListSepBy {
562+
fn duplicate(&self) -> Box<dyn FluentType + Send> {
563+
Box::new(self.clone())
564+
}
558565

559-
#[cfg(parallel_compiler)]
560-
fn as_string_threadsafe(
561-
&self,
562-
intls: &intl_memoizer::concurrent::IntlLangMemoizer,
563-
) -> Cow<'static, str> {
564-
let result = intls
565-
.with_try_get::<MemoizableListFormatter, _, _>((), |list_formatter| {
566-
list_formatter.format_to_string(self.0.iter())
567-
})
568-
.unwrap();
569-
Cow::Owned(result)
570-
}
566+
fn as_string(&self, intls: &intl_memoizer::IntlLangMemoizer) -> Cow<'static, str> {
567+
let result = intls
568+
.with_try_get::<MemoizableListFormatter, _, _>(self.sep, |list_formatter| {
569+
list_formatter.format_to_string(self.items.iter())
570+
})
571+
.unwrap();
572+
Cow::Owned(result)
573+
}
574+
575+
#[cfg(not(parallel_compiler))]
576+
fn as_string_threadsafe(
577+
&self,
578+
_intls: &intl_memoizer::concurrent::IntlLangMemoizer,
579+
) -> Cow<'static, str> {
580+
unreachable!("`as_string_threadsafe` is not used in non-parallel rustc")
581+
}
582+
583+
#[cfg(parallel_compiler)]
584+
fn as_string_threadsafe(
585+
&self,
586+
intls: &intl_memoizer::concurrent::IntlLangMemoizer,
587+
) -> Cow<'static, str> {
588+
let result = intls
589+
.with_try_get::<MemoizableListFormatter, _, _>(self.sep, |list_formatter| {
590+
list_formatter.format_to_string(self.items.iter())
591+
})
592+
.unwrap();
593+
Cow::Owned(result)
571594
}
595+
}
572596

573-
struct MemoizableListFormatter(icu_list::ListFormatter);
597+
struct MemoizableListFormatter(icu_list::ListFormatter);
574598

575-
impl std::ops::Deref for MemoizableListFormatter {
576-
type Target = icu_list::ListFormatter;
577-
fn deref(&self) -> &Self::Target {
578-
&self.0
579-
}
599+
impl std::ops::Deref for MemoizableListFormatter {
600+
type Target = icu_list::ListFormatter;
601+
fn deref(&self) -> &Self::Target {
602+
&self.0
580603
}
604+
}
581605

582-
impl intl_memoizer::Memoizable for MemoizableListFormatter {
583-
type Args = ();
584-
type Error = ();
585-
586-
fn construct(lang: LanguageIdentifier, _args: Self::Args) -> Result<Self, Self::Error>
587-
where
588-
Self: Sized,
589-
{
590-
let baked_data_provider = rustc_baked_icu_data::baked_data_provider();
591-
let locale_fallbacker =
592-
LocaleFallbacker::try_new_with_any_provider(&baked_data_provider)
593-
.expect("Failed to create fallback provider");
594-
let data_provider =
595-
LocaleFallbackProvider::new_with_fallbacker(baked_data_provider, locale_fallbacker);
596-
let locale = icu_locale_from_unic_langid(lang)
597-
.unwrap_or_else(|| rustc_baked_icu_data::supported_locales::EN);
598-
let list_formatter =
599-
icu_list::ListFormatter::try_new_and_with_length_with_any_provider(
600-
&data_provider,
601-
&locale.into(),
602-
icu_list::ListLength::Wide,
603-
)
604-
.expect("Failed to create list formatter");
605-
606-
Ok(MemoizableListFormatter(list_formatter))
607-
}
606+
impl intl_memoizer::Memoizable for MemoizableListFormatter {
607+
type Args = Separator;
608+
type Error = ();
609+
610+
fn construct(lang: LanguageIdentifier, separator: Separator) -> Result<Self, Self::Error>
611+
where
612+
Self: Sized,
613+
{
614+
let baked_data_provider = rustc_baked_icu_data::baked_data_provider();
615+
let locale_fallbacker = LocaleFallbacker::try_new_with_any_provider(&baked_data_provider)
616+
.expect("Failed to create fallback provider");
617+
let data_provider =
618+
LocaleFallbackProvider::new_with_fallbacker(baked_data_provider, locale_fallbacker);
619+
let locale = icu_locale_from_unic_langid(lang)
620+
.unwrap_or_else(|| rustc_baked_icu_data::supported_locales::EN);
621+
622+
let list_formatter = separator.list_formatter(&data_provider, locale);
623+
624+
Ok(MemoizableListFormatter(list_formatter))
608625
}
626+
}
609627

610-
let l = l.into_iter().map(|x| x.into_owned()).collect();
628+
pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValue<'_> {
629+
// Fluent requires 'static value here for its AnyEq usages.
630+
let items = l.into_iter().map(|x| x.into_owned()).collect();
611631

612-
FluentValue::Custom(Box::new(FluentStrListSepByAnd(l)))
632+
FluentValue::Custom(Box::new(FluentStrListSepBy { sep: Separator::And, items }))
613633
}

0 commit comments

Comments
 (0)