about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-08-21 18:16:43 +0000
committerbors <bors@rust-lang.org>2018-08-21 18:16:43 +0000
commit2d6d3acf4f6f405af1fcf178300a0728496de138 (patch)
tree5d83bd19ac95adbbc3f4684be5c9a77aacd9e5eb /src
parent9f9f2c0095cd683b94adca133f2733aa1f88bb19 (diff)
parent16958569af5c3dca9d1a46b0485254e2c095f022 (diff)
downloadrust-2d6d3acf4f6f405af1fcf178300a0728496de138.tar.gz
rust-2d6d3acf4f6f405af1fcf178300a0728496de138.zip
Auto merge of #53444 - varkor:lib_features-conditional, r=michaelwoerister
Only fetch lib_features when there are unknown feature attributes

An attempt to win back some of the performance lost in https://github.com/rust-lang/rust/pull/52644#issuecomment-413761127.

cc @nnethercote
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/lib_features.rs7
-rw-r--r--src/librustc/middle/stability.rs32
2 files changed, 27 insertions, 12 deletions
diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs
index c21ac621803..ec618de6773 100644
--- a/src/librustc/middle/lib_features.rs
+++ b/src/librustc/middle/lib_features.rs
@@ -17,7 +17,7 @@
 use ty::TyCtxt;
 use syntax::symbol::Symbol;
 use syntax::ast::{Attribute, MetaItem, MetaItemKind};
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::Span;
 use hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use errors::DiagnosticId;
@@ -152,11 +152,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LibFeatureCollector<'a, 'tcx> {
 
 pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LibFeatures {
     let mut collector = LibFeatureCollector::new(tcx);
-    for &cnum in tcx.crates().iter() {
-        for &(feature, since) in tcx.defined_lib_features(cnum).iter() {
-            collector.collect_feature(feature, since, DUMMY_SP);
-        }
-    }
     intravisit::walk_crate(&mut collector, tcx.hir.krate());
     collector.lib_features
 }
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index efd568b03ab..85195b0f62e 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -846,14 +846,34 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     remaining_lib_features.remove(&Symbol::intern("libc"));
     remaining_lib_features.remove(&Symbol::intern("test"));
 
-    for (feature, stable) in tcx.lib_features().to_vec() {
-        if let Some(since) = stable {
-            if let Some(span) = remaining_lib_features.get(&feature) {
-                // Warn if the user has enabled an already-stable lib feature.
-                unnecessary_stable_feature_lint(tcx, *span, feature, since);
+    let check_features =
+        |remaining_lib_features: &mut FxHashMap<_, _>, defined_features: &Vec<_>| {
+            for &(feature, since) in defined_features {
+                if let Some(since) = since {
+                    if let Some(span) = remaining_lib_features.get(&feature) {
+                        // Warn if the user has enabled an already-stable lib feature.
+                        unnecessary_stable_feature_lint(tcx, *span, feature, since);
+                    }
+                }
+                remaining_lib_features.remove(&feature);
+                if remaining_lib_features.is_empty() {
+                    break;
+                }
+            }
+        };
+
+    // We always collect the lib features declared in the current crate, even if there are
+    // no unknown features, because the collection also does feature attribute validation.
+    let local_defined_features = tcx.lib_features().to_vec();
+    if !remaining_lib_features.is_empty() {
+        check_features(&mut remaining_lib_features, &local_defined_features);
+
+        for &cnum in &*tcx.crates() {
+            if remaining_lib_features.is_empty() {
+                break;
             }
+            check_features(&mut remaining_lib_features, &tcx.defined_lib_features(cnum));
         }
-        remaining_lib_features.remove(&feature);
     }
 
     for (feature, span) in remaining_lib_features {