]> git.lizzy.rs Git - rust.git/commitdiff
validate stability against deprecation version
authorAlexis Beingessner <a.beingessner@gmail.com>
Fri, 12 Jun 2015 00:18:46 +0000 (17:18 -0700)
committerAlexis Beingessner <a.beingessner@gmail.com>
Fri, 12 Jun 2015 00:18:46 +0000 (17:18 -0700)
src/librustc/middle/stability.rs
src/libsyntax/attr.rs
src/test/compile-fail/stability-attribute-sanity.rs

index 5d092167d5ada08695087b3060e4ad6d6c1463c3..26efa5b4389854766959de8a89bf4178cebe98de 100644 (file)
@@ -31,6 +31,7 @@
 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 @@ fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
                     }
 
                     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")]
index 3c4c4d70343c38484b0e406f6bc55c571dad2101..44f84ec7594404376efb67c8b951ae94b5859f2e 100644 (file)
@@ -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 => {
index dcbb1880b1089da7de0a85b896226e9cb8963962..f0597d57b797363b039a0020bc60a645c113f2c7 100644 (file)
@@ -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