1use std::borrow::Cow;
2
3pub use fluent_bundle::types::FluentType;
4pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue};
5use rustc_macros::{Decodable, Encodable, StableHash};
6use rustc_span::Span;
7pub use unic_langid::{LanguageIdentifier, langid};
8
9mod diagnostic_impls;
10pub use diagnostic_impls::DiagArgFromDisplay;
11use rustc_data_structures::fx::FxIndexMap;
12
13pub fn register_functions<R, M>(bundle: &mut fluent_bundle::bundle::FluentBundle<R, M>) {
14 bundle
15 .add_function("STREQ", |positional, _named| match positional {
16 [FluentValue::String(a), FluentValue::String(b)] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", (a == b)))
})format!("{}", (a == b)).into(),
17 _ => FluentValue::Error,
18 })
19 .expect("Failed to add a function to the bundle.");
20}
21
22#[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_fields_are_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, const _: () =
{
impl ::rustc_data_structures::stable_hash::StableHash for DiagMessage
{
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
match *self {
DiagMessage::Str(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
DiagMessage::Inline(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash)]
27pub enum DiagMessage {
28 Str(Cow<'static, str>),
35 Inline(Cow<'static, str>),
37}
38
39impl DiagMessage {
40 pub fn as_str(&self) -> Option<&str> {
41 match self {
42 DiagMessage::Str(s) => Some(s),
43 DiagMessage::Inline(_) => None,
44 }
45 }
46}
47
48impl From<String> for DiagMessage {
49 fn from(s: String) -> Self {
50 DiagMessage::Str(Cow::Owned(s))
51 }
52}
53impl From<&'static str> for DiagMessage {
54 fn from(s: &'static str) -> Self {
55 DiagMessage::Str(Cow::Borrowed(s))
56 }
57}
58impl From<Cow<'static, str>> for DiagMessage {
59 fn from(s: Cow<'static, str>) -> Self {
60 DiagMessage::Str(s)
61 }
62}
63
64#[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)]
66pub struct SpanLabel {
67 pub span: Span,
69
70 pub is_primary: bool,
73
74 pub label: Option<DiagMessage>,
76}
77
78#[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_fields_are_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, const _: () =
{
impl ::rustc_data_structures::stable_hash::StableHash for MultiSpan {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
match *self {
MultiSpan {
primary_spans: ref __binding_0, span_labels: ref __binding_1
} => {
{ __binding_0.stable_hash(__hcx, __hasher); }
{ __binding_1.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash)]
87pub struct MultiSpan {
88 primary_spans: Vec<Span>,
89 span_labels: Vec<(Span, DiagMessage)>,
90}
91
92impl MultiSpan {
93 #[inline]
94 pub fn new() -> MultiSpan {
95 MultiSpan { primary_spans: ::alloc::vec::Vec::new()vec![], span_labels: ::alloc::vec::Vec::new()vec![] }
96 }
97
98 pub fn from_span(primary_span: Span) -> MultiSpan {
99 MultiSpan { primary_spans: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[primary_span]))vec![primary_span], span_labels: ::alloc::vec::Vec::new()vec![] }
100 }
101
102 pub fn from_spans(mut vec: Vec<Span>) -> MultiSpan {
103 vec.sort();
104 MultiSpan { primary_spans: vec, span_labels: ::alloc::vec::Vec::new()vec![] }
105 }
106
107 pub fn push_primary_span(&mut self, primary_span: Span) {
108 self.primary_spans.push(primary_span);
109 }
110
111 pub fn push_span_label(&mut self, span: Span, label: impl Into<DiagMessage>) {
112 self.span_labels.push((span, label.into()));
113 }
114
115 pub fn push_span_diag(&mut self, span: Span, diag: DiagMessage) {
116 self.span_labels.push((span, diag));
117 }
118
119 pub fn primary_span(&self) -> Option<Span> {
121 self.primary_spans.first().cloned()
122 }
123
124 pub fn primary_spans(&self) -> &[Span] {
126 &self.primary_spans
127 }
128
129 pub fn has_primary_spans(&self) -> bool {
131 !self.is_dummy()
132 }
133
134 pub fn is_dummy(&self) -> bool {
136 self.primary_spans.iter().all(|sp| sp.is_dummy())
137 }
138
139 pub fn replace(&mut self, before: Span, after: Span) -> bool {
142 let mut replacements_occurred = false;
143 for primary_span in &mut self.primary_spans {
144 if *primary_span == before {
145 *primary_span = after;
146 replacements_occurred = true;
147 }
148 }
149 for span_label in &mut self.span_labels {
150 if span_label.0 == before {
151 span_label.0 = after;
152 replacements_occurred = true;
153 }
154 }
155 replacements_occurred
156 }
157
158 pub fn span_labels(&self) -> Vec<SpanLabel> {
164 let is_primary = |span| self.primary_spans.contains(&span);
165
166 let mut span_labels = self
167 .span_labels
168 .iter()
169 .map(|&(span, ref label)| SpanLabel {
170 span,
171 is_primary: is_primary(span),
172 label: Some(label.clone()),
173 })
174 .collect::<Vec<_>>();
175
176 for &span in &self.primary_spans {
177 if !span_labels.iter().any(|sl| sl.span == span) {
178 span_labels.push(SpanLabel { span, is_primary: true, label: None });
179 }
180 }
181
182 span_labels
183 }
184
185 pub fn span_labels_raw(&self) -> &[(Span, DiagMessage)] {
187 &self.span_labels
188 }
189
190 pub fn has_span_labels(&self) -> bool {
192 self.span_labels.iter().any(|(sp, _)| !sp.is_dummy())
193 }
194
195 pub fn clone_ignoring_labels(&self) -> Self {
200 Self { primary_spans: self.primary_spans.clone(), ..MultiSpan::new() }
201 }
202}
203
204impl From<Span> for MultiSpan {
205 fn from(span: Span) -> MultiSpan {
206 MultiSpan::from_span(span)
207 }
208}
209
210impl From<Vec<Span>> for MultiSpan {
211 fn from(spans: Vec<Span>) -> MultiSpan {
212 MultiSpan::from_spans(spans)
213 }
214}
215
216fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locale::Locale> {
217 icu_locale::Locale::try_from_str(&lang.to_string()).ok()
218}
219
220pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValue<'_> {
221 #[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)]
223 struct FluentStrListSepByAnd(Vec<String>);
224
225 impl FluentType for FluentStrListSepByAnd {
226 fn duplicate(&self) -> Box<dyn FluentType + Send> {
227 Box::new(self.clone())
228 }
229
230 fn as_string(&self, intls: &intl_memoizer::IntlLangMemoizer) -> Cow<'static, str> {
231 let result = intls
232 .with_try_get::<MemoizableListFormatter, _, _>((), |list_formatter| {
233 list_formatter.format_to_string(self.0.iter())
234 })
235 .unwrap();
236 Cow::Owned(result)
237 }
238
239 fn as_string_threadsafe(
240 &self,
241 intls: &intl_memoizer::concurrent::IntlLangMemoizer,
242 ) -> Cow<'static, str> {
243 let result = intls
244 .with_try_get::<MemoizableListFormatter, _, _>((), |list_formatter| {
245 list_formatter.format_to_string(self.0.iter())
246 })
247 .unwrap();
248 Cow::Owned(result)
249 }
250 }
251
252 struct MemoizableListFormatter(icu_list::ListFormatter);
253
254 impl std::ops::Deref for MemoizableListFormatter {
255 type Target = icu_list::ListFormatter;
256 fn deref(&self) -> &Self::Target {
257 &self.0
258 }
259 }
260
261 impl intl_memoizer::Memoizable for MemoizableListFormatter {
262 type Args = ();
263 type Error = ();
264
265 fn construct(lang: LanguageIdentifier, _args: Self::Args) -> Result<Self, Self::Error> {
266 let locale = icu_locale_from_unic_langid(lang)
267 .unwrap_or_else(|| rustc_baked_icu_data::supported_locales::EN);
268 let list_formatter = icu_list::ListFormatter::try_new_and_unstable(
269 &rustc_baked_icu_data::BakedDataProvider,
270 locale.into(),
271 icu_list::options::ListFormatterOptions::default()
272 .with_length(icu_list::options::ListLength::Wide),
273 )
274 .expect("Failed to create list formatter");
275
276 Ok(MemoizableListFormatter(list_formatter))
277 }
278 }
279
280 let l = l.into_iter().map(|x| x.into_owned()).collect();
281
282 FluentValue::Custom(Box::new(FluentStrListSepByAnd(l)))
283}
284
285pub type DiagArg<'iter> = (&'iter DiagArgName, &'iter DiagArgValue);
289
290pub type DiagArgName = Cow<'static, str>;
292
293#[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_fields_are_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)]
296pub enum DiagArgValue {
297 Str(Cow<'static, str>),
298 Number(i32),
302 StrListSepByAnd(Vec<Cow<'static, str>>),
303}
304
305pub type DiagArgMap = FxIndexMap<DiagArgName, DiagArgValue>;
308
309pub trait IntoDiagArg {
314 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue;
321}
322
323impl IntoDiagArg for DiagArgValue {
324 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
325 self
326 }
327}
328
329impl From<DiagArgValue> for FluentValue<'static> {
330 fn from(val: DiagArgValue) -> Self {
331 match val {
332 DiagArgValue::Str(s) => From::from(s),
333 DiagArgValue::Number(n) => From::from(n),
334 DiagArgValue::StrListSepByAnd(l) => fluent_value_from_str_list_sep_by_and(l),
335 }
336 }
337}