Skip to content

Commit 747d951

Browse files
committed
Auto merge of #29014 - petrochenkov:stability, r=brson
Stricter checking of stability attributes + enforcement of their invariants at compile time (+ removed dead file librustc_front/attr.rs) I intended to enforce use of `reason` for unstable items as well (it normally presents for new items), but it turned out too intrusive, many older unstable items don't have `reason`s. r? @aturon I'm studying how stability works and do some refactoring along the way, so it's probably not the last PR.
2 parents 87e26ef + 704d598 commit 747d951

18 files changed

+329
-886
lines changed

src/librustc/middle/stability.rs

+30-18
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
//! A pass that annotates every item and method with its stability level,
1212
//! propagating default levels lexically from parent to children ast nodes.
1313
14+
pub use self::StabilityLevel::*;
15+
1416
use session::Session;
1517
use lint;
1618
use metadata::cstore::LOCAL_CRATE;
@@ -34,6 +36,18 @@ use rustc_front::visit::{self, FnKind, Visitor};
3436
use std::mem::replace;
3537
use std::cmp::Ordering;
3638

39+
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Copy, Debug, Eq, Hash)]
40+
pub enum StabilityLevel {
41+
Unstable,
42+
Stable,
43+
}
44+
45+
impl StabilityLevel {
46+
pub fn from_attr_level(level: &attr::StabilityLevel) -> Self {
47+
if level.is_stable() { Stable } else { Unstable }
48+
}
49+
}
50+
3751
/// A stability index, giving the stability level for items and methods.
3852
pub struct Index<'tcx> {
3953
/// This is mostly a cache, except the stabilities of local items
@@ -67,20 +81,19 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
6781
// if parent is deprecated and we're not, inherit this by merging
6882
// deprecated_since and its reason.
6983
if let Some(parent_stab) = self.parent {
70-
if parent_stab.deprecated_since.is_some()
71-
&& stab.deprecated_since.is_none() {
72-
stab.deprecated_since = parent_stab.deprecated_since.clone();
73-
stab.reason = parent_stab.reason.clone();
84+
if parent_stab.depr.is_some()
85+
&& stab.depr.is_none() {
86+
stab.depr = parent_stab.depr.clone()
7487
}
7588
}
7689

7790
let stab = self.tcx.intern_stability(stab);
7891

7992
// Check if deprecated_since < stable_since. If it is,
8093
// this is *almost surely* an accident.
81-
let deprecated_predates_stable = match (stab.deprecated_since.as_ref(),
82-
stab.since.as_ref()) {
83-
(Some(dep_since), Some(stab_since)) => {
94+
let deprecated_predates_stable = match (&stab.depr, &stab.level) {
95+
(&Some(attr::Deprecation {since: ref dep_since, ..}),
96+
&attr::Stable {since: ref stab_since}) => {
8497
// explicit version of iter::order::lt to handle parse errors properly
8598
let mut is_less = false;
8699
for (dep_v, stab_v) in dep_since.split(".").zip(stab_since.split(".")) {
@@ -117,7 +130,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
117130
self.index.map.insert(def_id, Some(stab));
118131

119132
// Don't inherit #[stable(feature = "rust1", since = "1.0.0")]
120-
if stab.level != attr::Stable {
133+
if !stab.level.is_stable() {
121134
let parent = replace(&mut self.parent, Some(stab));
122135
f(self);
123136
self.parent = parent;
@@ -261,7 +274,7 @@ impl<'tcx> Index<'tcx> {
261274
/// features and possibly prints errors. Returns a list of all
262275
/// features used.
263276
pub fn check_unstable_api_usage(tcx: &ty::ctxt)
264-
-> FnvHashMap<InternedString, attr::StabilityLevel> {
277+
-> FnvHashMap<InternedString, StabilityLevel> {
265278
let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features;
266279

267280
// Put the active features into a map for quick lookup
@@ -284,7 +297,7 @@ pub fn check_unstable_api_usage(tcx: &ty::ctxt)
284297
struct Checker<'a, 'tcx: 'a> {
285298
tcx: &'a ty::ctxt<'tcx>,
286299
active_features: FnvHashSet<InternedString>,
287-
used_features: FnvHashMap<InternedString, attr::StabilityLevel>,
300+
used_features: FnvHashMap<InternedString, StabilityLevel>,
288301
// Within a block where feature gate checking can be skipped.
289302
in_skip_block: u32,
290303
}
@@ -303,22 +316,21 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
303316
}
304317

305318
match *stab {
306-
Some(&Stability { level: attr::Unstable, ref feature, ref reason, issue, .. }) => {
307-
self.used_features.insert(feature.clone(), attr::Unstable);
319+
Some(&Stability { level: attr::Unstable {ref reason, issue}, ref feature, .. }) => {
320+
self.used_features.insert(feature.clone(), Unstable);
308321

309322
if !self.active_features.contains(feature) {
310323
let msg = match *reason {
311324
Some(ref r) => format!("use of unstable library feature '{}': {}",
312325
&feature, &r),
313326
None => format!("use of unstable library feature '{}'", &feature)
314327
};
315-
316328
emit_feature_err(&self.tcx.sess.parse_sess.span_diagnostic,
317-
&feature, span, GateIssue::Library(issue), &msg);
329+
&feature, span, GateIssue::Library(Some(issue)), &msg);
318330
}
319331
}
320-
Some(&Stability { level, ref feature, .. }) => {
321-
self.used_features.insert(feature.clone(), level);
332+
Some(&Stability { ref level, ref feature, .. }) => {
333+
self.used_features.insert(feature.clone(), StabilityLevel::from_attr_level(level));
322334

323335
// Stable APIs are always ok to call and deprecated APIs are
324336
// handled by a lint.
@@ -636,7 +648,7 @@ fn lookup_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stabil
636648
/// libraries, identify activated features that don't exist and error about them.
637649
pub fn check_unused_or_stable_features(sess: &Session,
638650
lib_features_used: &FnvHashMap<InternedString,
639-
attr::StabilityLevel>) {
651+
StabilityLevel>) {
640652
let ref declared_lib_features = sess.features.borrow().declared_lib_features;
641653
let mut remaining_lib_features: FnvHashMap<InternedString, Span>
642654
= declared_lib_features.clone().into_iter().collect();
@@ -653,7 +665,7 @@ pub fn check_unused_or_stable_features(sess: &Session,
653665
for (used_lib_feature, level) in lib_features_used {
654666
match remaining_lib_features.remove(used_lib_feature) {
655667
Some(span) => {
656-
if *level == attr::Stable {
668+
if *level == Stable {
657669
sess.add_lint(lint::builtin::STABLE_FEATURES,
658670
ast::CRATE_NODE_ID,
659671
span,

0 commit comments

Comments
 (0)