Skip to content

Commit 2962b26

Browse files
committed
validate stability against deprecation version
1 parent 5779fff commit 2962b26

File tree

3 files changed

+43
-3
lines changed

3 files changed

+43
-3
lines changed

src/librustc/middle/stability.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
3131
use util::ppaux::Repr;
3232

3333
use std::mem::replace;
34+
use std::cmp::Ordering;
3435

3536
/// A stability index, giving the stability level for items and methods.
3637
pub struct Index<'tcx> {
@@ -73,6 +74,44 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
7374
}
7475

7576
let stab = self.tcx.intern_stability(stab);
77+
78+
// Check if deprecated_since < stable_since. If it is,
79+
// this is *almost surely* an accident.
80+
let deprecated_predates_stable = match (stab.deprecated_since.as_ref(),
81+
stab.since.as_ref()) {
82+
(Some(dep_since), Some(stab_since)) => {
83+
// explicit version of iter::order::lt to handle parse errors properly
84+
let mut is_less = false;
85+
for (dep_v, stab_v) in dep_since.split(".").zip(stab_since.split(".")) {
86+
match (dep_v.parse::<u64>(), stab_v.parse::<u64>()) {
87+
(Ok(dep_v), Ok(stab_v)) => match dep_v.cmp(&stab_v) {
88+
Ordering::Less => {
89+
is_less = true;
90+
break;
91+
}
92+
Ordering::Equal => { continue; }
93+
Ordering::Greater => { break; }
94+
},
95+
_ => {
96+
self.tcx.sess.span_err(item_sp,
97+
"Invalid stability or deprecation version found");
98+
// act like it isn't less because the question is now
99+
// nonsensical, and this makes us not do anything else
100+
// interesting.
101+
break;
102+
}
103+
}
104+
}
105+
is_less
106+
},
107+
_ => false,
108+
};
109+
110+
if deprecated_predates_stable {
111+
self.tcx.sess.span_err(item_sp,
112+
"An API can't be stabilized after it is deprecated");
113+
}
114+
76115
self.index.map.insert(local_def(id), Some(stab));
77116

78117
// Don't inherit #[stable(feature = "rust1", since = "1.0.0")]

src/libsyntax/attr.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ fn find_stability_generic<'a,
397397
-> (Option<Stability>, Vec<&'a AM>) {
398398

399399
let mut stab: Option<Stability> = None;
400-
let mut deprecated: Option<(InternedString, Option<InternedString>)> = None;
400+
let mut deprecated: Option<(Option<InternedString>, Option<InternedString>)> = None;
401401
let mut used_attrs: Vec<&'a AM> = vec![];
402402

403403
'outer: for attr in attrs {
@@ -484,7 +484,7 @@ fn find_stability_generic<'a,
484484
diagnostic.span_err(item_sp, "multiple deprecated attributes");
485485
}
486486

487-
deprecated = Some((since.unwrap_or(intern_and_get_ident("bogus")), reason));
487+
deprecated = Some((since, reason));
488488
}
489489
}
490490

@@ -493,7 +493,7 @@ fn find_stability_generic<'a,
493493
match stab {
494494
Some(ref mut s) => {
495495
let (since, reason) = deprecated.unwrap();
496-
s.deprecated_since = Some(since);
496+
s.deprecated_since = since;
497497
s.reason = reason;
498498
}
499499
None => {

src/test/compile-fail/stability-attribute-sanity.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ fn multiple3() { } //~ ERROR multiple stability levels
8888
#[deprecated(since = "b")]
8989
#[deprecated(since = "b")]
9090
fn multiple4() { } //~ ERROR multiple deprecated attributes
91+
//~^ ERROR Invalid stability or deprecation version found
9192

9293
#[deprecated(since = "a")]
9394
fn deprecated_without_unstable_or_stable() { } //~ ERROR deprecated attribute must be paired

0 commit comments

Comments
 (0)