about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlexis Beingessner <a.beingessner@gmail.com>2015-06-11 17:18:46 -0700
committerAlexis Beingessner <a.beingessner@gmail.com>2015-06-11 17:18:46 -0700
commit2962b2681fd9dd4c91f27c4b061d9a2dc15ced02 (patch)
treeba6ab87d393257fe03210b12620fff499183af0a
parent5779fff5436c13369d655b76b7d81aed534776dc (diff)
downloadrust-2962b2681fd9dd4c91f27c4b061d9a2dc15ced02.tar.gz
rust-2962b2681fd9dd4c91f27c4b061d9a2dc15ced02.zip
validate stability against deprecation version
-rw-r--r--src/librustc/middle/stability.rs39
-rw-r--r--src/libsyntax/attr.rs6
-rw-r--r--src/test/compile-fail/stability-attribute-sanity.rs1
3 files changed, 43 insertions, 3 deletions
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 5d092167d5a..26efa5b4389 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -31,6 +31,7 @@ use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
 use util::ppaux::Repr;
 
 use std::mem::replace;
+use std::cmp::Ordering;
 
 /// A stability index, giving the stability level for items and methods.
 pub struct Index<'tcx> {
@@ -73,6 +74,44 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
                     }
 
                     let stab = self.tcx.intern_stability(stab);
+
+                    // Check if deprecated_since < stable_since. If it is,
+                    // this is *almost surely* an accident.
+                    let deprecated_predates_stable = match (stab.deprecated_since.as_ref(),
+                                                            stab.since.as_ref()) {
+                        (Some(dep_since), Some(stab_since)) => {
+                            // explicit version of iter::order::lt to handle parse errors properly
+                            let mut is_less = false;
+                            for (dep_v, stab_v) in dep_since.split(".").zip(stab_since.split(".")) {
+                                match (dep_v.parse::<u64>(), stab_v.parse::<u64>()) {
+                                    (Ok(dep_v), Ok(stab_v)) => match dep_v.cmp(&stab_v) {
+                                        Ordering::Less => {
+                                            is_less = true;
+                                            break;
+                                        }
+                                        Ordering::Equal => { continue; }
+                                        Ordering::Greater => { break; }
+                                    },
+                                    _ => {
+                                        self.tcx.sess.span_err(item_sp,
+                                            "Invalid stability or deprecation version found");
+                                        // act like it isn't less because the question is now
+                                        // nonsensical, and this makes us not do anything else
+                                        // interesting.
+                                        break;
+                                    }
+                                }
+                            }
+                            is_less
+                        },
+                        _ => false,
+                    };
+
+                    if deprecated_predates_stable {
+                        self.tcx.sess.span_err(item_sp,
+                            "An API can't be stabilized after it is deprecated");
+                    }
+
                     self.index.map.insert(local_def(id), Some(stab));
 
                     // Don't inherit #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 3c4c4d70343..44f84ec7594 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -397,7 +397,7 @@ fn find_stability_generic<'a,
                              -> (Option<Stability>, Vec<&'a AM>) {
 
     let mut stab: Option<Stability> = None;
-    let mut deprecated: Option<(InternedString, Option<InternedString>)> = None;
+    let mut deprecated: Option<(Option<InternedString>, Option<InternedString>)> = None;
     let mut used_attrs: Vec<&'a AM> = vec![];
 
     'outer: for attr in attrs {
@@ -484,7 +484,7 @@ fn find_stability_generic<'a,
                 diagnostic.span_err(item_sp, "multiple deprecated attributes");
             }
 
-            deprecated = Some((since.unwrap_or(intern_and_get_ident("bogus")), reason));
+            deprecated = Some((since, reason));
         }
     }
 
@@ -493,7 +493,7 @@ fn find_stability_generic<'a,
         match stab {
             Some(ref mut s) => {
                 let (since, reason) = deprecated.unwrap();
-                s.deprecated_since = Some(since);
+                s.deprecated_since = since;
                 s.reason = reason;
             }
             None => {
diff --git a/src/test/compile-fail/stability-attribute-sanity.rs b/src/test/compile-fail/stability-attribute-sanity.rs
index dcbb1880b10..f0597d57b79 100644
--- a/src/test/compile-fail/stability-attribute-sanity.rs
+++ b/src/test/compile-fail/stability-attribute-sanity.rs
@@ -88,6 +88,7 @@ fn multiple3() { } //~ ERROR multiple stability levels
 #[deprecated(since = "b")]
 #[deprecated(since = "b")]
 fn multiple4() { } //~ ERROR multiple deprecated attributes
+//~^ ERROR Invalid stability or deprecation version found
 
 #[deprecated(since = "a")]
 fn deprecated_without_unstable_or_stable() { } //~ ERROR deprecated attribute must be paired