提交 06c9e0f5 编写于 作者: Z Zack M. Davis

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.
上级 f3bfa313
......@@ -26,7 +26,7 @@
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 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 @@ pub fn new(hir_map: &hir_map::Map) -> 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 @@ fn check(&mut self, id: DefId, span: Span,
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 @@ fn check(&mut self, id: DefId, span: Span,
}
}
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 @@ fn lookup_deprecation_uncached(self, id: DefId) -> Option<Deprecation> {
/// 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 */ )
......
......@@ -59,8 +59,8 @@ fn f(features: &mut Features) -> &mut bool {
/// 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));
}
......
......@@ -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();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册