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) -> Self {
match self {
Self::Str(__self_0) =>
Self::Str(::core::clone::Clone::clone(__self_0)),
Self::Inline(__self_0) =>
Self::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 {
Self::Str(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Str",
&__self_0),
Self::Inline(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Inline",
&__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for DiagMessage { }
#[automatically_derived]
impl ::core::cmp::PartialEq for DiagMessage {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other) &&
match (self, other) {
(Self::Str(__self_0), Self::Str(__arg1_0)) =>
__self_0 == __arg1_0,
(Self::Inline(__self_0), Self::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) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state);
match self {
Self::Str(__self_0) => ::core::hash::Hash::hash(__self_0, state),
Self::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) -> Self {
Self {
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) -> Self {
Self {
primary_spans: ::core::clone::Clone::clone(&self.primary_spans),
span_labels: ::core::clone::Clone::clone(&self.span_labels),
span_context: ::core::clone::Clone::clone(&self.span_context),
}
}
}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_field3_finish(f, "MultiSpan",
"primary_spans", &self.primary_spans, "span_labels",
&self.span_labels, "span_context", &&self.span_context)
}
}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);
::core::hash::Hash::hash(&self.span_context, state)
}
}Hash, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for MultiSpan { }
#[automatically_derived]
impl ::core::cmp::PartialEq for MultiSpan {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.primary_spans == other.primary_spans &&
self.span_labels == other.span_labels &&
self.span_context == other.span_context
}
}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)>>;
let _: ::core::cmp::AssertParamIsEq<Vec<Span>>;
}
}Eq, const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for MultiSpan {
fn encode(&self, __encoder: &mut __E) {
let MultiSpan {
primary_spans: ref __binding_0,
span_labels: ref __binding_1,
span_context: ref __binding_2 } = *self;
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_2,
__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),
span_context: ::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,
span_context: ref __binding_2 } => {
{ __binding_0.stable_hash(__hcx, __hasher); }
{ __binding_1.stable_hash(__hcx, __hasher); }
{ __binding_2.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash)]
87pub struct MultiSpan {
88 primary_spans: Vec<Span>,
89 span_labels: Vec<(Span, DiagMessage)>,
90 span_context: Vec<Span>,
91}
92
93impl MultiSpan {
94 #[inline]
95 pub fn new() -> MultiSpan {
96 MultiSpan { primary_spans: ::alloc::vec::Vec::new()vec![], span_labels: ::alloc::vec::Vec::new()vec![], span_context: ::alloc::vec::Vec::new()vec![] }
97 }
98
99 pub fn from_span(primary_span: Span) -> MultiSpan {
100 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![], span_context: ::alloc::vec::Vec::new()vec![] }
101 }
102
103 pub fn from_spans(mut vec: Vec<Span>) -> MultiSpan {
104 vec.sort();
105 MultiSpan { primary_spans: vec, span_labels: ::alloc::vec::Vec::new()vec![], span_context: ::alloc::vec::Vec::new()vec![] }
106 }
107
108 pub fn push_primary_span(&mut self, primary_span: Span) {
109 self.primary_spans.push(primary_span);
110 }
111
112 pub fn push_span_label(&mut self, span: Span, label: impl Into<DiagMessage>) {
113 self.span_labels.push((span, label.into()));
114 }
115
116 pub fn push_span_context(&mut self, span: Span) {
117 self.span_context.push(span);
118 }
119
120 pub fn push_span_diag(&mut self, span: Span, diag: DiagMessage) {
121 self.span_labels.push((span, diag));
122 }
123
124 pub fn primary_span(&self) -> Option<Span> {
126 self.primary_spans.first().cloned()
127 }
128
129 pub fn primary_spans(&self) -> &[Span] {
131 &self.primary_spans
132 }
133
134 pub fn has_primary_spans(&self) -> bool {
136 !self.is_dummy()
137 }
138
139 pub fn is_dummy(&self) -> bool {
141 self.primary_spans.iter().all(|sp| sp.is_dummy())
142 }
143
144 pub fn replace(&mut self, before: Span, after: Span) -> bool {
147 let mut replacements_occurred = false;
148 for primary_span in &mut self.primary_spans {
149 if *primary_span == before {
150 *primary_span = after;
151 replacements_occurred = true;
152 }
153 }
154 for span_label in &mut self.span_labels {
155 if span_label.0 == before {
156 span_label.0 = after;
157 replacements_occurred = true;
158 }
159 }
160 replacements_occurred
161 }
162
163 pub fn span_labels(&self) -> Vec<SpanLabel> {
169 let is_primary = |span| self.primary_spans.contains(&span);
170
171 let mut span_labels = self
172 .span_labels
173 .iter()
174 .map(|&(span, ref label)| SpanLabel {
175 span,
176 is_primary: is_primary(span),
177 label: Some(label.clone()),
178 })
179 .collect::<Vec<_>>();
180
181 for &span in &self.primary_spans {
182 if !span_labels.iter().any(|sl| sl.span == span) {
183 span_labels.push(SpanLabel { span, is_primary: true, label: None });
184 }
185 }
186
187 span_labels
188 }
189
190 pub fn span_context(&self) -> &[Span] {
191 &self.span_context
192 }
193
194 pub fn span_labels_raw(&self) -> &[(Span, DiagMessage)] {
196 &self.span_labels
197 }
198
199 pub fn has_span_labels(&self) -> bool {
201 self.span_labels.iter().any(|(sp, _)| !sp.is_dummy())
202 }
203
204 pub fn clone_ignoring_labels(&self) -> Self {
209 Self { primary_spans: self.primary_spans.clone(), ..MultiSpan::new() }
210 }
211}
212
213impl From<Span> for MultiSpan {
214 fn from(span: Span) -> MultiSpan {
215 MultiSpan::from_span(span)
216 }
217}
218
219impl From<Vec<Span>> for MultiSpan {
220 fn from(spans: Vec<Span>) -> MultiSpan {
221 MultiSpan::from_spans(spans)
222 }
223}
224
225fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locale_core::Locale> {
226 icu_locale_core::Locale::try_from_str(&lang.to_string()).ok()
227}
228
229pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValue<'_> {
230 #[derive(#[automatically_derived]
impl ::core::clone::Clone for FluentStrListSepByAnd {
#[inline]
fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&self.0)) }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for FluentStrListSepByAnd { }
#[automatically_derived]
impl ::core::cmp::PartialEq for FluentStrListSepByAnd {
#[inline]
fn eq(&self, other: &Self) -> 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)]
232 struct FluentStrListSepByAnd(Vec<String>);
233
234 impl FluentType for FluentStrListSepByAnd {
235 fn duplicate(&self) -> Box<dyn FluentType + Send> {
236 Box::new(self.clone())
237 }
238
239 fn as_string(&self, intls: &intl_memoizer::IntlLangMemoizer) -> Cow<'static, str> {
240 let result = intls
241 .with_try_get::<MemoizableListFormatter, _, _>((), |list_formatter| {
242 list_formatter.format_to_string(self.0.iter())
243 })
244 .unwrap();
245 Cow::Owned(result)
246 }
247
248 fn as_string_threadsafe(
249 &self,
250 intls: &intl_memoizer::concurrent::IntlLangMemoizer,
251 ) -> Cow<'static, str> {
252 let result = intls
253 .with_try_get::<MemoizableListFormatter, _, _>((), |list_formatter| {
254 list_formatter.format_to_string(self.0.iter())
255 })
256 .unwrap();
257 Cow::Owned(result)
258 }
259 }
260
261 struct MemoizableListFormatter(icu_list::ListFormatter);
262
263 impl std::ops::Deref for MemoizableListFormatter {
264 type Target = icu_list::ListFormatter;
265 fn deref(&self) -> &Self::Target {
266 &self.0
267 }
268 }
269
270 impl intl_memoizer::Memoizable for MemoizableListFormatter {
271 type Args = ();
272 type Error = ();
273
274 fn construct(lang: LanguageIdentifier, _args: Self::Args) -> Result<Self, Self::Error> {
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) -> Self {
match self {
Self::Str(__self_0) =>
Self::Str(::core::clone::Clone::clone(__self_0)),
Self::Number(__self_0) =>
Self::Number(::core::clone::Clone::clone(__self_0)),
Self::StrListSepByAnd(__self_0) =>
Self::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 {
Self::Str(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Str",
&__self_0),
Self::Number(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Number",
&__self_0),
Self::StrListSepByAnd(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"StrListSepByAnd", &__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for DiagArgValue { }
#[automatically_derived]
impl ::core::cmp::PartialEq for DiagArgValue {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other) &&
match (self, other) {
(Self::Str(__self_0), Self::Str(__arg1_0)) =>
__self_0 == __arg1_0,
(Self::Number(__self_0), Self::Number(__arg1_0)) =>
__self_0 == __arg1_0,
(Self::StrListSepByAnd(__self_0),
Self::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) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state);
match self {
Self::Str(__self_0) => ::core::hash::Hash::hash(__self_0, state),
Self::Number(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Self::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}