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