1use std::ops::Range;
2
3use rustc_errors::E0232;
4use rustc_hir::AttrPath;
5use rustc_hir::attrs::diagnostic::{
6 Directive, Filter, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg, Name,
7 NameValue, Piece, Predicate,
8};
9use rustc_macros::Diagnostic;
10use rustc_parse_format::{
11 Argument, FormatSpec, ParseError, ParseMode, Parser, Piece as RpfPiece, Position,
12};
13use rustc_session::lint::builtin::{
14 MALFORMED_DIAGNOSTIC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
15};
16use rustc_span::{Ident, InnerSpan, Span, Symbol, kw, sym};
17use thin_vec::{ThinVec, thin_vec};
18
19use crate::context::AcceptContext;
20use crate::errors::{
21 FormatWarning, IgnoredDiagnosticOption, MalFormedDiagnosticAttributeLint,
22 MissingOptionsForDiagnosticAttribute, NonMetaItemDiagnosticAttribute, WrappedParserError,
23};
24use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser};
25
26pub(crate) mod do_not_recommend;
27pub(crate) mod on_const;
28pub(crate) mod on_move;
29pub(crate) mod on_unimplemented;
30pub(crate) mod on_unknown;
31pub(crate) mod on_unmatch_args;
32
33#[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)]
34pub(crate) enum Mode {
35 RustcOnUnimplemented,
37 DiagnosticOnUnimplemented,
39 DiagnosticOnConst,
41 DiagnosticOnMove,
43 DiagnosticOnUnknown,
45 DiagnosticOnUnmatchArgs,
47}
48
49impl Mode {
50 fn as_str(&self) -> &'static str {
51 match self {
52 Self::RustcOnUnimplemented => "rustc_on_unimplemented",
53 Self::DiagnosticOnUnimplemented => "diagnostic::on_unimplemented",
54 Self::DiagnosticOnConst => "diagnostic::on_const",
55 Self::DiagnosticOnMove => "diagnostic::on_move",
56 Self::DiagnosticOnUnknown => "diagnostic::on_unknown",
57 Self::DiagnosticOnUnmatchArgs => "diagnostic::on_unmatch_args",
58 }
59 }
60
61 fn expected_options(&self) -> &'static str {
62 const DEFAULT: &str =
63 "at least one of the `message`, `note` and `label` options are expected";
64 match self {
65 Self::RustcOnUnimplemented => {
66 "see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented>"
67 }
68 Self::DiagnosticOnUnimplemented => DEFAULT,
69 Self::DiagnosticOnConst => DEFAULT,
70 Self::DiagnosticOnMove => DEFAULT,
71 Self::DiagnosticOnUnknown => DEFAULT,
72 Self::DiagnosticOnUnmatchArgs => DEFAULT,
73 }
74 }
75
76 fn allowed_options(&self) -> &'static str {
77 const DEFAULT: &str = "only `message`, `note` and `label` are allowed as options";
78 match self {
79 Self::RustcOnUnimplemented => {
80 "see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented>"
81 }
82 Self::DiagnosticOnUnimplemented => DEFAULT,
83 Self::DiagnosticOnConst => DEFAULT,
84 Self::DiagnosticOnMove => DEFAULT,
85 Self::DiagnosticOnUnknown => DEFAULT,
86 Self::DiagnosticOnUnmatchArgs => DEFAULT,
87 }
88 }
89
90 fn allowed_format_arguments(&self) -> &'static str {
91 match self {
92 Self::RustcOnUnimplemented => {
93 "see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented> for allowed format arguments"
94 }
95 Self::DiagnosticOnUnimplemented => {
96 "only `Self` and generics of the trait are allowed as a format argument"
97 }
98 Self::DiagnosticOnConst => {
99 "only `Self` and generics of the implementation are allowed as a format argument"
100 }
101 Self::DiagnosticOnMove => {
102 "only `This`, `Self` and generics of the type are allowed as a format argument"
103 }
104 Self::DiagnosticOnUnknown => {
105 "only `This` is allowed as a format argument, referring to the failed import"
106 }
107 Self::DiagnosticOnUnmatchArgs => {
108 "only `This` is allowed as a format argument, referring to the macro's name"
109 }
110 }
111 }
112}
113
114fn merge_directives(
115 cx: &mut AcceptContext<'_, '_>,
116 first: &mut Option<(Span, Directive)>,
117 later: (Span, Directive),
118) {
119 if let Some((_, first)) = first {
120 if first.is_rustc_attr || later.1.is_rustc_attr {
121 cx.emit_err(DupesNotAllowed);
122 }
123
124 merge(cx, &mut first.message, later.1.message, sym::message);
125 merge(cx, &mut first.label, later.1.label, sym::label);
126 first.notes.extend(later.1.notes);
127 } else {
128 *first = Some(later);
129 }
130}
131
132fn merge<T>(
133 cx: &mut AcceptContext<'_, '_>,
134 first: &mut Option<(Span, T)>,
135 later: Option<(Span, T)>,
136 option_name: Symbol,
137) {
138 match (first, later) {
139 (Some(_) | None, None) => {}
140 (Some((first_span, _)), Some((later_span, _))) => {
141 let first_span = *first_span;
142 cx.emit_lint(
143 MALFORMED_DIAGNOSTIC_ATTRIBUTES,
144 IgnoredDiagnosticOption { first_span, later_span, option_name },
145 later_span,
146 );
147 }
148 (first @ None, Some(later)) => {
149 first.get_or_insert(later);
150 }
151 }
152}
153
154fn parse_list<'p>(
155 cx: &mut AcceptContext<'_, '_>,
156 args: &'p ArgParser,
157 mode: Mode,
158) -> Option<&'p MetaItemListParser> {
159 let span = cx.attr_span;
160 match args {
161 ArgParser::List(items) if items.len() != 0 => return Some(items),
162 ArgParser::List(list) => {
163 cx.emit_lint(
167 MALFORMED_DIAGNOSTIC_ATTRIBUTES,
168 NonMetaItemDiagnosticAttribute,
169 list.span,
170 );
171 }
172 ArgParser::NoArgs => {
173 cx.emit_lint(
174 MALFORMED_DIAGNOSTIC_ATTRIBUTES,
175 MissingOptionsForDiagnosticAttribute {
176 attribute: mode.as_str(),
177 options: mode.expected_options(),
178 },
179 span,
180 );
181 }
182 ArgParser::NameValue(_) => {
183 cx.emit_lint(
184 MALFORMED_DIAGNOSTIC_ATTRIBUTES,
185 MalFormedDiagnosticAttributeLint {
186 attribute: mode.as_str(),
187 options: mode.allowed_options(),
188 span,
189 },
190 span,
191 );
192 }
193 }
194 None
195}
196
197fn parse_directive_items<'p>(
198 cx: &mut AcceptContext<'_, '_>,
199 mode: Mode,
200 items: impl Iterator<Item = &'p MetaItemOrLitParser>,
201 is_root: bool,
202) -> Option<Directive> {
203 let mut message: Option<(Span, _)> = None;
204 let mut label: Option<(Span, _)> = None;
205 let mut notes = ThinVec::new();
206 let mut parent_label = None;
207 let mut filters = ThinVec::new();
208
209 for item in items {
210 let span = item.span();
211
212 macro malformed() {{
213 cx.emit_lint(
214 MALFORMED_DIAGNOSTIC_ATTRIBUTES,
215 MalFormedDiagnosticAttributeLint {
216 attribute: mode.as_str(),
217 options: mode.allowed_options(),
218 span,
219 },
220 span,
221 );
222 continue;
223 }}
224
225 macro or_malformed($($code:tt)*) {{
226 let Some(ret) = (
227 try {
228 $($code)*
229 }
230 ) else {
231 malformed!()
232 };
233 ret
234 }}
235
236 macro duplicate($name: ident, $($first_span:tt)*) {{
237 let first_span = $($first_span)*;
238 cx.emit_lint(
239 MALFORMED_DIAGNOSTIC_ATTRIBUTES,
240 IgnoredDiagnosticOption {
241 first_span,
242 later_span: span,
243 option_name: $name,
244 },
245 span,
246 );
247 }}
248
249 let item: &MetaItemParser = {
let Some(ret) =
(try {
item.meta_item()?
}) else {
{
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MalFormedDiagnosticAttributeLint {
attribute: mode.as_str(),
options: mode.allowed_options(),
span,
}, span);
continue;
}
};
ret
}or_malformed!(item.meta_item()?);
250 let name = {
let Some(ret) =
(try {
item.ident()?
}) else {
{
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MalFormedDiagnosticAttributeLint {
attribute: mode.as_str(),
options: mode.allowed_options(),
span,
}, span);
continue;
}
};
ret
}or_malformed!(item.ident()?).name;
251
252 let value: Option<Ident> = match item.args().as_name_value() {
260 Some(nv) => Some({
let Some(ret) =
(try {
nv.value_as_ident()?
}) else {
{
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MalFormedDiagnosticAttributeLint {
attribute: mode.as_str(),
options: mode.allowed_options(),
span,
}, span);
continue;
}
};
ret
}or_malformed!(nv.value_as_ident()?)),
261 None => None,
262 };
263
264 let mut parse_format = |input: Ident| {
265 let snippet = cx.sess.source_map().span_to_snippet(input.span).ok();
266 let is_snippet = snippet.is_some();
267 match parse_format_string(input.name, snippet, input.span, mode) {
268 Ok((f, warnings)) => {
269 for warning in warnings {
270 let (FormatWarning::InvalidSpecifier { span }
271 | FormatWarning::PositionalArgument { span }
272 | FormatWarning::IndexedArgument { span }
273 | FormatWarning::DisallowedPlaceholder { span, .. }) = warning;
274 cx.emit_lint(MALFORMED_DIAGNOSTIC_FORMAT_LITERALS, warning, span);
275 }
276
277 f
278 }
279 Err(e) => {
280 cx.emit_lint(
281 MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
282 WrappedParserError {
283 description: e.description,
284 label: e.label,
285 span: slice_span(input.span, e.span.clone(), is_snippet),
286 },
287 input.span,
288 );
289 FormatString {
291 input: input.name,
292 span: input.span,
293 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)],
294 }
295 }
296 }
297 };
298 match (mode, name) {
299 (_, sym::message) => {
300 let value = {
let Some(ret) =
(try {
value?
}) else {
{
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MalFormedDiagnosticAttributeLint {
attribute: mode.as_str(),
options: mode.allowed_options(),
span,
}, span);
continue;
}
};
ret
}or_malformed!(value?);
301 if let Some(message) = &message {
302 {
let first_span = message.0;
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
IgnoredDiagnosticOption {
first_span,
later_span: span,
option_name: name,
}, span);
}duplicate!(name, message.0)
303 } else {
304 message = Some((item.span(), parse_format(value)));
305 }
306 }
307 (_, sym::label) => {
308 let value = {
let Some(ret) =
(try {
value?
}) else {
{
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MalFormedDiagnosticAttributeLint {
attribute: mode.as_str(),
options: mode.allowed_options(),
span,
}, span);
continue;
}
};
ret
}or_malformed!(value?);
309 if let Some(label) = &label {
310 {
let first_span = label.0;
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
IgnoredDiagnosticOption {
first_span,
later_span: span,
option_name: name,
}, span);
}duplicate!(name, label.0)
311 } else {
312 label = Some((item.span(), parse_format(value)));
313 }
314 }
315 (_, sym::note) => {
316 let value = {
let Some(ret) =
(try {
value?
}) else {
{
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MalFormedDiagnosticAttributeLint {
attribute: mode.as_str(),
options: mode.allowed_options(),
span,
}, span);
continue;
}
};
ret
}or_malformed!(value?);
317 notes.push(parse_format(value))
318 }
319 (Mode::RustcOnUnimplemented, sym::parent_label) => {
320 let value = {
let Some(ret) =
(try {
value?
}) else {
{
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MalFormedDiagnosticAttributeLint {
attribute: mode.as_str(),
options: mode.allowed_options(),
span,
}, span);
continue;
}
};
ret
}or_malformed!(value?);
321 if parent_label.is_none() {
322 parent_label = Some(parse_format(value));
323 } else {
324 {
let first_span = span;
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
IgnoredDiagnosticOption {
first_span,
later_span: span,
option_name: name,
}, span);
}duplicate!(name, span)
325 }
326 }
327 (Mode::RustcOnUnimplemented, sym::on) => {
328 if is_root {
329 let items = {
let Some(ret) =
(try {
item.args().as_list()?
}) else {
{
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MalFormedDiagnosticAttributeLint {
attribute: mode.as_str(),
options: mode.allowed_options(),
span,
}, span);
continue;
}
};
ret
}or_malformed!(item.args().as_list()?);
330 let mut iter = items.mixed();
331 let filter: &MetaItemOrLitParser = match iter.next() {
332 Some(c) => c,
333 None => {
334 cx.emit_err(InvalidOnClause::Empty { span });
335 continue;
336 }
337 };
338
339 let filter = parse_filter(filter);
340
341 if items.len() < 2 {
342 {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MalFormedDiagnosticAttributeLint {
attribute: mode.as_str(),
options: mode.allowed_options(),
span,
}, span);
continue;
};malformed!();
345 }
346
347 match filter {
348 Ok(filter) => {
349 let directive =
350 {
let Some(ret) =
(try {
parse_directive_items(cx, mode, iter, false)?
}) else {
{
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MalFormedDiagnosticAttributeLint {
attribute: mode.as_str(),
options: mode.allowed_options(),
span,
}, span);
continue;
}
};
ret
}or_malformed!(parse_directive_items(cx, mode, iter, false)?);
351 filters.push((filter, directive));
352 }
353 Err(e) => {
354 cx.emit_err(e);
355 }
356 }
357 } else {
358 {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MalFormedDiagnosticAttributeLint {
attribute: mode.as_str(),
options: mode.allowed_options(),
span,
}, span);
continue;
};malformed!();
359 }
360 }
361
362 _other => {
363 {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MalFormedDiagnosticAttributeLint {
attribute: mode.as_str(),
options: mode.allowed_options(),
span,
}, span);
continue;
};malformed!();
364 }
365 }
366 }
367
368 Some(Directive {
369 is_rustc_attr: #[allow(non_exhaustive_omitted_patterns)] match mode {
Mode::RustcOnUnimplemented => true,
_ => false,
}matches!(mode, Mode::RustcOnUnimplemented),
370 filters,
371 message,
372 label,
373 notes,
374 parent_label,
375 })
376}
377
378pub(crate) fn parse_format_string(
379 input: Symbol,
380 snippet: Option<String>,
381 span: Span,
382 mode: Mode,
383) -> Result<(FormatString, Vec<FormatWarning>), ParseError> {
384 let s = input.as_str();
385 let mut parser = Parser::new(s, None, snippet, false, ParseMode::Diagnostic);
386 let pieces: Vec<_> = parser.by_ref().collect();
387
388 if let Some(err) = parser.errors.into_iter().next() {
389 return Err(err);
390 }
391 let mut warnings = Vec::new();
392
393 let pieces = pieces
394 .into_iter()
395 .map(|piece| match piece {
396 RpfPiece::Lit(lit) => Piece::Lit(Symbol::intern(lit)),
397 RpfPiece::NextArgument(arg) => {
398 Piece::Arg(parse_arg(&arg, mode, &mut warnings, span, parser.is_source_literal))
399 }
400 })
401 .collect();
402
403 Ok((FormatString { input, pieces, span }, warnings))
404}
405
406fn parse_arg(
407 arg: &Argument<'_>,
408 mode: Mode,
409 warnings: &mut Vec<FormatWarning>,
410 input_span: Span,
411 is_source_literal: bool,
412) -> FormatArg {
413 let span = slice_span(input_span, arg.position_span.clone(), is_source_literal);
414
415 let mut check_format = true;
416
417 let ret = match arg.position {
418 Position::ArgumentNamed(name) => match (mode, Symbol::intern(name)) {
420 (Mode::RustcOnUnimplemented, sym::ItemContext) => FormatArg::ItemContext,
421
422 (Mode::RustcOnUnimplemented, sym::This) => match arg.format.ty {
424 "resolved" => {
425 check_format = false;
426 FormatArg::ThisResolved
427 }
428 "path" => {
429 check_format = false;
430 FormatArg::ThisPath
431 }
432 _ => FormatArg::This,
433 },
434
435 (
441 Mode::DiagnosticOnUnknown | Mode::DiagnosticOnMove | Mode::DiagnosticOnUnmatchArgs,
442 sym::This,
443 ) => FormatArg::This,
444
445 (
451 Mode::RustcOnUnimplemented
452 | Mode::DiagnosticOnUnimplemented
453 | Mode::DiagnosticOnMove
454 | Mode::DiagnosticOnConst,
455 kw::SelfUpper,
456 ) => FormatArg::SelfUpper,
457
458 (
464 Mode::RustcOnUnimplemented
465 | Mode::DiagnosticOnUnimplemented
466 | Mode::DiagnosticOnMove
467 | Mode::DiagnosticOnConst,
468 generic_param,
469 ) => FormatArg::GenericParam { generic_param, span },
470
471 (Mode::DiagnosticOnUnknown | Mode::DiagnosticOnUnmatchArgs, as_is) => {
473 warnings.push(FormatWarning::DisallowedPlaceholder {
474 span,
475 attr: mode.as_str(),
476 allowed: mode.allowed_format_arguments(),
477 });
478 FormatArg::AsIs(Symbol::intern(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}}}", as_is))
})format!("{{{as_is}}}")))
479 }
480 },
481
482 Position::ArgumentIs(idx) => {
484 warnings.push(FormatWarning::IndexedArgument { span });
485 FormatArg::AsIs(Symbol::intern(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}}}", idx))
})format!("{{{idx}}}")))
486 }
487 Position::ArgumentImplicitlyIs(_) => {
488 warnings.push(FormatWarning::PositionalArgument { span });
489 FormatArg::AsIs(sym::empty_braces)
490 }
491 };
492 if check_format {
493 warn_on_format_spec(&arg.format, warnings, input_span, is_source_literal);
494 }
495 ret
496}
497
498fn warn_on_format_spec(
501 spec: &FormatSpec<'_>,
502 warnings: &mut Vec<FormatWarning>,
503 input_span: Span,
504 is_source_literal: bool,
505) {
506 if let Some(ty_span) = &spec.ty_span {
507 let span = slice_span(input_span, ty_span.clone(), is_source_literal);
508 warnings.push(FormatWarning::InvalidSpecifier { span })
509 }
510}
511
512fn slice_span(input: Span, Range { start, end }: Range<usize>, is_source_literal: bool) -> Span {
513 if is_source_literal { input.from_inner(InnerSpan { start, end }) } else { input }
514}
515
516pub(crate) fn parse_filter(input: &MetaItemOrLitParser) -> Result<Filter, InvalidOnClause> {
517 let span = input.span();
518 let pred = parse_predicate(input)?;
519 Ok(Filter { span, pred })
520}
521
522fn parse_predicate(input: &MetaItemOrLitParser) -> Result<Predicate, InvalidOnClause> {
523 let Some(meta_item) = input.meta_item() else {
524 return Err(InvalidOnClause::UnsupportedLiteral { span: input.span() });
525 };
526
527 let Some(predicate) = meta_item.ident() else {
528 return Err(InvalidOnClause::ExpectedIdentifier {
529 span: meta_item.path().span(),
530 path: meta_item.path().get_attribute_path(),
531 });
532 };
533
534 match meta_item.args() {
535 ArgParser::List(mis) => match predicate.name {
536 sym::any => Ok(Predicate::Any(parse_predicate_sequence(mis)?)),
537 sym::all => Ok(Predicate::All(parse_predicate_sequence(mis)?)),
538 sym::not => {
539 if let Some(single) = mis.as_single() {
540 Ok(Predicate::Not(Box::new(parse_predicate(single)?)))
541 } else {
542 Err(InvalidOnClause::ExpectedOnePredInNot { span: mis.span })
543 }
544 }
545 invalid_pred => {
546 Err(InvalidOnClause::InvalidPredicate { span: predicate.span, invalid_pred })
547 }
548 },
549 ArgParser::NameValue(p) => {
550 let Some(value) = p.value_as_ident() else {
551 return Err(InvalidOnClause::UnsupportedLiteral { span: p.args_span() });
552 };
553 let name = parse_name(predicate.name);
554 let value = parse_filter_format(value.name);
555 let kv = NameValue { name, value };
556 Ok(Predicate::Match(kv))
557 }
558 ArgParser::NoArgs => {
559 let flag = parse_flag(predicate)?;
560 Ok(Predicate::Flag(flag))
561 }
562 }
563}
564
565fn parse_predicate_sequence(
566 sequence: &MetaItemListParser,
567) -> Result<ThinVec<Predicate>, InvalidOnClause> {
568 sequence.mixed().map(parse_predicate).collect()
569}
570
571fn parse_flag(Ident { name, span }: Ident) -> Result<Flag, InvalidOnClause> {
572 match name {
573 sym::crate_local => Ok(Flag::CrateLocal),
574 sym::direct => Ok(Flag::Direct),
575 sym::from_desugaring => Ok(Flag::FromDesugaring),
576 invalid_flag => Err(InvalidOnClause::InvalidFlag { invalid_flag, span }),
577 }
578}
579
580fn parse_name(name: Symbol) -> Name {
581 match name {
582 kw::SelfUpper => Name::SelfUpper,
583 sym::from_desugaring => Name::FromDesugaring,
584 sym::cause => Name::Cause,
585 generic => Name::GenericArg(generic),
586 }
587}
588
589fn parse_filter_format(input: Symbol) -> FilterFormatString {
590 let pieces = Parser::new(input.as_str(), None, None, false, ParseMode::Diagnostic)
591 .map(|p| match p {
592 RpfPiece::Lit(s) => LitOrArg::Lit(Symbol::intern(s)),
593 RpfPiece::NextArgument(a) => match a.position {
595 Position::ArgumentNamed(
603 arg @ ("integer" | "integral" | "float" | "union" | "enum" | "struct"),
604 ) => LitOrArg::Lit(Symbol::intern(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}}}", arg))
})format!("{{{arg}}}"))),
605
606 Position::ArgumentNamed(arg) => LitOrArg::Arg(Symbol::intern(arg)),
607 Position::ArgumentImplicitlyIs(_) => LitOrArg::Lit(sym::empty_braces),
608 Position::ArgumentIs(idx) => LitOrArg::Lit(Symbol::intern(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}}}", idx))
})format!("{{{idx}}}"))),
609 },
610 })
611 .collect();
612 FilterFormatString { pieces }
613}
614
615#[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)]
616pub(crate) enum InvalidOnClause {
617 #[diag("empty `on`-clause in `#[rustc_on_unimplemented]`", code = E0232)]
618 Empty {
619 #[primary_span]
620 #[label("empty `on`-clause here")]
621 span: Span,
622 },
623 #[diag("expected a single predicate in `not(..)`", code = E0232)]
624 ExpectedOnePredInNot {
625 #[primary_span]
626 #[label("unexpected quantity of predicates here")]
627 span: Span,
628 },
629 #[diag("literals inside `on`-clauses are not supported", code = E0232)]
630 UnsupportedLiteral {
631 #[primary_span]
632 #[label("unexpected literal here")]
633 span: Span,
634 },
635 #[diag("expected an identifier inside this `on`-clause", code = E0232)]
636 ExpectedIdentifier {
637 #[primary_span]
638 #[label("expected an identifier here, not `{$path}`")]
639 span: Span,
640 path: AttrPath,
641 },
642 #[diag("this predicate is invalid", code = E0232)]
643 InvalidPredicate {
644 #[primary_span]
645 #[label("expected one of `any`, `all` or `not` here, not `{$invalid_pred}`")]
646 span: Span,
647 invalid_pred: Symbol,
648 },
649 #[diag("invalid flag in `on`-clause", code = E0232)]
650 InvalidFlag {
651 #[primary_span]
652 #[label(
653 "expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}`"
654 )]
655 span: Span,
656 invalid_flag: Symbol,
657 },
658}
659
660#[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)]
661#[diag(
662 "using multiple `rustc_on_unimplemented` (or mixing it with `diagnostic::on_unimplemented`) is not supported"
663)]
664pub(crate) struct DupesNotAllowed;