about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2015-01-22 12:33:46 -0800
committerBrian Anderson <banderson@mozilla.com>2015-01-23 15:50:03 -0800
commit9758c488a94e77cc8a110a6783a99cf5b91326db (patch)
treeca5f2436cb4b9dc39aa7f525cf4a5fc9288d0ac7 /src/libsyntax
parentcd6d9eab5d75584edfcae4ffdef8b0836db80c1e (diff)
downloadrust-9758c488a94e77cc8a110a6783a99cf5b91326db.tar.gz
rust-9758c488a94e77cc8a110a6783a99cf5b91326db.zip
Deprecated attributes don't take 'feature' names and are paired with stable/unstable
Conflicts:
	src/libcore/atomic.rs
	src/libcore/finally.rs
	src/test/auxiliary/inherited_stability.rs
	src/test/auxiliary/lint_stability.rs
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/attr.rs100
-rw-r--r--src/libsyntax/ext/base.rs3
-rw-r--r--src/libsyntax/util/small_vector.rs3
3 files changed, 78 insertions, 28 deletions
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index ff1dc5d0c35..d63370b41f5 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -351,13 +351,15 @@ pub struct Stability {
     pub level: StabilityLevel,
     pub feature: InternedString,
     pub since: Option<InternedString>,
+    pub deprecated_since: Option<InternedString>,
+    // The reason for the current stability level. If deprecated, the
+    // reason for deprecation.
     pub reason: Option<InternedString>,
 }
 
 /// The available stability levels.
 #[derive(RustcEncodable,RustcDecodable,PartialEq,PartialOrd,Clone,Show,Copy)]
 pub enum StabilityLevel {
-    Deprecated,
     Unstable,
     Stable,
 }
@@ -368,18 +370,24 @@ impl fmt::String for StabilityLevel {
     }
 }
 
-pub fn find_stability_generic<'a,
+fn find_stability_generic<'a,
                               AM: AttrMetaMethods,
                               I: Iterator<Item=&'a AM>>
-                             (diagnostic: &SpanHandler, mut attrs: I)
-                             -> Option<(Stability, &'a AM)> {
-    for attr in attrs {
-        let level = match attr.name().get() {
-            "deprecated" => Deprecated,
-            "unstable" => Unstable,
-            "stable" => Stable,
-            _ => continue // not a stability level
-        };
+                             (diagnostic: &SpanHandler, mut attrs: I, item_sp: Span)
+                             -> (Option<Stability>, Vec<&'a AM>) {
+
+    let mut stab: Option<Stability> = None;
+    let mut deprecated: Option<(InternedString, Option<InternedString>)> = None;
+    let mut used_attrs: Vec<&'a AM> = vec![];
+
+    'outer: for attr in attrs {
+        let tag = attr.name();
+        let tag = tag.get();
+        if tag != "deprecated" && tag != "unstable" && tag != "stable" {
+            continue // not a stability level
+        }
+
+        used_attrs.push(attr);
 
         let (feature, since, reason) = match attr.meta_item_list() {
             Some(metas) => {
@@ -392,6 +400,7 @@ pub fn find_stability_generic<'a,
                             Some(v) => feature = Some(v),
                             None => {
                                 diagnostic.span_err(meta.span, "incorrect meta item");
+                                continue 'outer;
                             }
                         }
                     }
@@ -400,6 +409,7 @@ pub fn find_stability_generic<'a,
                             Some(v) => since = Some(v),
                             None => {
                                 diagnostic.span_err(meta.span, "incorrect meta item");
+                                continue 'outer;
                             }
                         }
                     }
@@ -408,6 +418,7 @@ pub fn find_stability_generic<'a,
                             Some(v) => reason = Some(v),
                             None => {
                                 diagnostic.span_err(meta.span, "incorrect meta item");
+                                continue 'outer;
                             }
                         }
                     }
