summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-12-16 08:15:23 +0000
committerbors <bors@rust-lang.org>2015-12-16 08:15:23 +0000
commitac2c5ff0241bdd090af11a74566bd00f03ae8ae0 (patch)
tree780d1609c300fedd2dd9c7af17a0366d185c61aa /src/libsyntax
parent9ace0a46de9b47cfa93c4e906805455b221e2881 (diff)
parent67a978411a2009093bb40c4f1320a08d2a28b6c7 (diff)
downloadrust-ac2c5ff0241bdd090af11a74566bd00f03ae8ae0.tar.gz
rust-ac2c5ff0241bdd090af11a74566bd00f03ae8ae0.zip
Auto merge of #30206 - petrochenkov:newdepr, r=brson
Closes https://github.com/rust-lang/rust/issues/29935

The attributes `deprecated` and `rustc_deprecated` are completely independent in this implementation and it leads to some noticeable code duplication. Representing `deprecated` as
```
Stability {
    level: Stable { since: "" },
    feature: "",
    depr: Some(Deprecation),
}
```
or, contrariwise, splitting rustc_deprecation from stability makes most of the duplication go away.
I can do this refactoring, but before doing it I must be sure, that further divergence of `deprecated` and `rustc_deprecated` is certainly not a goal.

cc @llogiq
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/attr.rs91
-rw-r--r--src/libsyntax/feature_gate.rs7
2 files changed, 88 insertions, 10 deletions
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index e828d8ae248..d511ce09a36 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -398,7 +398,7 @@ pub fn cfg_matches<T: CfgDiag>(cfgs: &[P<MetaItem>],
 pub struct Stability {
     pub level: StabilityLevel,
     pub feature: InternedString,
-    pub depr: Option<Deprecation>,
+    pub rustc_depr: Option<RustcDeprecation>,
 }
 
 /// The available stability levels.
@@ -410,11 +410,17 @@ pub enum StabilityLevel {
 }
 
 #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
-pub struct Deprecation {
+pub struct RustcDeprecation {
     pub since: InternedString,
     pub reason: InternedString,
 }
 
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
+pub struct Deprecation {
+    pub since: Option<InternedString>,
+    pub note: Option<InternedString>,
+}
+
 impl StabilityLevel {
     pub fn is_unstable(&self) -> bool { if let Unstable {..} = *self { true } else { false }}
     pub fn is_stable(&self) -> bool { if let Stable {..} = *self { true } else { false }}
@@ -427,7 +433,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
     where I: Iterator<Item = &'a Attribute>
 {
     let mut stab: Option<Stability> = None;
-    let mut depr: Option<Deprecation> = None;
+    let mut rustc_depr: Option<RustcDeprecation> = None;
 
     'outer: for attr in attrs_iter {
         let tag = attr.name();
@@ -456,7 +462,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
 
             match tag {
                 "rustc_deprecated" => {
-                    if depr.is_some() {
+                    if rustc_depr.is_some() {
                         diagnostic.span_err(item_sp, "multiple rustc_deprecated attributes");
                         break
                     }
@@ -477,7 +483,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
 
                     match (since, reason) {
                         (Some(since), Some(reason)) => {
-                            depr = Some(Deprecation {
+                            rustc_depr = Some(RustcDeprecation {
                                 since: since,
                                 reason: reason,
                             })
@@ -529,7 +535,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
                                     }
                                 },
                                 feature: feature,
-                                depr: None,
+                                rustc_depr: None,
                             })
                         }
                         (None, _, _) => {
@@ -569,7 +575,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
                                     since: since,
                                 },
                                 feature: feature,
-                                depr: None,
+                                rustc_depr: None,
                             })
                         }
                         (None, _) => {
@@ -591,12 +597,12 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
     }
 
     // Merge the deprecation info into the stability info
-    if let Some(depr) = depr {
+    if let Some(rustc_depr) = rustc_depr {
         if let Some(ref mut stab) = stab {
             if let Unstable {reason: ref mut reason @ None, ..} = stab.level {
-                *reason = Some(depr.reason.clone())
+                *reason = Some(rustc_depr.reason.clone())
             }
-            stab.depr = Some(depr);
+            stab.rustc_depr = Some(rustc_depr);
         } else {
             diagnostic.span_err(item_sp, "rustc_deprecated attribute must be paired with \
                                           either stable or unstable attribute");
@@ -606,12 +612,77 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
     stab
 }
 
+fn find_deprecation_generic<'a, I>(diagnostic: &SpanHandler,
+                                 attrs_iter: I,
+                                 item_sp: Span)
+                                 -> Option<Deprecation>
+    where I: Iterator<Item = &'a Attribute>
+{
+    let mut depr: Option<Deprecation> = None;
+
+    'outer: for attr in attrs_iter {
+        if attr.name() != "deprecated" {
+            continue
+        }
+
+        mark_used(attr);
+
+        if depr.is_some() {
+            diagnostic.span_err(item_sp, "multiple deprecated attributes");
+            break
+        }
+
+        depr = if let Some(metas) = attr.meta_item_list() {
+            let get = |meta: &MetaItem, item: &mut Option<InternedString>| {
+                if item.is_some() {
+                    diagnostic.span_err(meta.span, &format!("multiple '{}' items",
+                                                             meta.name()));
+                    return false
+                }
+                if let Some(v) = meta.value_str() {
+                    *item = Some(v);
+                    true
+                } else {
+                    diagnostic.span_err(meta.span, "incorrect meta item");
+                    false
+                }
+            };
+
+            let mut since = None;
+            let mut note = None;
+            for meta in metas {
+                match &*meta.name() {
+                    "since" => if !get(meta, &mut since) { continue 'outer },
+                    "note" => if !get(meta, &mut note) { continue 'outer },
+                    _ => {
+                        diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
+                                                                meta.name()));
+                        continue 'outer
+                    }
+                }
+            }
+
+            Some(Deprecation {since: since, note: note})
+        } else {
+            Some(Deprecation{since: None, note: None})
+        }
+    }
+
+    depr
+}
+
 /// Find the first stability attribute. `None` if none exists.
 pub fn find_stability(diagnostic: &SpanHandler, attrs: &[Attribute],
                       item_sp: Span) -> Option<Stability> {
     find_stability_generic(diagnostic, attrs.iter(), item_sp)
 }
 
+/// Find the deprecation attribute. `None` if none exists.
+pub fn find_deprecation(diagnostic: &SpanHandler, attrs: &[Attribute],
+                      item_sp: Span) -> Option<Deprecation> {
+    find_deprecation_generic(diagnostic, attrs.iter(), item_sp)
+}
+
 pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P<MetaItem>]) {
     let mut set = HashSet::new();
     for meta in metas {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index c456b7dc8b9..f186aff6d36 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -230,6 +230,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
 
     // Allow attributes on expressions and non-item statements
     ("stmt_expr_attributes", "1.6.0", Some(15701), Active),
+
+    // Allows `#[deprecated]` attribute
+    ("deprecated", "1.6.0", Some(29935), Active),
 ];
 // (changing above list without updating src/doc/reference.md makes @cmr sad)
 
@@ -377,6 +380,7 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
     ("must_use", Whitelisted, Ungated),
     ("stable", Whitelisted, Ungated),
     ("unstable", Whitelisted, Ungated),
+    ("deprecated", Normal, Gated("deprecated", "`#[deprecated]` attribute is unstable")),
 
     ("rustc_paren_sugar", Normal, Gated("unboxed_closures",
                                         "unboxed_closures are still evolving")),
@@ -539,6 +543,7 @@ pub struct Features {
     pub braced_empty_structs: bool,
     pub staged_api: bool,
     pub stmt_expr_attributes: bool,
+    pub deprecated: bool,
 }
 
 impl Features {
@@ -573,6 +578,7 @@ impl Features {
             braced_empty_structs: false,
             staged_api: false,
             stmt_expr_attributes: false,
+            deprecated: false,
         }
     }
 }
@@ -1151,6 +1157,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
         braced_empty_structs: cx.has_feature("braced_empty_structs"),
         staged_api: cx.has_feature("staged_api"),
         stmt_expr_attributes: cx.has_feature("stmt_expr_attributes"),
+        deprecated: cx.has_feature("deprecated"),
     }
 }