From c5cc29b0e0bb8238955691dc0cc324050653cbeb Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 20 Jul 2020 10:11:53 -0400 Subject: [PATCH] Parse rustc_deprecated as deprecated attribute --- src/librustc_attr/builtin.rs | 98 ++++++++++--------- src/librustc_error_codes/error_codes.rs | 2 +- .../stability-attribute-sanity.rs | 2 +- .../stability-attribute-sanity.stderr | 4 +- 4 files changed, 58 insertions(+), 48 deletions(-) diff --git a/src/librustc_attr/builtin.rs b/src/librustc_attr/builtin.rs index 0606fac2fe7..16d776593ac 100644 --- a/src/librustc_attr/builtin.rs +++ b/src/librustc_attr/builtin.rs @@ -124,7 +124,6 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op /// /// - `#[stable]` /// - `#[unstable]` -/// - `#[rustc_deprecated]` #[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(HashStable_Generic)] pub struct Stability { @@ -213,7 +212,6 @@ where 'outer: for attr in attrs_iter { if ![ - sym::rustc_deprecated, sym::rustc_const_unstable, sym::rustc_const_stable, sym::unstable, @@ -299,35 +297,6 @@ where let meta_name = meta.name_or_empty(); 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 => { if meta_name == sym::unstable && stab.is_some() { handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels); @@ -714,7 +683,16 @@ pub fn eval_condition( #[derive(RustcEncodable, RustcDecodable, Clone, HashStable_Generic)] pub struct Deprecation { pub since: Option, + /// The note to issue a reason. pub note: Option, + /// A text snippet used to completely replace any use of the deprecated item in an expression. + /// + /// This is currently unstable. + pub suggestion: Option, + + /// 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. @@ -738,7 +716,7 @@ where let diagnostic = &sess.span_diagnostic; '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; } @@ -751,11 +729,12 @@ where Some(meta) => meta, None => continue, }; - depr = match &meta.kind { - MetaItemKind::Word => Some(Deprecation { since: None, note: None }), - MetaItemKind::NameValue(..) => { - meta.value_str().map(|note| Deprecation { since: None, note: Some(note) }) - } + let mut since = None; + let mut note = None; + let mut suggestion = None; + match &meta.kind { + MetaItemKind::Word => {} + MetaItemKind::NameValue(..) => note = meta.value_str(), MetaItemKind::List(list) => { let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { @@ -789,8 +768,6 @@ where } }; - let mut since = None; - let mut note = None; for meta in list { match meta { NestedMetaItem::MetaItem(mi) => match mi.name_or_empty() { @@ -799,18 +776,32 @@ where continue 'outer; } } - sym::note => { + sym::note if attr.check_name(sym::deprecated) => { if !get(mi, &mut note) { 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( sess, meta.span(), AttrError::UnknownMetaItem( pprust::path_to_string(&mi.path), - &["since", "note"], + if attr.check_name(sym::deprecated) { + &["since", "note"] + } else { + &["since", "reason", "suggestion"] + }, ), ); 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 diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index bbbd8359f01..99f4fb5c12c 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -588,7 +588,7 @@ E0770: include_str!("./error_codes/E0770.md"), E0521, // borrowed data escapes outside of closure E0523, // E0526, // shuffle indices are not constant - E0540, // multiple rustc_deprecated attributes +// E0540, // multiple rustc_deprecated attributes E0542, // missing 'since' E0543, // missing 'reason' E0544, // multiple stability levels diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity.rs b/src/test/ui/stability-attribute/stability-attribute-sanity.rs index 5db924642e5..80d7ae6dc63 100644 --- a/src/test/ui/stability-attribute/stability-attribute-sanity.rs +++ b/src/test/ui/stability-attribute/stability-attribute-sanity.rs @@ -62,7 +62,7 @@ fn multiple3() { } #[rustc_deprecated(since = "b", reason = "text")] #[rustc_const_unstable(feature = "c", issue = "none")] #[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 #[rustc_deprecated(since = "a", reason = "text")] diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr index 3c5da3f1440..134c657c620 100644 --- a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr +++ b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr @@ -82,7 +82,7 @@ error[E0544]: multiple stability levels LL | #[stable(feature = "a", since = "b")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0540]: multiple rustc_deprecated attributes +error[E0550]: multiple deprecated attributes --> $DIR/stability-attribute-sanity.rs:65:1 | LL | pub const fn multiple4() { } @@ -108,5 +108,5 @@ LL | fn deprecated_without_unstable_or_stable() { } 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`.