@@ -416,34 +427,71 @@ pub fn find_stability_generic<'a,
             }
             None => {
                 diagnostic.span_err(attr.span(), "incorrect stability attribute type");
-                (None, None, None)
+                continue
             }
         };
 
-        if feature == None {
+        // Deprecated tags don't require feature names
+        if feature == None && tag != "deprecated" {
             diagnostic.span_err(attr.span(), "missing 'feature'");
         }
 
-        if since == None && level != Unstable {
+        // Unstable tags don't require a version
+        if since == None && tag != "unstable" {
             diagnostic.span_err(attr.span(), "missing 'since'");
         }
 
-        return Some((Stability {
-            level: level,
-            feature: feature.unwrap_or(intern_and_get_ident("bogus")),
-            since: since,
-            reason: reason,
-        }, attr));
+        if tag == "unstable" || tag == "stable" {
+            if stab.is_some() {
+                diagnostic.span_err(item_sp, "multiple stability levels");
+            }
+
+            let level = match tag {
+                "unstable" => Unstable,
+                "stable" => Stable,
+                _ => unreachable!()
+            };
+
+            stab = Some(Stability {
+                level: level,
+                feature: feature.unwrap_or(intern_and_get_ident("bogus")),
+                since: since,
+                deprecated_since: None,
+                reason: reason
+            });
+        } else { // "deprecated"
+            if deprecated.is_some() {
+                diagnostic.span_err(item_sp, "multiple deprecated attributes");
+            }
+
+            deprecated = Some((since.unwrap_or(intern_and_get_ident("bogus")), reason));
+        }
+    }
+
+    // Merge the deprecation info into the stability info
+    if deprecated.is_some() {
+        match stab {
+            Some(ref mut s) => {
+                let (since, reason) = deprecated.unwrap();
+                s.deprecated_since = Some(since);
+                s.reason = reason;
+            }
+            None => {
+                diagnostic.span_err(item_sp, "deprecated attribute must be paired with \
+                                              either stable or unstable attribute");
+            }
+        }
     }
-    None
+
+    (stab, used_attrs)
 }
 
 /// Find the first stability attribute. `None` if none exists.
-pub fn find_stability(diagnostic: &SpanHandler, attrs: &[Attribute]) -> Option<Stability> {
-    find_stability_generic(diagnostic, attrs.iter()).map(|(s, attr)| {
-        mark_used(attr);
-        s
-    })
+pub fn find_stability(diagnostic: &SpanHandler, attrs: &[Attribute],
+                      item_sp: Span) -> Option<Stability> {
+    let (s, used) = find_stability_generic(diagnostic, attrs.iter(), item_sp);
+    for used in used.into_iter() { mark_used(used) }
+    return s;
 }
 
 pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P<MetaItem>]) {
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index cd04332b47f..bca7131fdb7 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -568,7 +568,8 @@ impl<'a> ExtCtxt<'a> {
         }
     }
 
-    #[deprecated(feature = "oldstuff", since = "1.0.0",
+    #[unstable(feature = "rustc_private")]
+    #[deprecated(since = "1.0.0",
                  reason = "Replaced with `expander().fold_expr()`")]
     pub fn expand_expr(&mut self, e: P<ast::Expr>) -> P<ast::Expr> {
         self.expander().fold_expr(e)
diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs
index 342fed1653d..22f2fb36fc8 100644
--- a/src/libsyntax/util/small_vector.rs
+++ b/src/libsyntax/util/small_vector.rs
@@ -112,7 +112,8 @@ impl<T> SmallVector<T> {
     }
 
     /// Deprecated: use `into_iter`.
-    #[deprecated(feature = "oldstuff", since = "1.0.0", reason = "use into_iter")]
+    #[unstable(feature = "rustc_private")]
+    #[deprecated(since = "1.0.0", reason = "use into_iter")]
     pub fn move_iter(self) -> IntoIter<T> {
         self.into_iter()
     }