rustc_attr_parsing/attributes/
confusables.rs

1use rustc_feature::template;
2use rustc_hir::attrs::AttributeKind;
3use rustc_hir::{MethodKind, Target};
4use rustc_span::{Span, Symbol, sym};
5use thin_vec::ThinVec;
6
7use super::{AcceptMapping, AttributeParser};
8use crate::context::MaybeWarn::Allow;
9use crate::context::{AllowedTargets, FinalizeContext, Stage};
10use crate::session_diagnostics;
11#[derive(Default)]
12pub(crate) struct ConfusablesParser {
13    confusables: ThinVec<Symbol>,
14    first_span: Option<Span>,
15}
16
17impl<S: Stage> AttributeParser<S> for ConfusablesParser {
18    const ATTRIBUTES: AcceptMapping<Self, S> = &[(
19        &[sym::rustc_confusables],
20        template!(List: &[r#""name1", "name2", ..."#]),
21        |this, cx, args| {
22            let Some(list) = args.list() else {
23                cx.expected_list(cx.attr_span);
24                return;
25            };
26
27            if list.is_empty() {
28                cx.emit_err(session_diagnostics::EmptyConfusables { span: cx.attr_span });
29            }
30
31            for param in list.mixed() {
32                let span = param.span();
33
34                let Some(lit) = param.lit().and_then(|i| i.value_str()) else {
35                    cx.expected_string_literal(span, param.lit());
36                    continue;
37                };
38
39                this.confusables.push(lit);
40            }
41
42            this.first_span.get_or_insert(cx.attr_span);
43        },
44    )];
45    const ALLOWED_TARGETS: AllowedTargets =
46        AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]);
47
48    fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
49        if self.confusables.is_empty() {
50            return None;
51        }
52
53        Some(AttributeKind::Confusables {
54            symbols: self.confusables,
55            first_span: self.first_span.unwrap(),
56        })
57    }
58}