rustc_attr_parsing/attributes/
traits.rs

1use 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}