Parse rustc_deprecated as deprecated attribute

This commit is contained in:
Mark Rousskov 2020-07-20 10:11:53 -04:00
parent 05630b06fd
commit c5cc29b0e0
4 changed files with 58 additions and 48 deletions

View file

@ -124,7 +124,6 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op
/// ///
/// - `#[stable]` /// - `#[stable]`
/// - `#[unstable]` /// - `#[unstable]`
/// - `#[rustc_deprecated]`
#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic)] #[derive(HashStable_Generic)]
pub struct Stability { pub struct Stability {
@ -213,7 +212,6 @@ where
'outer: for attr in attrs_iter { 'outer: for attr in attrs_iter {
if ![ if ![
sym::rustc_deprecated,
sym::rustc_const_unstable, sym::rustc_const_unstable,
sym::rustc_const_stable, sym::rustc_const_stable,
sym::unstable, sym::unstable,
@ -299,35 +297,6 @@ where
let meta_name = meta.name_or_empty(); let meta_name = meta.name_or_empty();
match meta_name { match meta_name {
sym::rustc_deprecated => {
if rustc_depr.is_some() {
struct_span_err!(
diagnostic,
item_sp,
E0540,
"multiple rustc_deprecated attributes"
)
.emit();
continue 'outer;
}
get_meta!(since, reason, suggestion);
match (since, reason) {
(Some(since), Some(reason)) => {
rustc_depr = Some(RustcDeprecation { since, reason, suggestion })
}
(None, _) => {
handle_errors(sess, attr.span, AttrError::MissingSince);
continue;
}
_ => {
struct_span_err!(diagnostic, attr.span, E0543, "missing 'reason'")
.emit();
continue;
}
}
}
sym::rustc_const_unstable | sym::unstable => { sym::rustc_const_unstable | sym::unstable => {
if meta_name == sym::unstable && stab.is_some() { if meta_name == sym::unstable && stab.is_some() {
handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels); handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels);
@ -714,7 +683,16 @@ pub fn eval_condition(
#[derive(RustcEncodable, RustcDecodable, Clone, HashStable_Generic)] #[derive(RustcEncodable, RustcDecodable, Clone, HashStable_Generic)]
pub struct Deprecation { pub struct Deprecation {
pub since: Option<Symbol>, pub since: Option<Symbol>,
/// The note to issue a reason.
pub note: Option<Symbol>, pub note: Option<Symbol>,
/// A text snippet used to completely replace any use of the deprecated item in an expression.
///
/// This is currently unstable.
pub suggestion: Option<Symbol>,
/// Whether to treat the since attribute as being a Rust version identifier
/// (rather than an opaque string).
pub is_since_rustc_version: bool,
} }
/// Finds the deprecation attribute. `None` if none exists. /// Finds the deprecation attribute. `None` if none exists.
@ -738,7 +716,7 @@ where
let diagnostic = &sess.span_diagnostic; let diagnostic = &sess.span_diagnostic;
'outer: for attr in attrs_iter { 'outer: for attr in attrs_iter {
if !attr.check_name(sym::deprecated) { if !(attr.check_name(sym::deprecated) || attr.check_name(sym::rustc_deprecated)) {
continue; continue;
} }
@ -751,11 +729,12 @@ where
Some(meta) => meta, Some(meta) => meta,
None => continue, None => continue,
}; };
depr = match &meta.kind { let mut since = None;
MetaItemKind::Word => Some(Deprecation { since: None, note: None }), let mut note = None;
MetaItemKind::NameValue(..) => { let mut suggestion = None;
meta.value_str().map(|note| Deprecation { since: None, note: Some(note) }) match &meta.kind {
} MetaItemKind::Word => {}
MetaItemKind::NameValue(..) => note = meta.value_str(),
MetaItemKind::List(list) => { MetaItemKind::List(list) => {
let get = |meta: &MetaItem, item: &mut Option<Symbol>| { let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
if item.is_some() { if item.is_some() {
@ -789,8 +768,6 @@ where
} }
}; };
let mut since = None;
let mut note = None;
for meta in list { for meta in list {
match meta { match meta {
NestedMetaItem::MetaItem(mi) => match mi.name_or_empty() { NestedMetaItem::MetaItem(mi) => match mi.name_or_empty() {
@ -799,18 +776,32 @@ where
continue 'outer; continue 'outer;
} }
} }
sym::note => { sym::note if attr.check_name(sym::deprecated) => {
if !get(mi, &mut note) { if !get(mi, &mut note) {
continue 'outer; continue 'outer;
} }
} }
sym::reason if attr.check_name(sym::rustc_deprecated) => {
if !get(mi, &mut note) {
continue 'outer;
}
}
sym::suggestion if attr.check_name(sym::rustc_deprecated) => {
if !get(mi, &mut suggestion) {
continue 'outer;
}
}
_ => { _ => {
handle_errors( handle_errors(
sess, sess,
meta.span(), meta.span(),
AttrError::UnknownMetaItem( AttrError::UnknownMetaItem(
pprust::path_to_string(&mi.path), pprust::path_to_string(&mi.path),
&["since", "note"], if attr.check_name(sym::deprecated) {
&["since", "note"]
} else {
&["since", "reason", "suggestion"]
},
), ),
); );
continue 'outer; continue 'outer;
@ -829,10 +820,29 @@ where
} }
} }
} }
Some(Deprecation { since, note })
} }
}; }
if suggestion.is_some() && attr.check_name(sym::deprecated) {
unreachable!("only allowed on rustc_deprecated")
}
if attr.check_name(sym::rustc_deprecated) {
if since.is_none() {
handle_errors(sess, attr.span, AttrError::MissingSince);
continue;
}
if note.is_none() {
struct_span_err!(diagnostic, attr.span, E0543, "missing 'reason'").emit();
continue;
}
}
mark_used(&attr);
let is_since_rustc_version = attr.check_name(sym::rustc_deprecated);
depr = Some(Deprecation { since, note, suggestion, is_since_rustc_version });
} }
depr depr

View file

@ -588,7 +588,7 @@ E0770: include_str!("./error_codes/E0770.md"),
E0521, // borrowed data escapes outside of closure E0521, // borrowed data escapes outside of closure
E0523, E0523,
// E0526, // shuffle indices are not constant // E0526, // shuffle indices are not constant
E0540, // multiple rustc_deprecated attributes // E0540, // multiple rustc_deprecated attributes
E0542, // missing 'since' E0542, // missing 'since'
E0543, // missing 'reason' E0543, // missing 'reason'
E0544, // multiple stability levels E0544, // multiple stability levels

View file

@ -62,7 +62,7 @@ fn multiple3() { }
#[rustc_deprecated(since = "b", reason = "text")] #[rustc_deprecated(since = "b", reason = "text")]
#[rustc_const_unstable(feature = "c", issue = "none")] #[rustc_const_unstable(feature = "c", issue = "none")]
#[rustc_const_unstable(feature = "d", issue = "none")] //~ ERROR multiple stability levels #[rustc_const_unstable(feature = "d", issue = "none")] //~ ERROR multiple stability levels
pub const fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540] pub const fn multiple4() { } //~ ERROR multiple deprecated attributes
//~^ ERROR Invalid stability or deprecation version found //~^ ERROR Invalid stability or deprecation version found
#[rustc_deprecated(since = "a", reason = "text")] #[rustc_deprecated(since = "a", reason = "text")]

View file

@ -82,7 +82,7 @@ error[E0544]: multiple stability levels
LL | #[stable(feature = "a", since = "b")] LL | #[stable(feature = "a", since = "b")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0540]: multiple rustc_deprecated attributes error[E0550]: multiple deprecated attributes
--> $DIR/stability-attribute-sanity.rs:65:1 --> $DIR/stability-attribute-sanity.rs:65:1
| |
LL | pub const fn multiple4() { } LL | pub const fn multiple4() { }
@ -108,5 +108,5 @@ LL | fn deprecated_without_unstable_or_stable() { }
error: aborting due to 18 previous errors error: aborting due to 18 previous errors
Some errors have detailed explanations: E0539, E0541. Some errors have detailed explanations: E0539, E0541, E0550.
For more information about an error, try `rustc --explain E0539`. For more information about an error, try `rustc --explain E0539`.