rustc_attr_parsing/attributes/
must_use.rs1use rustc_errors::DiagArgValue;
2
3use super::prelude::*;
4use crate::session_diagnostics::IllFormedAttributeInputLint;
5
6pub(crate) struct MustUseParser;
7
8impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
9 const PATH: &[Symbol] = &[sym::must_use];
10 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
11 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
12 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
13 Allow(Target::Fn),
14 Allow(Target::Enum),
15 Allow(Target::Struct),
16 Allow(Target::Union),
17 Allow(Target::Method(MethodKind::Trait { body: false })),
18 Allow(Target::Method(MethodKind::Trait { body: true })),
19 Allow(Target::Method(MethodKind::Inherent)),
20 Allow(Target::ForeignFn),
21 Allow(Target::Trait),
25 Error(Target::WherePredicate),
26 ]);
27 const TEMPLATE: AttributeTemplate = template!(
28 Word, NameValueStr: "reason",
29 "https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute"
30 );
31
32 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
33 Some(AttributeKind::MustUse {
34 span: cx.attr_span,
35 reason: match args {
36 ArgParser::NoArgs => None,
37 ArgParser::NameValue(name_value) => {
38 let Some(value_str) = name_value.value_as_str() else {
39 cx.expected_string_literal(
40 name_value.value_span,
41 Some(&name_value.value_as_lit()),
42 );
43 return None;
44 };
45 Some(value_str)
46 }
47 ArgParser::List(_) => {
48 let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
49 .suggestions(cx.attr_style, "must_use");
50 cx.emit_err(IllFormedAttributeInputLint {
51 num_suggestions: suggestions.len(),
52 suggestions: DiagArgValue::StrListSepByAnd(
53 suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
54 ),
55 span: cx.attr_span,
56 });
57 return None;
58 }
59 },
60 })
61 }
62}