diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 5d092167d5ad..26efa5b43898 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::(), stab_v.parse::()) { + (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 3c4c4d70343c..44f84ec75944 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -397,7 +397,7 @@ fn find_stability_generic<'a, -> (Option, Vec<&'a AM>) { let mut stab: Option = None; - let mut deprecated: Option<(InternedString, Option)> = None; + let mut deprecated: Option<(Option, Option)> = 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 dcbb1880b108..f0597d57b797 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