@@ -201,16 +201,17 @@ impl Index {
201
201
/// Cross-references the feature names of unstable APIs with enabled
202
202
/// features and possibly prints errors. Returns a list of all
203
203
/// features used.
204
- pub fn check_unstable_api_usage ( tcx : & ty:: ctxt ) -> FnvHashSet < InternedString > {
205
- let ref active_lib_features = tcx. sess . features . borrow ( ) . lib_features ;
204
+ pub fn check_unstable_api_usage ( tcx : & ty:: ctxt )
205
+ -> FnvHashMap < InternedString , attr:: StabilityLevel > {
206
+ let ref active_lib_features = tcx. sess . features . borrow ( ) . declared_lib_features ;
206
207
207
208
// Put the active features into a map for quick lookup
208
209
let active_features = active_lib_features. iter ( ) . map ( |& ( ref s, _) | s. clone ( ) ) . collect ( ) ;
209
210
210
211
let mut checker = Checker {
211
212
tcx : tcx,
212
213
active_features : active_features,
213
- used_features : FnvHashSet ( )
214
+ used_features : FnvHashMap ( )
214
215
} ;
215
216
216
217
let krate = tcx. map . krate ( ) ;
@@ -223,7 +224,7 @@ pub fn check_unstable_api_usage(tcx: &ty::ctxt) -> FnvHashSet<InternedString> {
223
224
struct Checker < ' a , ' tcx : ' a > {
224
225
tcx : & ' a ty:: ctxt < ' tcx > ,
225
226
active_features : FnvHashSet < InternedString > ,
226
- used_features : FnvHashSet < InternedString >
227
+ used_features : FnvHashMap < InternedString , attr :: StabilityLevel >
227
228
}
228
229
229
230
impl < ' a , ' tcx > Checker < ' a , ' tcx > {
@@ -234,7 +235,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
234
235
235
236
match * stab {
236
237
Some ( Stability { level : attr:: Unstable , ref feature, ref reason, .. } ) => {
237
- self . used_features . insert ( feature. clone ( ) ) ;
238
+ self . used_features . insert ( feature. clone ( ) , attr :: Unstable ) ;
238
239
239
240
if !self . active_features . contains ( feature) {
240
241
let msg = match * reason {
@@ -247,7 +248,9 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
247
248
feature. get ( ) , span, & msg[ ] ) ;
248
249
}
249
250
}
250
- Some ( ..) => {
251
+ Some ( Stability { level, ref feature, .. } ) => {
252
+ self . used_features . insert ( feature. clone ( ) , level) ;
253
+
251
254
// Stable APIs are always ok to call and deprecated APIs are
252
255
// handled by a lint.
253
256
}
@@ -433,17 +436,37 @@ pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
433
436
/// Given the list of enabled features that were not language features (i.e. that
434
437
/// were expected to be library features), and the list of features used from
435
438
/// libraries, identify activated features that don't exist and error about them.
436
- pub fn check_unused_features ( sess : & Session ,
437
- used_lib_features : & FnvHashSet < InternedString > ) {
438
- let ref lib_features = sess. features . borrow ( ) . lib_features ;
439
- let mut active_lib_features: FnvHashMap < InternedString , Span >
440
- = lib_features. clone ( ) . into_iter ( ) . collect ( ) ;
441
-
442
- for used_feature in used_lib_features {
443
- active_lib_features. remove ( used_feature) ;
439
+ pub fn check_unused_or_stable_features ( sess : & Session ,
440
+ lib_features_used : & FnvHashMap < InternedString ,
441
+ attr:: StabilityLevel > ) {
442
+ let ref declared_lib_features = sess. features . borrow ( ) . declared_lib_features ;
443
+ let mut remaining_lib_features: FnvHashMap < InternedString , Span >
444
+ = declared_lib_features. clone ( ) . into_iter ( ) . collect ( ) ;
445
+
446
+ let stable_msg = "this feature is stable. attribute no longer needed" ;
447
+
448
+ for & span in sess. features . borrow ( ) . declared_stable_lang_features . iter ( ) {
449
+ sess. add_lint ( lint:: builtin:: STABLE_FEATURES ,
450
+ ast:: CRATE_NODE_ID ,
451
+ span,
452
+ stable_msg. to_string ( ) ) ;
453
+ }
454
+
455
+ for ( used_lib_feature, level) in lib_features_used. iter ( ) {
456
+ match remaining_lib_features. remove ( used_lib_feature) {
457
+ Some ( span) => {
458
+ if * level == attr:: Stable {
459
+ sess. add_lint ( lint:: builtin:: STABLE_FEATURES ,
460
+ ast:: CRATE_NODE_ID ,
461
+ span,
462
+ stable_msg. to_string ( ) ) ;
463
+ }
464
+ }
465
+ None => ( /* used but undeclared, handled during the previous ast visit */ )
466
+ }
444
467
}
445
468
446
- for ( _, & span) in & active_lib_features {
469
+ for ( _, & span) in remaining_lib_features . iter ( ) {
447
470
sess. add_lint ( lint:: builtin:: UNUSED_FEATURES ,
448
471
ast:: CRATE_NODE_ID ,
449
472
span,
0 commit comments