2323//! Errors are reported if we are in the suitable configuration but
2424//! the required condition is not met.
2525//!
26- //! The `#[rustc_metadata_dirty]` and `#[rustc_metadata_clean]` attributes
27- //! can be used to check the incremental compilation hash (ICH) values of
28- //! metadata exported in rlibs.
29- //!
30- //! - If a node is marked with `#[rustc_metadata_clean(cfg="rev2")]` we
31- //! check that the metadata hash for that node is the same for "rev2"
32- //! it was for "rev1".
33- //! - If a node is marked with `#[rustc_metadata_dirty(cfg="rev2")]` we
34- //! check that the metadata hash for that node is *different* for "rev2"
35- //! than it was for "rev1".
36- //!
37- //! Note that the metadata-testing attributes must never specify the
38- //! first revision. This would lead to a crash since there is no
39- //! previous revision to compare things to.
40- //!
4126
4227use std:: collections:: HashSet ;
4328use std:: iter:: FromIterator ;
@@ -49,10 +34,9 @@ use rustc::hir::map::Node as HirNode;
4934use rustc:: hir:: def_id:: DefId ;
5035use rustc:: hir:: itemlikevisit:: ItemLikeVisitor ;
5136use rustc:: hir:: intravisit;
52- use rustc:: ich:: { Fingerprint , ATTR_DIRTY , ATTR_CLEAN , ATTR_DIRTY_METADATA ,
53- ATTR_CLEAN_METADATA } ;
37+ use rustc:: ich:: { ATTR_DIRTY , ATTR_CLEAN } ;
5438use syntax:: ast:: { self , Attribute , NestedMetaItem } ;
55- use rustc_data_structures:: fx:: { FxHashSet , FxHashMap } ;
39+ use rustc_data_structures:: fx:: FxHashSet ;
5640use syntax_pos:: Span ;
5741use rustc:: ty:: TyCtxt ;
5842
@@ -553,157 +537,6 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> {
553537 }
554538}
555539
556- pub fn check_dirty_clean_metadata < ' a , ' tcx > (
557- tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
558- prev_metadata_hashes : & FxHashMap < DefId , Fingerprint > ,
559- current_metadata_hashes : & FxHashMap < DefId , Fingerprint > )
560- {
561- if !tcx. sess . opts . debugging_opts . query_dep_graph {
562- return ;
563- }
564-
565- tcx. dep_graph . with_ignore ( ||{
566- let krate = tcx. hir . krate ( ) ;
567- let mut dirty_clean_visitor = DirtyCleanMetadataVisitor {
568- tcx,
569- prev_metadata_hashes,
570- current_metadata_hashes,
571- checked_attrs : FxHashSet ( ) ,
572- } ;
573- intravisit:: walk_crate ( & mut dirty_clean_visitor, krate) ;
574-
575- let mut all_attrs = FindAllAttrs {
576- tcx,
577- attr_names : vec ! [ ATTR_DIRTY_METADATA , ATTR_CLEAN_METADATA ] ,
578- found_attrs : vec ! [ ] ,
579- } ;
580- intravisit:: walk_crate ( & mut all_attrs, krate) ;
581-
582- // Note that we cannot use the existing "unused attribute"-infrastructure
583- // here, since that is running before trans. This is also the reason why
584- // all trans-specific attributes are `Whitelisted` in syntax::feature_gate.
585- all_attrs. report_unchecked_attrs ( & dirty_clean_visitor. checked_attrs ) ;
586- } ) ;
587- }
588-
589- pub struct DirtyCleanMetadataVisitor < ' a , ' tcx : ' a , ' m > {
590- tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
591- prev_metadata_hashes : & ' m FxHashMap < DefId , Fingerprint > ,
592- current_metadata_hashes : & ' m FxHashMap < DefId , Fingerprint > ,
593- checked_attrs : FxHashSet < ast:: AttrId > ,
594- }
595-
596- impl < ' a , ' tcx , ' m > intravisit:: Visitor < ' tcx > for DirtyCleanMetadataVisitor < ' a , ' tcx , ' m > {
597-
598- fn nested_visit_map < ' this > ( & ' this mut self ) -> intravisit:: NestedVisitorMap < ' this , ' tcx > {
599- intravisit:: NestedVisitorMap :: All ( & self . tcx . hir )
600- }
601-
602- fn visit_item ( & mut self , item : & ' tcx hir:: Item ) {
603- self . check_item ( item. id , item. span ) ;
604- intravisit:: walk_item ( self , item) ;
605- }
606-
607- fn visit_variant ( & mut self ,
608- variant : & ' tcx hir:: Variant ,
609- generics : & ' tcx hir:: Generics ,
610- parent_id : ast:: NodeId ) {
611- if let Some ( e) = variant. node . disr_expr {
612- self . check_item ( e. node_id , variant. span ) ;
613- }
614-
615- intravisit:: walk_variant ( self , variant, generics, parent_id) ;
616- }
617-
618- fn visit_variant_data ( & mut self ,
619- variant_data : & ' tcx hir:: VariantData ,
620- _: ast:: Name ,
621- _: & ' tcx hir:: Generics ,
622- _parent_id : ast:: NodeId ,
623- span : Span ) {
624- if self . tcx . hir . find ( variant_data. id ( ) ) . is_some ( ) {
625- // VariantData that represent structs or tuples don't have a
626- // separate entry in the HIR map and checking them would error,
627- // so only check if this is an enum or union variant.
628- self . check_item ( variant_data. id ( ) , span) ;
629- }
630-
631- intravisit:: walk_struct_def ( self , variant_data) ;
632- }
633-
634- fn visit_trait_item ( & mut self , item : & ' tcx hir:: TraitItem ) {
635- self . check_item ( item. id , item. span ) ;
636- intravisit:: walk_trait_item ( self , item) ;
637- }
638-
639- fn visit_impl_item ( & mut self , item : & ' tcx hir:: ImplItem ) {
640- self . check_item ( item. id , item. span ) ;
641- intravisit:: walk_impl_item ( self , item) ;
642- }
643-
644- fn visit_foreign_item ( & mut self , i : & ' tcx hir:: ForeignItem ) {
645- self . check_item ( i. id , i. span ) ;
646- intravisit:: walk_foreign_item ( self , i) ;
647- }
648-
649- fn visit_struct_field ( & mut self , s : & ' tcx hir:: StructField ) {
650- self . check_item ( s. id , s. span ) ;
651- intravisit:: walk_struct_field ( self , s) ;
652- }
653- }
654-
655- impl < ' a , ' tcx , ' m > DirtyCleanMetadataVisitor < ' a , ' tcx , ' m > {
656-
657- fn check_item ( & mut self , item_id : ast:: NodeId , item_span : Span ) {
658- let def_id = self . tcx . hir . local_def_id ( item_id) ;
659-
660- for attr in self . tcx . get_attrs ( def_id) . iter ( ) {
661- if attr. check_name ( ATTR_DIRTY_METADATA ) {
662- if check_config ( self . tcx , attr) {
663- if self . checked_attrs . insert ( attr. id ) {
664- self . assert_state ( false , def_id, item_span) ;
665- }
666- }
667- } else if attr. check_name ( ATTR_CLEAN_METADATA ) {
668- if check_config ( self . tcx , attr) {
669- if self . checked_attrs . insert ( attr. id ) {
670- self . assert_state ( true , def_id, item_span) ;
671- }
672- }
673- }
674- }
675- }
676-
677- fn assert_state ( & self , should_be_clean : bool , def_id : DefId , span : Span ) {
678- let item_path = self . tcx . item_path_str ( def_id) ;
679- debug ! ( "assert_state({})" , item_path) ;
680-
681- if let Some ( & prev_hash) = self . prev_metadata_hashes . get ( & def_id) {
682- let hashes_are_equal = prev_hash == self . current_metadata_hashes [ & def_id] ;
683-
684- if should_be_clean && !hashes_are_equal {
685- self . tcx . sess . span_err (
686- span,
687- & format ! ( "Metadata hash of `{}` is dirty, but should be clean" ,
688- item_path) ) ;
689- }
690-
691- let should_be_dirty = !should_be_clean;
692- if should_be_dirty && hashes_are_equal {
693- self . tcx . sess . span_err (
694- span,
695- & format ! ( "Metadata hash of `{}` is clean, but should be dirty" ,
696- item_path) ) ;
697- }
698- } else {
699- self . tcx . sess . span_err (
700- span,
701- & format ! ( "Could not find previous metadata hash of `{}`" ,
702- item_path) ) ;
703- }
704- }
705- }
706-
707540/// Given a `#[rustc_dirty]` or `#[rustc_clean]` attribute, scan
708541/// for a `cfg="foo"` attribute and check whether we have a cfg
709542/// flag called `foo`.
@@ -759,7 +592,6 @@ fn expect_associated_value(tcx: TyCtxt, item: &NestedMetaItem) -> ast::Name {
759592 }
760593}
761594
762-
763595// A visitor that collects all #[rustc_dirty]/#[rustc_clean] attributes from
764596// the HIR. It is used to verfiy that we really ran checks for all annotated
765597// nodes.
0 commit comments