1#![allow(internal_features)]
3#![feature(rustc_attrs)]
4use std::borrow::Cow;
7
8pub use fluent_bundle::types::FluentType;
9pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue};
10use rustc_macros::{Decodable, Encodable};
11use rustc_span::Span;
12pub use unic_langid::{LanguageIdentifier, langid};
13
14mod diagnostic_impls;
15pub use diagnostic_impls::DiagArgFromDisplay;
16use rustc_data_structures::fx::FxIndexMap;
17
18pub fn register_functions<R, M>(bundle: &mut fluent_bundle::bundle::FluentBundle<R, M>) {
19 bundle
20 .add_function("STREQ", |positional, _named| match positional {
21 [FluentValue::String(a), FluentValue::String(b)] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", (a == b)))
})format!("{}", (a == b)).into(),
22 _ => FluentValue::Error,
23 })
24 .expect("Failed to add a function to the bundle.");
25}
26
27#[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)]
32#[rustc_diagnostic_item = "DiagMessage"]
33pub enum DiagMessage {
34 Str(Cow<'static, str>),
41 Inline(Cow<'static, str>),
43}
44
45impl DiagMessage {
46 pub fn as_str(&self) -> Option<&str> {
47 match self {
48 DiagMessage::Str(s) => Some(s),
49 DiagMessage::Inline(_) => None,
50 }
51 }
52}
53
54impl From<String> for DiagMessage {
55 fn from(s: String) -> Self {
56 DiagMessage::Str(Cow::Owned(s))
57 }
58}
59impl From<&'static str> for DiagMessage {
60 fn from(s: &'static str) -> Self {
61 DiagMessage::Str(Cow::Borrowed(s))
62 }
63}
64impl From<Cow<'static, str>> for DiagMessage {
65 fn from(s: Cow<'static, str>) -> Self {
66 DiagMessage::Str(s)
67 }
68}
69
70#[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)]
72pub struct SpanLabel {
73 pub span: Span,
75
76 pub is_primary: bool,
79
80 pub label: Option<DiagMessage>,
82}
83
84#[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)]
93pub struct MultiSpan {
94 primary_spans: Vec<Span>,
95 span_labels: Vec<(Span, DiagMessage)>,
96}
97
98impl MultiSpan {
99 #[inline]
100 pub fn new() -> MultiSpan {
101 MultiSpan { primary_spans: ::alloc::vec::Vec::new()vec![], span_labels: ::alloc::vec::Vec::new()vec![] }
102 }
103
104 pub fn from_span(primary_span: Span) -> MultiSpan {
105 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![] }
106 }
107
108 pub fn from_spans(mut vec: Vec<Span>) -> MultiSpan {
109 vec.sort();
110 MultiSpan { primary_spans: vec, span_labels: ::alloc::vec::Vec::new()vec![] }
111 }
112
113 pub fn push_primary_span(&mut self, primary_span: Span) {
114 self.primary_spans.push(primary_span);
115 }
116
117 pub fn push_span_label(&mut self, span: Span, label: impl Into<DiagMessage>) {
118 self.span_labels.push((span, label.into()));
119 }
120
121 pub fn push_span_diag(&mut self, span: Span, diag: DiagMessage) {
122 self.span_labels.push((span, diag));
123 }
124
125 pub fn primary_span(&self) -> Option<Span> {
127 self.primary_spans.first().cloned()
128 }
129
130 pub fn primary_spans(&self) -> &[Span] {
132 &self.primary_spans
133 }
134
135 pub fn has_primary_spans(&self) -> bool {
137 !self.is_dummy()
138 }
139
140 pub fn is_dummy(&self) -> bool {
142 self.primary_spans.iter().all(|sp| sp.is_dummy())
143 }
144
145 pub fn replace(&mut self, before: Span, after: Span) -> bool {
148 let mut replacements_occurred = false;
149 for primary_span in &mut self.primary_spans {
150 if *primary_span == before {
151 *primary_span = after;
152 replacements_occurred = true;
153 }
154 }
155 for span_label in &mut self.span_labels {
156 if span_label.0 == before {
157 span_label.0 = after;
158 replacements_occurred = true;
159 }
160 }
161 replacements_occurred
162 }
163
164 pub fn span_labels(&self) -> Vec<SpanLabel> {
170 let is_primary = |span| self.primary_spans.contains(&span);
171
172 let mut span_labels = self
173 .span_labels
174 .iter()
175 .map(|&(span, ref label)| SpanLabel {
176 span,
177 is_primary: is_primary(span),
178 label: Some(label.clone()),
179 })
180 .collect::<Vec<_>>();
181
182 for &span in &self.primary_spans {
183 if !span_labels.iter().any(|sl| sl.span == span) {
184 span_labels.push(SpanLabel { span, is_primary: true, label: None });
185 }
186 }
187
188 span_labels
189 }
190
191 pub fn span_labels_raw(&self) -> &[(Span, DiagMessage)] {
193 &self.span_labels
194 }
195
196 pub fn has_span_labels(&self) -> bool {
198 self.span_labels.iter().any(|(sp, _)| !sp.is_dummy())
199 }
200
201 pub fn clone_ignoring_labels(&self) -> Self {
206 Self { primary_spans: self.primary_spans.clone(), ..MultiSpan::new() }
207 }
208}
209
210impl From<Span> for MultiSpan {
211 fn from(span: Span) -> MultiSpan {
212 MultiSpan::from_span(span)
213 }
214}
215
216impl From<Vec<Span>> for MultiSpan {
217 fn from(spans: Vec<Span>) -> MultiSpan {
218 MultiSpan::from_spans(spans)
219 }
220}
221
222fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locale::Locale> {
223 icu_locale::Locale::try_from_str(&lang.to_string()).ok()
224}
225
226pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValue<'_> {
227 #[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)]
229 struct FluentStrListSepByAnd(Vec<String>);
230
231 impl FluentType for FluentStrListSepByAnd {
232 fn duplicate(&self) -> Box<dyn FluentType + Send> {
233 Box::new(self.clone())
234 }
235
236 fn as_string(&self, intls: &intl_memoizer::IntlLangMemoizer) -> Cow<'static, str> {
237 let result = intls
238 .with_try_get::<MemoizableListFormatter, _, _>((), |list_formatter| {
239 list_formatter.format_to_string(self.0.iter())
240 })
241 .unwrap();
242 Cow::Owned(result)
243 }
244
245 fn as_string_threadsafe(
246 &self,
247 intls: &intl_memoizer::concurrent::IntlLangMemoizer,
248 ) -> Cow<'static, str> {
249 let result = intls
250 .with_try_get::<MemoizableListFormatter, _, _>((), |list_formatter| {
251 list_formatter.format_to_string(self.0.iter())
252 })
253 .unwrap();
254 Cow::Owned(result)
255 }
256 }
257
258 struct MemoizableListFormatter(icu_list::ListFormatter);
259
260 impl std::ops::Deref for MemoizableListFormatter {
261 type Target = icu_list::ListFormatter;
262 fn deref(&self) -> &Self::Target {
263 &self.0
264 }
265 }
266
267 impl intl_memoizer::Memoizable for MemoizableListFormatter {
268 type Args = ();
269 type Error = ();
270
271 fn construct(lang: LanguageIdentifier, _args: Self::Args) -> Result<Self, Self::Error>
272 where
273 Self: Sized,
274 {
275 let locale = icu_locale_from_unic_langid(lang)
276 .unwrap_or_else(|| rustc_baked_icu_data::supported_locales::EN);
277 let list_formatter = icu_list::ListFormatter::try_new_and_unstable(
278 &rustc_baked_icu_data::BakedDataProvider,
279 locale.into(),
280 icu_list::options::ListFormatterOptions::default()
281 .with_length(icu_list::options::ListLength::Wide),
282 )
283 .expect("Failed to create list formatter");
284
285 Ok(MemoizableListFormatter(list_formatter))
286 }
287 }
288
289 let l = l.into_iter().map(|x| x.into_owned()).collect();
290
291 FluentValue::Custom(Box::new(FluentStrListSepByAnd(l)))
292}
293
294pub type DiagArg<'iter> = (&'iter DiagArgName, &'iter DiagArgValue);
298
299pub type DiagArgName = Cow<'static, str>;
301
302#[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)]
305pub enum DiagArgValue {
306 Str(Cow<'static, str>),
307 Number(i32),
311 StrListSepByAnd(Vec<Cow<'static, str>>),
312}
313
314pub type DiagArgMap = FxIndexMap<DiagArgName, DiagArgValue>;
317
318pub trait IntoDiagArg {
323 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue;
330}
331
332impl IntoDiagArg for DiagArgValue {
333 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
334 self
335 }
336}
337
338impl From<DiagArgValue> for FluentValue<'static> {
339 fn from(val: DiagArgValue) -> Self {
340 match val {
341 DiagArgValue::Str(s) => From::from(s),
342 DiagArgValue::Number(n) => From::from(n),
343 DiagArgValue::StrListSepByAnd(l) => fluent_value_from_str_list_sep_by_and(l),
344 }
345 }
346}