|
| 1 | +#![allow(warnings)] |
| 2 | + |
| 3 | +use std::convert::identity; |
| 4 | + |
| 5 | +use rustc_ast::{AttrArgs, AttrStyle, Item, ItemKind, Trait, ast}; |
| 6 | +use rustc_attr_parsing::parser::{AllowExprMetavar, ArgParser}; |
| 7 | +use rustc_attr_parsing::{AttributeParser, AttributeSafety, ParsedDescription, ShouldEmit}; |
| 8 | +use rustc_expand::base::{Annotatable, ExtCtxt}; |
| 9 | +use rustc_feature::template; |
| 10 | +use rustc_hir::{AttrPath, Target}; |
| 11 | +use rustc_parse::parser::Recovery; |
| 12 | +use rustc_span::{Span, sym}; |
| 13 | + |
| 14 | +pub(crate) mod rustc_on_unimplemented { |
| 15 | + use super::*; |
| 16 | + pub(crate) fn expand(ecx: &mut ExtCtxt<'_>, attr: &ast::Attribute, item: &mut Annotatable) { |
| 17 | + let attr = attr.get_normal_item(); |
| 18 | + let span = attr.span(); |
| 19 | + let Some(args) = ArgParser::from_attr_args( |
| 20 | + &attr.args.unparsed_ref().unwrap(), |
| 21 | + &[sym::diagnostic, sym::rustc_on_unimplemented], |
| 22 | + &ecx.sess.psess, |
| 23 | + ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden }, |
| 24 | + AllowExprMetavar::No, |
| 25 | + ) else { |
| 26 | + // Lints/errors are/will be emitted by ArgParser. |
| 27 | + return; |
| 28 | + }; |
| 29 | + |
| 30 | + match item { |
| 31 | + Annotatable::Item(box Item { |
| 32 | + span: target_span, |
| 33 | + kind: ItemKind::Trait(box Trait { on_unimplemented, .. }), |
| 34 | + .. |
| 35 | + }) => { |
| 36 | + if on_unimplemented.is_some() { |
| 37 | + // FIXME(mejrs) coalescing multiple rustc_on_unimplemented attrs isn't |
| 38 | + // (and was never) supported - might be nice to have at some point |
| 39 | + ecx.dcx().span_err( |
| 40 | + span, |
| 41 | + "using multiple `#[diagnostic::rustc_on_unimplemented]` is not supported", |
| 42 | + ); |
| 43 | + } |
| 44 | + *on_unimplemented = AttributeParser::parse_single_args( |
| 45 | + ecx.sess, |
| 46 | + span, |
| 47 | + span, |
| 48 | + AttrStyle::Inner, |
| 49 | + AttrPath::from_ast(&attr.path, identity), |
| 50 | + None, |
| 51 | + AttributeSafety::Normal, |
| 52 | + ParsedDescription::Macro, |
| 53 | + *target_span, |
| 54 | + ecx.current_expansion.lint_node_id, |
| 55 | + Target::Trait, |
| 56 | + Some(ecx.ecfg.features), |
| 57 | + ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden }, |
| 58 | + &args, |
| 59 | + rustc_attr_parsing::parse_rustc_on_unimplemented, |
| 60 | + &template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), |
| 61 | + ); |
| 62 | + } |
| 63 | + _ => { |
| 64 | + ecx.dcx() |
| 65 | + .span_err(item.span(), "`#[diagnostic::rustc_on_unimplemented]` is only supported on trait definitions"); |
| 66 | + } |
| 67 | + } |
| 68 | + } |
| 69 | +} |
0 commit comments