rustc_attr_parsing/attributes/
must_use.rs1use rustc_attr_data_structures::AttributeKind;
2use rustc_errors::DiagArgValue;
3use rustc_feature::{AttributeTemplate, template};
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::KeepLast;
16 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
17 const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason");
18
19 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
20 Some(AttributeKind::MustUse {
21 span: cx.attr_span,
22 reason: match args {
23 ArgParser::NoArgs => None,
24 ArgParser::NameValue(name_value) => {
25 let Some(value_str) = name_value.value_as_str() else {
26 cx.expected_string_literal(
27 name_value.value_span,
28 Some(&name_value.value_as_lit()),
29 );
30 return None;
31 };
32 Some(value_str)
33 }
34 ArgParser::List(_) => {
35 let suggestions =
36 <Self as SingleAttributeParser<S>>::TEMPLATE.suggestions(false, "must_use");
37 cx.emit_err(session_diagnostics::MustUseIllFormedAttributeInput {
38 num_suggestions: suggestions.len(),
39 suggestions: DiagArgValue::StrListSepByAnd(
40 suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
41 ),
42 span: cx.attr_span,
43 });
44 return None;
45 }
46 },
47 })
48 }
49}