2424//! Errors are reported if we are in the suitable configuration but
2525//! the required condition is not met.
2626
27+ use super :: directory:: RetracedDefIdDirectory ;
28+ use super :: load:: DirtyNodes ;
2729use rustc:: dep_graph:: { DepGraphQuery , DepNode } ;
2830use rustc:: hir;
2931use rustc:: hir:: def_id:: DefId ;
3032use rustc:: hir:: intravisit:: Visitor ;
33+ use rustc_data_structures:: fnv:: FnvHashSet ;
3134use syntax:: ast:: { self , Attribute , MetaItem } ;
3235use syntax:: attr:: AttrMetaMethods ;
3336use syntax:: parse:: token:: InternedString ;
@@ -38,19 +41,33 @@ const CLEAN: &'static str = "rustc_clean";
3841const LABEL : & ' static str = "label" ;
3942const CFG : & ' static str = "cfg" ;
4043
41- pub fn check_dirty_clean_annotations < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
44+ pub fn check_dirty_clean_annotations < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
45+ dirty_inputs : & DirtyNodes ,
46+ retraced : & RetracedDefIdDirectory ) {
47+ // can't add `#[rustc_dirty]` etc without opting in to this feature
48+ if !tcx. sess . features . borrow ( ) . rustc_attrs {
49+ return ;
50+ }
51+
4252 let _ignore = tcx. dep_graph . in_ignore ( ) ;
53+ let dirty_inputs: FnvHashSet < DepNode < DefId > > =
54+ dirty_inputs. iter ( )
55+ . filter_map ( |d| retraced. map ( d) )
56+ . collect ( ) ;
4357 let query = tcx. dep_graph . query ( ) ;
58+ debug ! ( "query-nodes: {:?}" , query. nodes( ) ) ;
4459 let krate = tcx. map . krate ( ) ;
4560 krate. visit_all_items ( & mut DirtyCleanVisitor {
4661 tcx : tcx,
4762 query : & query,
63+ dirty_inputs : dirty_inputs,
4864 } ) ;
4965}
5066
5167pub struct DirtyCleanVisitor < ' a , ' tcx : ' a > {
5268 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
5369 query : & ' a DepGraphQuery < DefId > ,
70+ dirty_inputs : FnvHashSet < DepNode < DefId > > ,
5471}
5572
5673impl < ' a , ' tcx > DirtyCleanVisitor < ' a , ' tcx > {
@@ -81,10 +98,13 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
8198 return true ;
8299 }
83100 }
101+ return false ;
84102 }
85103 }
86- debug ! ( "check_config: no match found" ) ;
87- return false ;
104+
105+ self . tcx . sess . span_fatal (
106+ attr. span ,
107+ & format ! ( "no cfg attribute" ) ) ;
88108 }
89109
90110 fn dep_node ( & self , attr : & Attribute , def_id : DefId ) -> DepNode < DefId > {
@@ -105,29 +125,59 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
105125 self . tcx . sess . span_fatal ( attr. span , "no `label` found" ) ;
106126 }
107127
108- fn dep_node_str ( & self , dep_node : DepNode < DefId > ) -> DepNode < String > {
128+ fn dep_node_str ( & self , dep_node : & DepNode < DefId > ) -> DepNode < String > {
109129 dep_node. map_def ( |& def_id| Some ( self . tcx . item_path_str ( def_id) ) ) . unwrap ( )
110130 }
111131
112132 fn assert_dirty ( & self , item : & hir:: Item , dep_node : DepNode < DefId > ) {
113133 debug ! ( "assert_dirty({:?})" , dep_node) ;
114134
115- if self . query . contains_node ( & dep_node) {
116- let dep_node_str = self . dep_node_str ( dep_node) ;
117- self . tcx . sess . span_err (
118- item. span ,
119- & format ! ( "`{:?}` found in dep graph, but should be dirty" , dep_node_str) ) ;
135+ match dep_node {
136+ DepNode :: Hir ( _) => {
137+ // HIR nodes are inputs, so if we are asserting that the HIR node is
138+ // dirty, we check the dirty input set.
139+ if !self . dirty_inputs . contains ( & dep_node) {
140+ let dep_node_str = self . dep_node_str ( & dep_node) ;
141+ self . tcx . sess . span_err (
142+ item. span ,
143+ & format ! ( "`{:?}` not found in dirty set, but should be dirty" , dep_node_str) ) ;
144+ }
145+ }
146+ _ => {
147+ // Other kinds of nodes would be targets, so check if
148+ // the dep-graph contains the node.
149+ if self . query . contains_node ( & dep_node) {
150+ let dep_node_str = self . dep_node_str ( & dep_node) ;
151+ self . tcx . sess . span_err (
152+ item. span ,
153+ & format ! ( "`{:?}` found in dep graph, but should be dirty" , dep_node_str) ) ;
154+ }
155+ }
120156 }
121157 }
122158
123159 fn assert_clean ( & self , item : & hir:: Item , dep_node : DepNode < DefId > ) {
124160 debug ! ( "assert_clean({:?})" , dep_node) ;
125161
126- if !self . query . contains_node ( & dep_node) {
127- let dep_node_str = self . dep_node_str ( dep_node) ;
128- self . tcx . sess . span_err (
129- item. span ,
130- & format ! ( "`{:?}` not found in dep graph, but should be clean" , dep_node_str) ) ;
162+ match dep_node {
163+ DepNode :: Hir ( _) => {
164+ // For HIR nodes, check the inputs.
165+ if self . dirty_inputs . contains ( & dep_node) {
166+ let dep_node_str = self . dep_node_str ( & dep_node) ;
167+ self . tcx . sess . span_err (
168+ item. span ,
169+ & format ! ( "`{:?}` found in dirty-node set, but should be clean" , dep_node_str) ) ;
170+ }
171+ }
172+ _ => {
173+ // Otherwise, check if the dep-node exists.
174+ if !self . query . contains_node ( & dep_node) {
175+ let dep_node_str = self . dep_node_str ( & dep_node) ;
176+ self . tcx . sess . span_err (
177+ item. span ,
178+ & format ! ( "`{:?}` not found in dep graph, but should be clean" , dep_node_str) ) ;
179+ }
180+ }
131181 }
132182 }
133183}
0 commit comments