rustc_attr_parsing/attributes/
deprecation.rs
1use rustc_attr_data_structures::{AttributeKind, DeprecatedSince, Deprecation};
2use rustc_span::symbol::Ident;
3use rustc_span::{Span, Symbol, sym};
4
5use super::SingleAttributeParser;
6use super::util::parse_version;
7use crate::context::AcceptContext;
8use crate::parser::ArgParser;
9use crate::session_diagnostics;
10use crate::session_diagnostics::UnsupportedLiteralReason;
11
12pub(crate) struct DeprecationParser;
13
14fn get(
15 cx: &AcceptContext<'_>,
16 ident: Ident,
17 param_span: Span,
18 arg: &ArgParser<'_>,
19 item: &Option<Symbol>,
20) -> Option<Symbol> {
21 if item.is_some() {
22 cx.emit_err(session_diagnostics::MultipleItem {
23 span: param_span,
24 item: ident.to_string(),
25 });
26 return None;
27 }
28 if let Some(v) = arg.name_value() {
29 if let Some(value_str) = v.value_as_str() {
30 Some(value_str)
31 } else {
32 let lit = v.value_as_lit();
33 cx.emit_err(session_diagnostics::UnsupportedLiteral {
34 span: v.value_span,
35 reason: UnsupportedLiteralReason::DeprecatedString,
36 is_bytestr: lit.kind.is_bytestr(),
37 start_point_span: cx.sess().source_map().start_point(lit.span),
38 });
39 None
40 }
41 } else {
42 cx.emit_err(session_diagnostics::IncorrectMetaItem { span: param_span, suggestion: None });
44 None
45 }
46}
47
48impl SingleAttributeParser for DeprecationParser {
49 const PATH: &'static [rustc_span::Symbol] = &[sym::deprecated];
50
51 fn on_duplicate(cx: &AcceptContext<'_>, first_span: rustc_span::Span) {
52 cx.emit_err(session_diagnostics::UnusedMultiple {
54 this: cx.attr_span,
55 other: first_span,
56 name: sym::deprecated,
57 });
58 }
59
60 fn convert(cx: &AcceptContext<'_>, args: &ArgParser<'_>) -> Option<AttributeKind> {
61 let features = cx.features();
62
63 let mut since = None;
64 let mut note = None;
65 let mut suggestion = None;
66
67 let is_rustc = features.staged_api();
68
69 if let Some(value) = args.name_value()
70 && let Some(value_str) = value.value_as_str()
71 {
72 note = Some(value_str)
73 } else if let Some(list) = args.list() {
74 for param in list.mixed() {
75 let param_span = param.span();
76 let Some(param) = param.meta_item() else {
77 cx.emit_err(session_diagnostics::UnsupportedLiteral {
78 span: param_span,
79 reason: UnsupportedLiteralReason::DeprecatedKvPair,
80 is_bytestr: false,
81 start_point_span: cx.sess().source_map().start_point(param_span),
82 });
83 return None;
84 };
85
86 let (ident, arg) = param.word_or_empty();
87
88 match ident.name {
89 sym::since => {
90 since = Some(get(cx, ident, param_span, arg, &since)?);
91 }
92 sym::note => {
93 note = Some(get(cx, ident, param_span, arg, ¬e)?);
94 }
95 sym::suggestion => {
96 if !features.deprecated_suggestion() {
97 cx.emit_err(session_diagnostics::DeprecatedItemSuggestion {
98 span: param_span,
99 is_nightly: cx.sess().is_nightly_build(),
100 details: (),
101 });
102 }
103
104 suggestion = Some(get(cx, ident, param_span, arg, &suggestion)?);
105 }
106 _ => {
107 cx.emit_err(session_diagnostics::UnknownMetaItem {
108 span: param_span,
109 item: ident.to_string(),
110 expected: if features.deprecated_suggestion() {
111 &["since", "note", "suggestion"]
112 } else {
113 &["since", "note"]
114 },
115 });
116 return None;
117 }
118 }
119 }
120 }
121
122 let since = if let Some(since) = since {
123 if since.as_str() == "TBD" {
124 DeprecatedSince::Future
125 } else if !is_rustc {
126 DeprecatedSince::NonStandard(since)
127 } else if let Some(version) = parse_version(since) {
128 DeprecatedSince::RustcVersion(version)
129 } else {
130 cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
131 DeprecatedSince::Err
132 }
133 } else if is_rustc {
134 cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
135 DeprecatedSince::Err
136 } else {
137 DeprecatedSince::Unspecified
138 };
139
140 if is_rustc && note.is_none() {
141 cx.emit_err(session_diagnostics::MissingNote { span: cx.attr_span });
142 return None;
143 }
144
145 Some(AttributeKind::Deprecation {
146 deprecation: Deprecation { since, note, suggestion },
147 span: cx.attr_span,
148 })
149 }
150}