rustc_attr_parsing/attributes/
traits.rs1use core::mem;
2
3use rustc_attr_data_structures::AttributeKind;
4use rustc_feature::{AttributeTemplate, template};
5use rustc_span::{Symbol, sym};
6
7use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
8use crate::context::{AcceptContext, Stage};
9use crate::parser::ArgParser;
10
11pub(crate) struct SkipDuringMethodDispatchParser;
12
13impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
14 const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
15 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
16 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
17
18 const TEMPLATE: AttributeTemplate = template!(List: "array, boxed_slice");
19
20 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
21 let mut array = false;
22 let mut boxed_slice = false;
23 let Some(args) = args.list() else {
24 cx.expected_list(cx.attr_span);
25 return None;
26 };
27 if args.is_empty() {
28 cx.expected_at_least_one_argument(args.span);
29 return None;
30 }
31 for arg in args.mixed() {
32 let Some(arg) = arg.meta_item() else {
33 cx.unexpected_literal(arg.span());
34 continue;
35 };
36 if let Err(span) = arg.args().no_args() {
37 cx.expected_no_args(span);
38 }
39 let path = arg.path();
40 let (key, skip): (Symbol, &mut bool) = match path.word_sym() {
41 Some(key @ sym::array) => (key, &mut array),
42 Some(key @ sym::boxed_slice) => (key, &mut boxed_slice),
43 _ => {
44 cx.expected_specific_argument(path.span(), vec!["array", "boxed_slice"]);
45 continue;
46 }
47 };
48 if mem::replace(skip, true) {
49 cx.duplicate_key(arg.span(), key);
50 }
51 }
52 Some(AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: cx.attr_span })
53 }
54}