1use std::ops::Range;
2
3use rustc_errors::E0232;
4use rustc_hir::AttrPath;
5use rustc_hir::attrs::diagnostic::{
6 AppendConstMessage, Directive, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg,
7 Name, NameValue, OnUnimplementedCondition, Piece, Predicate,
8};
9use rustc_hir::lints::{AttributeLintKind, FormatWarning};
10use rustc_macros::Diagnostic;
11use rustc_parse_format::{
12 Argument, FormatSpec, ParseError, ParseMode, Parser, Piece as RpfPiece, Position,
13};
14use rustc_session::lint::builtin::{
15 MALFORMED_DIAGNOSTIC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
16};
17use rustc_span::{Ident, InnerSpan, Span, Symbol, kw, sym};
18use thin_vec::{ThinVec, thin_vec};
19
20use crate::context::{AcceptContext, Stage};
21use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser};
22
23pub(crate) mod do_not_recommend;
24pub(crate) mod on_const;
25pub(crate) mod on_unimplemented;
26
27#[derive(#[automatically_derived]
impl ::core::marker::Copy for Mode { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Mode {
#[inline]
fn clone(&self) -> Mode { *self }
}Clone)]
28pub(crate) enum Mode {
29 RustcOnUnimplemented,
31 DiagnosticOnUnimplemented,
33 DiagnosticOnConst,
35}
36
37fn merge_directives<S: Stage>(
38 cx: &mut AcceptContext<'_, '_, S>,
39 first: &mut Option<(Span, Directive)>,
40 later: (Span, Directive),
41) {
42 if let Some((_, first)) = first {
43 if first.is_rustc_attr || later.1.is_rustc_attr {
44 cx.emit_err(DupesNotAllowed);
45 }
46
47 merge(cx, &mut first.message, later.1.message, sym::message);
48 merge(cx, &mut first.label, later.1.label, sym::label);
49 first.notes.extend(later.1.notes);
50 } else {
51 *first = Some(later);
52 }
53}
54
55fn merge<T, S: Stage>(
56 cx: &mut AcceptContext<'_, '_, S>,
57 first: &mut Option<(Span, T)>,
58 later: Option<(Span, T)>,
59 option_name: Symbol,
60) {
61 match (first, later) {
62 (Some(_) | None, None) => {}
63 (Some((first_span, _)), Some((later_span, _))) => {
64 cx.emit_lint(
65 MALFORMED_DIAGNOSTIC_ATTRIBUTES,
66 AttributeLintKind::IgnoredDiagnosticOption {
67 first_span: *first_span,
68 later_span,
69 option_name,
70 },
71 later_span,
72 );
73 }
74 (first @ None, Some(later)) => {
75 first.get_or_insert(later);
76 }
77 }
78}
79
80fn parse_directive_items<'p, S: Stage>(
81 cx: &mut AcceptContext<'_, '_, S>,
82 mode: Mode,
83 items: impl Iterator<Item = &'p MetaItemOrLitParser>,
84 is_root: bool,
85) -> Option<Directive> {
86 let condition = None;
87 let mut message: Option<(Span, _)> = None;
88 let mut label: Option<(Span, _)> = None;
89 let mut notes = ThinVec::new();
90 let mut parent_label = None;
91 let mut subcommands = ThinVec::new();
92 let mut append_const_msg = None;
93
94 for item in items {
95 let span = item.span();
96
97 macro malformed() {{
98 match mode {
99 Mode::RustcOnUnimplemented => {
100 cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
101 }
102 Mode::DiagnosticOnUnimplemented => {
103 cx.emit_lint(
104 MALFORMED_DIAGNOSTIC_ATTRIBUTES,
105 AttributeLintKind::MalformedOnUnimplementedAttr { span },
106 span,
107 );
108 }
109 Mode::DiagnosticOnConst => {
110 cx.emit_lint(
111 MALFORMED_DIAGNOSTIC_ATTRIBUTES,
112 AttributeLintKind::MalformedOnConstAttr { span },
113 span,
114 );
115 }
116 }
117 continue;
118 }}
119
120 macro or_malformed($($code:tt)*) {{
121 let Some(ret) = (||{
122 Some($($code)*)
123 })() else {
124
125 malformed!()
126 };
127 ret
128 }}
129
130 macro duplicate($name: ident, $($first_span:tt)*) {{
131 match mode {
132 Mode::RustcOnUnimplemented => {
133 cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
134 }
135 Mode::DiagnosticOnUnimplemented |Mode::DiagnosticOnConst => {
136 cx.emit_lint(
137 MALFORMED_DIAGNOSTIC_ATTRIBUTES,
138 AttributeLintKind::IgnoredDiagnosticOption {
139 first_span: $($first_span)*,
140 later_span: span,
141 option_name: $name,
142 },
143 span,
144 );
145 }
146 }
147 }}
148
149 let item: &MetaItemParser = {
let Some(ret) =
(||
{
Some(item.meta_item()?)
})() else {
{
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnUnimplementedAttr { span },
span);
}
Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnConstAttr { span }, span);
}
}
continue;
}
};
ret
}or_malformed!(item.meta_item()?);
150 let name = {
let Some(ret) =
(||
{
Some(item.ident()?)
})() else {
{
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnUnimplementedAttr { span },
span);
}
Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnConstAttr { span }, span);
}
}
continue;
}
};
ret
}or_malformed!(item.ident()?).name;
151
152 let value: Option<Ident> = match item.args().name_value() {
155 Some(nv) => Some({
let Some(ret) =
(||
{
Some(nv.value_as_ident()?)
})() else {
{
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnUnimplementedAttr { span },
span);
}
Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnConstAttr { span }, span);
}
}
continue;
}
};
ret
}or_malformed!(nv.value_as_ident()?)),
156 None => None,
157 };
158
159 let mut parse_format = |input: Ident| {
160 let snippet = cx.sess.source_map().span_to_snippet(input.span).ok();
161 let is_snippet = snippet.is_some();
162 match parse_format_string(input.name, snippet, input.span, mode) {
163 Ok((f, warnings)) => {
164 for warning in warnings {
165 let (FormatWarning::InvalidSpecifier { span, .. }
166 | FormatWarning::PositionalArgument { span, .. }) = warning;
167 cx.emit_lint(
168 MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
169 AttributeLintKind::MalformedDiagnosticFormat { warning },
170 span,
171 );
172 }
173
174 f
175 }
176 Err(e) => {
177 cx.emit_lint(
178 MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
179 AttributeLintKind::DiagnosticWrappedParserError {
180 description: e.description,
181 label: e.label,
182 span: slice_span(input.span, e.span, is_snippet),
183 },
184 input.span,
185 );
186 FormatString {
188 input: input.name,
189 span: input.span,
190 pieces: {
let len = [()].len();
let mut vec = ::thin_vec::ThinVec::with_capacity(len);
vec.push(Piece::Lit(input.name));
vec
}thin_vec![Piece::Lit(input.name)],
191 }
192 }
193 }
194 };
195 match (mode, name) {
196 (_, sym::message) => {
197 let value = {
let Some(ret) =
(||
{
Some(value?)
})() else {
{
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnUnimplementedAttr { span },
span);
}
Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnConstAttr { span }, span);
}
}
continue;
}
};
ret
}or_malformed!(value?);
198 if let Some(message) = &message {
199 {
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented | Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::IgnoredDiagnosticOption {
first_span: message.0,
later_span: span,
option_name: name,
}, span);
}
}
}duplicate!(name, message.0)
200 } else {
201 message = Some((item.span(), parse_format(value)));
202 }
203 }
204 (_, sym::label) => {
205 let value = {
let Some(ret) =
(||
{
Some(value?)
})() else {
{
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnUnimplementedAttr { span },
span);
}
Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnConstAttr { span }, span);
}
}
continue;
}
};
ret
}or_malformed!(value?);
206 if let Some(label) = &label {
207 {
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented | Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::IgnoredDiagnosticOption {
first_span: label.0,
later_span: span,
option_name: name,
}, span);
}
}
}duplicate!(name, label.0)
208 } else {
209 label = Some((item.span(), parse_format(value)));
210 }
211 }
212 (_, sym::note) => {
213 let value = {
let Some(ret) =
(||
{
Some(value?)
})() else {
{
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnUnimplementedAttr { span },
span);
}
Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnConstAttr { span }, span);
}
}
continue;
}
};
ret
}or_malformed!(value?);
214 notes.push(parse_format(value))
215 }
216
217 (Mode::RustcOnUnimplemented, sym::append_const_msg) => {
218 append_const_msg = if let Some(msg) = value {
219 Some(AppendConstMessage::Custom(msg.name, item.span()))
220 } else {
221 Some(AppendConstMessage::Default)
222 }
223 }
224 (Mode::RustcOnUnimplemented, sym::parent_label) => {
225 let value = {
let Some(ret) =
(||
{
Some(value?)
})() else {
{
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnUnimplementedAttr { span },
span);
}
Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnConstAttr { span }, span);
}
}
continue;
}
};
ret
}or_malformed!(value?);
226 if parent_label.is_none() {
227 parent_label = Some(parse_format(value));
228 } else {
229 {
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented | Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::IgnoredDiagnosticOption {
first_span: span,
later_span: span,
option_name: name,
}, span);
}
}
}duplicate!(name, span)
230 }
231 }
232 (Mode::RustcOnUnimplemented, sym::on) => {
233 if is_root {
234 let items = {
let Some(ret) =
(||
{
Some(item.args().list()?)
})() else {
{
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnUnimplementedAttr { span },
span);
}
Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnConstAttr { span }, span);
}
}
continue;
}
};
ret
}or_malformed!(item.args().list()?);
235 let mut iter = items.mixed();
236 let condition: &MetaItemOrLitParser = match iter.next() {
237 Some(c) => c,
238 None => {
239 cx.emit_err(InvalidOnClause::Empty { span });
240 continue;
241 }
242 };
243
244 let condition = parse_condition(condition);
245
246 if items.len() < 2 {
247 {
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnUnimplementedAttr { span },
span);
}
Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnConstAttr { span }, span);
}
}
continue;
};malformed!();
250 }
251
252 let mut directive =
253 {
let Some(ret) =
(||
{
Some(parse_directive_items(cx, mode, iter, false)?)
})() else {
{
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnUnimplementedAttr { span },
span);
}
Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnConstAttr { span }, span);
}
}
continue;
}
};
ret
}or_malformed!(parse_directive_items(cx, mode, iter, false)?);
254
255 match condition {
256 Ok(c) => {
257 directive.condition = Some(c);
258 subcommands.push(directive);
259 }
260 Err(e) => {
261 cx.emit_err(e);
262 }
263 }
264 } else {
265 {
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnUnimplementedAttr { span },
span);
}
Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnConstAttr { span }, span);
}
}
continue;
};malformed!();
266 }
267 }
268
269 _other => {
270 {
match mode {
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnUnimplementedAttr { span },
span);
}
Mode::DiagnosticOnConst => {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnConstAttr { span }, span);
}
}
continue;
};malformed!();
271 }
272 }
273 }
274
275 Some(Directive {
276 is_rustc_attr: #[allow(non_exhaustive_omitted_patterns)] match mode {
Mode::RustcOnUnimplemented => true,
_ => false,
}matches!(mode, Mode::RustcOnUnimplemented),
277 condition,
278 subcommands,
279 message,
280 label,
281 notes,
282 parent_label,
283 append_const_msg,
284 })
285}
286
287pub(crate) fn parse_format_string(
288 input: Symbol,
289 snippet: Option<String>,
290 span: Span,
291 mode: Mode,
292) -> Result<(FormatString, Vec<FormatWarning>), ParseError> {
293 let s = input.as_str();
294 let mut parser = Parser::new(s, None, snippet, false, ParseMode::Diagnostic);
295 let pieces: Vec<_> = parser.by_ref().collect();
296
297 if let Some(err) = parser.errors.into_iter().next() {
298 return Err(err);
299 }
300 let mut warnings = Vec::new();
301
302 let pieces = pieces
303 .into_iter()
304 .map(|piece| match piece {
305 RpfPiece::Lit(lit) => Piece::Lit(Symbol::intern(lit)),
306 RpfPiece::NextArgument(arg) => {
307 warn_on_format_spec(&arg.format, &mut warnings, span, parser.is_source_literal);
308 let arg = parse_arg(&arg, mode, &mut warnings, span, parser.is_source_literal);
309 Piece::Arg(arg)
310 }
311 })
312 .collect();
313
314 Ok((FormatString { input, pieces, span }, warnings))
315}
316
317fn parse_arg(
318 arg: &Argument<'_>,
319 mode: Mode,
320 warnings: &mut Vec<FormatWarning>,
321 input_span: Span,
322 is_source_literal: bool,
323) -> FormatArg {
324 let span = slice_span(input_span, arg.position_span.clone(), is_source_literal);
325
326 match arg.position {
327 Position::ArgumentNamed(name) => match (mode, Symbol::intern(name)) {
329 (Mode::RustcOnUnimplemented { .. }, sym::ItemContext) => FormatArg::ItemContext,
331 (Mode::RustcOnUnimplemented { .. }, sym::This) => FormatArg::This,
332 (Mode::RustcOnUnimplemented { .. }, sym::Trait) => FormatArg::Trait,
333 (_, kw::SelfUpper) => FormatArg::SelfUpper,
335 (_, generic_param) => FormatArg::GenericParam { generic_param, span },
336 },
337
338 Position::ArgumentIs(idx) => {
340 warnings.push(FormatWarning::PositionalArgument {
341 span,
342 help: ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use `{{{0}}}` to print a number in braces",
idx))
})format!("use `{{{idx}}}` to print a number in braces"),
343 });
344 FormatArg::AsIs(Symbol::intern(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}}}", idx))
})format!("{{{idx}}}")))
345 }
346 Position::ArgumentImplicitlyIs(_) => {
347 warnings.push(FormatWarning::PositionalArgument {
348 span,
349 help: String::from("use `{{}}` to print empty braces"),
350 });
351 FormatArg::AsIs(sym::empty_braces)
352 }
353 }
354}
355
356fn warn_on_format_spec(
359 spec: &FormatSpec<'_>,
360 warnings: &mut Vec<FormatWarning>,
361 input_span: Span,
362 is_source_literal: bool,
363) {
364 if spec.ty != "" {
365 let span = spec
366 .ty_span
367 .as_ref()
368 .map(|inner| slice_span(input_span, inner.clone(), is_source_literal))
369 .unwrap_or(input_span);
370 warnings.push(FormatWarning::InvalidSpecifier { span, name: spec.ty.into() })
371 }
372}
373
374fn slice_span(input: Span, Range { start, end }: Range<usize>, is_source_literal: bool) -> Span {
375 if is_source_literal { input.from_inner(InnerSpan { start, end }) } else { input }
376}
377
378pub(crate) fn parse_condition(
379 input: &MetaItemOrLitParser,
380) -> Result<OnUnimplementedCondition, InvalidOnClause> {
381 let span = input.span();
382 let pred = parse_predicate(input)?;
383 Ok(OnUnimplementedCondition { span, pred })
384}
385
386fn parse_predicate(input: &MetaItemOrLitParser) -> Result<Predicate, InvalidOnClause> {
387 let Some(meta_item) = input.meta_item() else {
388 return Err(InvalidOnClause::UnsupportedLiteral { span: input.span() });
389 };
390
391 let Some(predicate) = meta_item.ident() else {
392 return Err(InvalidOnClause::ExpectedIdentifier {
393 span: meta_item.path().span(),
394 path: meta_item.path().get_attribute_path(),
395 });
396 };
397
398 match meta_item.args() {
399 ArgParser::List(mis) => match predicate.name {
400 sym::any => Ok(Predicate::Any(parse_predicate_sequence(mis)?)),
401 sym::all => Ok(Predicate::All(parse_predicate_sequence(mis)?)),
402 sym::not => {
403 if let Some(single) = mis.single() {
404 Ok(Predicate::Not(Box::new(parse_predicate(single)?)))
405 } else {
406 Err(InvalidOnClause::ExpectedOnePredInNot { span: mis.span })
407 }
408 }
409 invalid_pred => {
410 Err(InvalidOnClause::InvalidPredicate { span: predicate.span, invalid_pred })
411 }
412 },
413 ArgParser::NameValue(p) => {
414 let Some(value) = p.value_as_ident() else {
415 return Err(InvalidOnClause::UnsupportedLiteral { span: p.args_span() });
416 };
417 let name = parse_name(predicate.name);
418 let value = parse_filter(value.name);
419 let kv = NameValue { name, value };
420 Ok(Predicate::Match(kv))
421 }
422 ArgParser::NoArgs => {
423 let flag = parse_flag(predicate)?;
424 Ok(Predicate::Flag(flag))
425 }
426 }
427}
428
429fn parse_predicate_sequence(
430 sequence: &MetaItemListParser,
431) -> Result<ThinVec<Predicate>, InvalidOnClause> {
432 sequence.mixed().map(parse_predicate).collect()
433}
434
435fn parse_flag(Ident { name, span }: Ident) -> Result<Flag, InvalidOnClause> {
436 match name {
437 sym::crate_local => Ok(Flag::CrateLocal),
438 sym::direct => Ok(Flag::Direct),
439 sym::from_desugaring => Ok(Flag::FromDesugaring),
440 invalid_flag => Err(InvalidOnClause::InvalidFlag { invalid_flag, span }),
441 }
442}
443
444fn parse_name(name: Symbol) -> Name {
445 match name {
446 kw::SelfUpper => Name::SelfUpper,
447 sym::from_desugaring => Name::FromDesugaring,
448 sym::cause => Name::Cause,
449 generic => Name::GenericArg(generic),
450 }
451}
452
453fn parse_filter(input: Symbol) -> FilterFormatString {
454 let pieces = Parser::new(input.as_str(), None, None, false, ParseMode::Diagnostic)
455 .map(|p| match p {
456 RpfPiece::Lit(s) => LitOrArg::Lit(Symbol::intern(s)),
457 RpfPiece::NextArgument(a) => match a.position {
459 Position::ArgumentNamed(arg @ ("integer" | "integral" | "float")) => {
466 LitOrArg::Lit(Symbol::intern(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}}}", arg))
})format!("{{{arg}}}")))
467 }
468
469 Position::ArgumentNamed(arg) => LitOrArg::Arg(Symbol::intern(arg)),
470 Position::ArgumentImplicitlyIs(_) => LitOrArg::Lit(sym::empty_braces),
471 Position::ArgumentIs(idx) => LitOrArg::Lit(Symbol::intern(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}}}", idx))
})format!("{{{idx}}}"))),
472 },
473 })
474 .collect();
475 FilterFormatString { pieces }
476}
477
478#[derive(const _: () =
{
impl<'_sess, G> rustc_errors::Diagnostic<'_sess, G> for
InvalidOnClause where G: rustc_errors::EmissionGuarantee {
#[track_caller]
fn into_diag(self, dcx: rustc_errors::DiagCtxtHandle<'_sess>,
level: rustc_errors::Level) -> rustc_errors::Diag<'_sess, G> {
match self {
InvalidOnClause::Empty { span: __binding_0 } => {
let mut diag =
rustc_errors::Diag::new(dcx, level,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("empty `on`-clause in `#[rustc_on_unimplemented]`")));
diag.code(E0232);
;
diag.span(__binding_0);
diag.span_label(__binding_0,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("empty `on`-clause here")));
diag
}
InvalidOnClause::ExpectedOnePredInNot { span: __binding_0 }
=> {
let mut diag =
rustc_errors::Diag::new(dcx, level,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("expected a single predicate in `not(..)`")));
diag.code(E0232);
;
diag.span(__binding_0);
diag.span_label(__binding_0,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("unexpected quantity of predicates here")));
diag
}
InvalidOnClause::UnsupportedLiteral { span: __binding_0 } =>
{
let mut diag =
rustc_errors::Diag::new(dcx, level,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("literals inside `on`-clauses are not supported")));
diag.code(E0232);
;
diag.span(__binding_0);
diag.span_label(__binding_0,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("unexpected literal here")));
diag
}
InvalidOnClause::ExpectedIdentifier {
span: __binding_0, path: __binding_1 } => {
let mut diag =
rustc_errors::Diag::new(dcx, level,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("expected an identifier inside this `on`-clause")));
diag.code(E0232);
;
diag.arg("path", __binding_1);
diag.span(__binding_0);
diag.span_label(__binding_0,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("expected an identifier here, not `{$path}`")));
diag
}
InvalidOnClause::InvalidPredicate {
span: __binding_0, invalid_pred: __binding_1 } => {
let mut diag =
rustc_errors::Diag::new(dcx, level,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("this predicate is invalid")));
diag.code(E0232);
;
diag.arg("invalid_pred", __binding_1);
diag.span(__binding_0);
diag.span_label(__binding_0,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("expected one of `any`, `all` or `not` here, not `{$invalid_pred}`")));
diag
}
InvalidOnClause::InvalidFlag {
span: __binding_0, invalid_flag: __binding_1 } => {
let mut diag =
rustc_errors::Diag::new(dcx, level,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("invalid flag in `on`-clause")));
diag.code(E0232);
;
diag.arg("invalid_flag", __binding_1);
diag.span(__binding_0);
diag.span_label(__binding_0,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}`")));
diag
}
}
}
}
};Diagnostic)]
479pub(crate) enum InvalidOnClause {
480 #[diag("empty `on`-clause in `#[rustc_on_unimplemented]`", code = E0232)]
481 Empty {
482 #[primary_span]
483 #[label("empty `on`-clause here")]
484 span: Span,
485 },
486 #[diag("expected a single predicate in `not(..)`", code = E0232)]
487 ExpectedOnePredInNot {
488 #[primary_span]
489 #[label("unexpected quantity of predicates here")]
490 span: Span,
491 },
492 #[diag("literals inside `on`-clauses are not supported", code = E0232)]
493 UnsupportedLiteral {
494 #[primary_span]
495 #[label("unexpected literal here")]
496 span: Span,
497 },
498 #[diag("expected an identifier inside this `on`-clause", code = E0232)]
499 ExpectedIdentifier {
500 #[primary_span]
501 #[label("expected an identifier here, not `{$path}`")]
502 span: Span,
503 path: AttrPath,
504 },
505 #[diag("this predicate is invalid", code = E0232)]
506 InvalidPredicate {
507 #[primary_span]
508 #[label("expected one of `any`, `all` or `not` here, not `{$invalid_pred}`")]
509 span: Span,
510 invalid_pred: Symbol,
511 },
512 #[diag("invalid flag in `on`-clause", code = E0232)]
513 InvalidFlag {
514 #[primary_span]
515 #[label(
516 "expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}`"
517 )]
518 span: Span,
519 invalid_flag: Symbol,
520 },
521}
522
523#[derive(const _: () =
{
impl<'_sess, G> rustc_errors::Diagnostic<'_sess, G> for
NoValueInOnUnimplemented where G: rustc_errors::EmissionGuarantee
{
#[track_caller]
fn into_diag(self, dcx: rustc_errors::DiagCtxtHandle<'_sess>,
level: rustc_errors::Level) -> rustc_errors::Diag<'_sess, G> {
match self {
NoValueInOnUnimplemented { span: __binding_0 } => {
let mut diag =
rustc_errors::Diag::new(dcx, level,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("this attribute must have a value")));
diag.code(E0232);
diag.note(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("e.g. `#[rustc_on_unimplemented(message=\"foo\")]`")));
;
diag.span(__binding_0);
diag.span_label(__binding_0,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("expected value here")));
diag
}
}
}
}
};Diagnostic)]
524#[diag("this attribute must have a value", code = E0232)]
525#[note("e.g. `#[rustc_on_unimplemented(message=\"foo\")]`")]
526pub(crate) struct NoValueInOnUnimplemented {
527 #[primary_span]
528 #[label("expected value here")]
529 pub span: Span,
530}
531
532#[derive(const _: () =
{
impl<'_sess, G> rustc_errors::Diagnostic<'_sess, G> for
DupesNotAllowed where G: rustc_errors::EmissionGuarantee {
#[track_caller]
fn into_diag(self, dcx: rustc_errors::DiagCtxtHandle<'_sess>,
level: rustc_errors::Level) -> rustc_errors::Diag<'_sess, G> {
match self {
DupesNotAllowed => {
let mut diag =
rustc_errors::Diag::new(dcx, level,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("using multiple `rustc_on_unimplemented` (or mixing it with `diagnostic::on_unimplemented`) is not supported")));
;
diag
}
}
}
}
};Diagnostic)]
533#[diag(
534 "using multiple `rustc_on_unimplemented` (or mixing it with `diagnostic::on_unimplemented`) is not supported"
535)]
536pub(crate) struct DupesNotAllowed;