about summary refs log tree commit diff
diff options
context:
space:
mode:
authorZack M. Davis <code@zackmdavis.net>2016-05-30 13:55:12 -0700
committerZack M. Davis <code@zackmdavis.net>2016-05-30 15:17:13 -0700
commit06c9e0f5f80d2a2bad9e7b90af73b8dc89f756c6 (patch)
tree4da9532b7e04994b9596b00dd20280046ea489a1
parentf3bfa313ecf557b9684568f6a2acd42cd67cc1bc (diff)
downloadrust-06c9e0f5f80d2a2bad9e7b90af73b8dc89f756c6.tar.gz
rust-06c9e0f5f80d2a2bad9e7b90af73b8dc89f756c6.zip
stable features lint warning mentions version stabilized
To accomplish this, we alter the checks in `rustc::middle::stability` to
use the `StabilityLevel` defined in `syntax::attr` (which includes the
version in which the feature was stabilized) rather than the local
`StabilityLevel` in the same module, and make the
`declared_stable_lang_features` field of
`syntax::feature_gate::Features` hold a Vec of feature-name, span
tuples (in analogy to the `declared_lib_features` field) rather than
just spans.

This is in the matter of issue #33394.
-rw-r--r--src/librustc/middle/stability.rs28
-rw-r--r--src/libsyntax/feature_gate.rs10
-rw-r--r--src/test/compile-fail/stable-features.rs4
3 files changed, 26 insertions, 16 deletions
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index fcb03aba6d1..eb1fb43789f 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -26,7 +26,7 @@ use syntax::parse::token::InternedString;
 use syntax::codemap::{Span, DUMMY_SP};
 use syntax::ast;
 use syntax::ast::{NodeId, Attribute};
-use syntax::feature_gate::{GateIssue, emit_feature_err};
+use syntax::feature_gate::{GateIssue, emit_feature_err, find_lang_feature_accepted_version};
 use syntax::attr::{self, Stability, Deprecation, AttrMetaMethods};
 use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
 
@@ -37,6 +37,7 @@ use hir::pat_util::EnumerateAndAdjustIterator;
 
 use std::mem::replace;
 use std::cmp::Ordering;
+use std::ops::Deref;
 
 #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Copy, Debug, Eq, Hash)]
 pub enum StabilityLevel {
@@ -322,7 +323,7 @@ impl<'a, 'tcx> Index<'tcx> {
 /// features and possibly prints errors. Returns a list of all
 /// features used.
 pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                                          -> FnvHashMap<InternedString, StabilityLevel> {
+                                          -> FnvHashMap<InternedString, attr::StabilityLevel> {
     let _task = tcx.dep_graph.in_task(DepNode::StabilityCheck);
     let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features;
 
@@ -343,7 +344,7 @@ pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
 struct Checker<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     active_features: FnvHashSet<InternedString>,
-    used_features: FnvHashMap<InternedString, StabilityLevel>,
+    used_features: FnvHashMap<InternedString, attr::StabilityLevel>,
     // Within a block where feature gate checking can be skipped.
     in_skip_block: u32,
 }
@@ -367,7 +368,8 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
 
         match *stab {
             Some(&Stability { level: attr::Unstable {ref reason, issue}, ref feature, .. }) => {
-                self.used_features.insert(feature.clone(), Unstable);
+                self.used_features.insert(feature.clone(),
+                                          attr::Unstable { reason: reason.clone(), issue: issue });
 
                 if !self.active_features.contains(feature) {
                     let msg = match *reason {
@@ -380,7 +382,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
                 }
             }
             Some(&Stability { ref level, ref feature, .. }) => {
-                self.used_features.insert(feature.clone(), StabilityLevel::from_attr_level(level));
+                self.used_features.insert(feature.clone(), level.clone());
 
                 // Stable APIs are always ok to call and deprecated APIs are
                 // handled by a lint.
@@ -716,28 +718,32 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
 /// libraries, identify activated features that don't exist and error about them.
 pub fn check_unused_or_stable_features(sess: &Session,
                                        lib_features_used: &FnvHashMap<InternedString,
-                                                                      StabilityLevel>) {
+                                                                      attr::StabilityLevel>) {
     let ref declared_lib_features = sess.features.borrow().declared_lib_features;
     let mut remaining_lib_features: FnvHashMap<InternedString, Span>
         = declared_lib_features.clone().into_iter().collect();
 
-    let stable_msg = "this feature is stable. attribute no longer needed";
+    fn format_stable_since_msg(version: &str) -> String {
+        format!("this feature has been stable since {}. Attribute no longer needed", version)
+    }
 
-    for &span in &sess.features.borrow().declared_stable_lang_features {
+    for &(ref stable_lang_feature, span) in &sess.features.borrow().declared_stable_lang_features {
+        let version = find_lang_feature_accepted_version(stable_lang_feature.deref())
+            .expect("unexpectedly couldn't find version feature was stabilized");
         sess.add_lint(lint::builtin::STABLE_FEATURES,
                       ast::CRATE_NODE_ID,
                       span,
-                      stable_msg.to_string());
+                      format_stable_since_msg(version));
     }
 
     for (used_lib_feature, level) in lib_features_used {
         match remaining_lib_features.remove(used_lib_feature) {
             Some(span) => {
-                if *level == Stable {
+                if let &attr::StabilityLevel::Stable { since: ref version } = level {
                     sess.add_lint(lint::builtin::STABLE_FEATURES,
                                   ast::CRATE_NODE_ID,
                                   span,
-                                  stable_msg.to_string());
+                                  format_stable_since_msg(version.deref()));
                 }
             }
             None => ( /* used but undeclared, handled during the previous ast visit */ )
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 5687099b27c..08e593ca747 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -59,8 +59,8 @@ macro_rules! declare_features {
 
         /// A set of features to be used by later passes.
         pub struct Features {
-            /// spans of #![feature] attrs for stable language features. for error reporting
-            pub declared_stable_lang_features: Vec<Span>,
+            /// #![feature] attrs for stable language features, for error reporting
+            pub declared_stable_lang_features: Vec<(InternedString, Span)>,
             /// #![feature] attrs for non-language (library) features
             pub declared_lib_features: Vec<(InternedString, Span)>,
             $(pub $feature: bool),+
@@ -753,6 +753,10 @@ pub fn check_attribute(attr: &ast::Attribute, handler: &Handler,
     cx.check_attribute(attr, true);
 }
 
+pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
+    ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
+}
+
 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
     if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
         let issue = info.2;
@@ -1191,7 +1195,7 @@ pub fn get_features(span_handler: &Handler, krate: &ast::Crate) -> Features {
                     }
                     else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
                         .find(|& &(n, _, _)| name == n) {
-                        features.declared_stable_lang_features.push(mi.span);
+                        features.declared_stable_lang_features.push((name, mi.span));
                     } else {
                         features.declared_lib_features.push((name, mi.span));
                     }
diff --git a/src/test/compile-fail/stable-features.rs b/src/test/compile-fail/stable-features.rs
index 30eb4112c3f..6f8c95c3840 100644
--- a/src/test/compile-fail/stable-features.rs
+++ b/src/test/compile-fail/stable-features.rs
@@ -12,8 +12,8 @@
 // language and lib features.
 
 #![deny(stable_features)]
-#![feature(test_accepted_feature)] //~ ERROR this feature is stable
-#![feature(rust1)] //~ ERROR this feature is stable
+#![feature(test_accepted_feature)] //~ ERROR this feature has been stable since 1.0.0
+#![feature(rust1)] //~ ERROR this feature has been stable since 1.0.0
 
 fn main() {
     let _foo: Vec<()> = Vec::new();