@@ -27,6 +27,7 @@ use rustc::hir::intravisit;
27
27
use rustc:: session:: { self , CompileIncomplete , config} ;
28
28
use rustc:: session:: config:: { OutputType , OutputTypes , Externs , CodegenOptions } ;
29
29
use rustc:: session:: search_paths:: { SearchPaths , PathKind } ;
30
+ use rustc:: util:: nodemap:: FxHashSet ;
30
31
use rustc_metadata:: dynamic_lib:: DynamicLibrary ;
31
32
use tempfile:: Builder as TempFileBuilder ;
32
33
use rustc_driver:: { self , driver, target_features, Compilation } ;
@@ -152,6 +153,7 @@ pub fn run(input_path: &Path,
152
153
collector : & mut collector,
153
154
map : & map,
154
155
codes : ErrorCodes :: from ( sess. opts . unstable_features . is_nightly_build ( ) ) ,
156
+ tested_items : FxHashSet ( ) ,
155
157
current_vis : true ,
156
158
} ;
157
159
hir_collector. visit_testable ( "" . to_string ( ) , & krate. attrs , true , |this| {
@@ -673,6 +675,7 @@ struct HirCollector<'a, 'hir: 'a> {
673
675
collector : & ' a mut Collector ,
674
676
map : & ' a hir:: map:: Map < ' hir > ,
675
677
codes : ErrorCodes ,
678
+ tested_items : FxHashSet < ast:: NodeId > ,
676
679
current_vis : bool ,
677
680
}
678
681
@@ -745,8 +748,6 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
745
748
if is_public {
746
749
if let Some ( node) = self . map . get_if_local ( path. def . def_id ( ) ) {
747
750
// load doctests from the actual item, not the use statement
748
- // TODO(misdreavus): this will run some doctests multiple times if an item is
749
- // re-exported multiple times (say, into a prelude)
750
751
match node {
751
752
// if we've re-exported an item, continue with the new item, using the
752
753
// exported visibility
@@ -791,6 +792,11 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
791
792
}
792
793
}
793
794
795
+ if !self . tested_items . insert ( item. id ) {
796
+ // item's been tested already, don't run them again
797
+ return ;
798
+ }
799
+
794
800
let name = if let hir:: ItemKind :: Impl ( .., ref ty, _) = item. node {
795
801
self . map . node_to_pretty_string ( ty. id )
796
802
} else {
@@ -815,19 +821,34 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
815
821
}
816
822
817
823
fn visit_trait_item ( & mut self , item : & ' hir hir:: TraitItem ) {
824
+ if !self . tested_items . insert ( item. id ) {
825
+ // item's been tested already, don't run them again
826
+ return ;
827
+ }
828
+
818
829
self . visit_testable ( item. ident . to_string ( ) , & item. attrs , true , |this| {
819
830
intravisit:: walk_trait_item ( this, item) ;
820
831
} ) ;
821
832
}
822
833
823
834
fn visit_impl_item ( & mut self , item : & ' hir hir:: ImplItem ) {
835
+ if !self . tested_items . insert ( item. id ) {
836
+ // item's been tested already, don't run them again
837
+ return ;
838
+ }
839
+
824
840
let is_public = item. vis . node . is_pub ( ) ;
825
841
self . visit_testable ( item. ident . to_string ( ) , & item. attrs , is_public, |this| {
826
842
intravisit:: walk_impl_item ( this, item) ;
827
843
} ) ;
828
844
}
829
845
830
846
fn visit_foreign_item ( & mut self , item : & ' hir hir:: ForeignItem ) {
847
+ if !self . tested_items . insert ( item. id ) {
848
+ // item's been tested already, don't run them again
849
+ return ;
850
+ }
851
+
831
852
let is_public = item. vis . node . is_pub ( ) ;
832
853
self . visit_testable ( item. name . to_string ( ) ,
833
854
& item. attrs ,
@@ -841,12 +862,20 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
841
862
v : & ' hir hir:: Variant ,
842
863
g : & ' hir hir:: Generics ,
843
864
item_id : ast:: NodeId ) {
865
+ // FIXME(misdreavus): variants don't have their own NodeId so we can't insert them into the
866
+ // set
867
+
844
868
self . visit_testable ( v. node . name . to_string ( ) , & v. node . attrs , true , |this| {
845
869
intravisit:: walk_variant ( this, v, g, item_id) ;
846
870
} ) ;
847
871
}
848
872
849
873
fn visit_struct_field ( & mut self , f : & ' hir hir:: StructField ) {
874
+ if !self . tested_items . insert ( f. id ) {
875
+ // item's been tested already, don't run them again
876
+ return ;
877
+ }
878
+
850
879
let is_public = f. vis . node . is_pub ( ) ;
851
880
self . visit_testable ( f. ident . to_string ( ) ,
852
881
& f. attrs ,
@@ -857,6 +886,11 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
857
886
}
858
887
859
888
fn visit_macro_def ( & mut self , macro_def : & ' hir hir:: MacroDef ) {
889
+ if !self . tested_items . insert ( macro_def. id ) {
890
+ // item's been tested already, don't run them again
891
+ return ;
892
+ }
893
+
860
894
// FIXME(misdreavus): does macro export status surface to us? is it in AccessLevels, does
861
895
// its #[macro_export] attribute show up here?
862
896
self . visit_testable ( macro_def. name . to_string ( ) , & macro_def. attrs , true , |_| ( ) ) ;
0 commit comments