rustc_attr_parsing/attributes/
deprecation.rs

1//! Parsing and validation of builtin attributes
2
3use rustc_ast::attr::AttributeExt;
4use rustc_ast::{MetaItem, MetaItemInner};
5use rustc_ast_pretty::pprust;
6use rustc_attr_data_structures::{DeprecatedSince, Deprecation};
7use rustc_feature::Features;
8use rustc_session::Session;
9use rustc_span::{Span, Symbol, sym};
10
11use super::util::UnsupportedLiteralReason;
12use crate::{parse_version, session_diagnostics};
13
14/// Finds the deprecation attribute. `None` if none exists.
15pub fn find_deprecation(
16    sess: &Session,
17    features: &Features,
18    attrs: &[impl AttributeExt],
19) -> Option<(Deprecation, Span)> {
20    let mut depr: Option<(Deprecation, Span)> = None;
21    let is_rustc = features.staged_api();
22
23    'outer: for attr in attrs {
24        if !attr.has_name(sym::deprecated) {
25            continue;
26        }
27
28        let mut since = None;
29        let mut note = None;
30        let mut suggestion = None;
31
32        if attr.is_doc_comment() {
33            continue;
34        } else if attr.is_word() {
35        } else if let Some(value) = attr.value_str() {
36            note = Some(value)
37        } else if let Some(list) = attr.meta_item_list() {
38            let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
39                if item.is_some() {
40                    sess.dcx().emit_err(session_diagnostics::MultipleItem {
41                        span: meta.span,
42                        item: pprust::path_to_string(&meta.path),
43                    });
44                    return false;
45                }
46                if let Some(v) = meta.value_str() {
47                    *item = Some(v);
48                    true
49                } else {
50                    if let Some(lit) = meta.name_value_literal() {
51                        sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
52                            span: lit.span,
53                            reason: UnsupportedLiteralReason::DeprecatedString,
54                            is_bytestr: lit.kind.is_bytestr(),
55                            start_point_span: sess.source_map().start_point(lit.span),
56                        });
57                    } else {
58                        sess.dcx()
59                            .emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
60                    }
61                    false
62                }
63            };
64
65            for meta in &list {
66                match meta {
67                    MetaItemInner::MetaItem(mi) => match mi.name_or_empty() {
68                        sym::since => {
69                            if !get(mi, &mut since) {
70                                continue 'outer;
71                            }
72                        }
73                        sym::note => {
74                            if !get(mi, &mut note) {
75                                continue 'outer;
76                            }
77                        }
78                        sym::suggestion => {
79                            if !features.deprecated_suggestion() {
80                                sess.dcx().emit_err(
81                                    session_diagnostics::DeprecatedItemSuggestion {
82                                        span: mi.span,
83                                        is_nightly: sess.is_nightly_build(),
84                                        details: (),
85                                    },
86                                );
87                            }
88
89                            if !get(mi, &mut suggestion) {
90                                continue 'outer;
91                            }
92                        }
93                        _ => {
94                            sess.dcx().emit_err(session_diagnostics::UnknownMetaItem {
95                                span: meta.span(),
96                                item: pprust::path_to_string(&mi.path),
97                                expected: if features.deprecated_suggestion() {
98                                    &["since", "note", "suggestion"]
99                                } else {
100                                    &["since", "note"]
101                                },
102                            });
103                            continue 'outer;
104                        }
105                    },
106                    MetaItemInner::Lit(lit) => {
107                        sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
108                            span: lit.span,
109                            reason: UnsupportedLiteralReason::DeprecatedKvPair,
110                            is_bytestr: false,
111                            start_point_span: sess.source_map().start_point(lit.span),
112                        });
113                        continue 'outer;
114                    }
115                }
116            }
117        } else {
118            continue;
119        }
120
121        let since = if let Some(since) = since {
122            if since.as_str() == "TBD" {
123                DeprecatedSince::Future
124            } else if !is_rustc {
125                DeprecatedSince::NonStandard(since)
126            } else if let Some(version) = parse_version(since) {
127                DeprecatedSince::RustcVersion(version)
128            } else {
129                sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span() });
130                DeprecatedSince::Err
131            }
132        } else if is_rustc {
133            sess.dcx().emit_err(session_diagnostics::MissingSince { span: attr.span() });
134            DeprecatedSince::Err
135        } else {
136            DeprecatedSince::Unspecified
137        };
138
139        if is_rustc && note.is_none() {
140            sess.dcx().emit_err(session_diagnostics::MissingNote { span: attr.span() });
141            continue;
142        }
143
144        depr = Some((Deprecation { since, note, suggestion }, attr.span()));
145    }
146
147    depr
148}