rustc_attr_parsing/attributes/
must_use.rs

1use rustc_errors::DiagArgValue;
2use rustc_feature::{AttributeTemplate, template};
3use rustc_hir::attrs::AttributeKind;
4use rustc_span::{Symbol, sym};
5
6use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
7use crate::context::{AcceptContext, Stage};
8use crate::parser::ArgParser;
9use crate::session_diagnostics;
10
11pub(crate) struct MustUseParser;
12
13impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
14    const PATH: &[Symbol] = &[sym::must_use];
15    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
16    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
17    const TEMPLATE: AttributeTemplate = template!(
18        Word, NameValueStr: "reason",
19        "https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute"
20    );
21
22    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
23        Some(AttributeKind::MustUse {
24            span: cx.attr_span,
25            reason: match args {
26                ArgParser::NoArgs => None,
27                ArgParser::NameValue(name_value) => {
28                    let Some(value_str) = name_value.value_as_str() else {
29                        cx.expected_string_literal(
30                            name_value.value_span,
31                            Some(&name_value.value_as_lit()),
32                        );
33                        return None;
34                    };
35                    Some(value_str)
36                }
37                ArgParser::List(_) => {
38                    let suggestions =
39                        <Self as SingleAttributeParser<S>>::TEMPLATE.suggestions(false, "must_use");
40                    cx.emit_err(session_diagnostics::IllFormedAttributeInputLint {
41                        num_suggestions: suggestions.len(),
42                        suggestions: DiagArgValue::StrListSepByAnd(
43                            suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
44                        ),
45                        span: cx.attr_span,
46                    });
47                    return None;
48                }
49            },
50        })
51    }
52}