@@ -53,6 +53,7 @@ use rustc_hir::{
5353use rustc_index:: vec:: { Idx , IndexVec } ;
5454use rustc_macros:: HashStable ;
5555use rustc_middle:: mir:: FakeReadCause ;
56+ use rustc_query_system:: dep_graph:: DepNodeIndex ;
5657use rustc_query_system:: ich:: StableHashingContext ;
5758use rustc_serialize:: opaque:: { FileEncodeResult , FileEncoder } ;
5859use rustc_session:: config:: { CrateType , OutputFilenames } ;
@@ -1009,6 +1010,14 @@ pub struct FreeRegionInfo {
10091010 pub is_impl_item : bool ,
10101011}
10111012
1013+ #[ derive( Copy , Clone ) ]
1014+ pub struct TyCtxtFeed < ' tcx > {
1015+ pub tcx : TyCtxt < ' tcx > ,
1016+ pub def_id : LocalDefId ,
1017+ /// This struct should only be created by `create_def`.
1018+ _priv : ( ) ,
1019+ }
1020+
10121021/// The central data structure of the compiler. It stores references
10131022/// to the various **arenas** and also houses the results of the
10141023/// various **compiler queries** that have been performed. See the
@@ -1471,12 +1480,15 @@ impl<'tcx> TyCtxt<'tcx> {
14711480 }
14721481
14731482 /// Create a new definition within the incr. comp. engine.
1474- pub fn create_def ( self , parent : LocalDefId , data : hir:: definitions:: DefPathData ) -> LocalDefId {
1483+ pub fn create_def (
1484+ self ,
1485+ parent : LocalDefId ,
1486+ data : hir:: definitions:: DefPathData ,
1487+ ) -> TyCtxtFeed < ' tcx > {
14751488 // This function modifies `self.definitions` using a side-effect.
14761489 // We need to ensure that these side effects are re-run by the incr. comp. engine.
14771490 // Depending on the forever-red node will tell the graph that the calling query
14781491 // needs to be re-evaluated.
1479- use rustc_query_system:: dep_graph:: DepNodeIndex ;
14801492 self . dep_graph . read_index ( DepNodeIndex :: FOREVER_RED_NODE ) ;
14811493
14821494 // The following call has the side effect of modifying the tables inside `definitions`.
@@ -1493,23 +1505,38 @@ impl<'tcx> TyCtxt<'tcx> {
14931505 // This is fine because:
14941506 // - those queries are `eval_always` so we won't miss their result changing;
14951507 // - this write will have happened before these queries are called.
1496- self . definitions . write ( ) . create_def ( parent, data)
1508+ let def_id = self . definitions . write ( ) . create_def ( parent, data) ;
1509+
1510+ TyCtxtFeed { tcx : self , def_id, _priv : ( ) }
14971511 }
14981512
14991513 pub fn iter_local_def_id ( self ) -> impl Iterator < Item = LocalDefId > + ' tcx {
1500- // Create a dependency to the crate to be sure we re-execute this when the amount of
1514+ // Create a dependency to the red node to be sure we re-execute this when the amount of
15011515 // definitions change.
1502- self . ensure ( ) . hir_crate ( ( ) ) ;
1503- // Leak a read lock once we start iterating on definitions, to prevent adding new ones
1504- // while iterating. If some query needs to add definitions, it should be `ensure`d above.
1505- let definitions = self . definitions . leak ( ) ;
1506- definitions. iter_local_def_id ( )
1516+ self . dep_graph . read_index ( DepNodeIndex :: FOREVER_RED_NODE ) ;
1517+
1518+ let definitions = & self . definitions ;
1519+ std:: iter:: from_generator ( || {
1520+ let mut i = 0 ;
1521+
1522+ // Recompute the number of definitions each time, because our caller may be creating
1523+ // new ones.
1524+ while i < { definitions. read ( ) . num_definitions ( ) } {
1525+ let local_def_index = rustc_span:: def_id:: DefIndex :: from_usize ( i) ;
1526+ yield LocalDefId { local_def_index } ;
1527+ i += 1 ;
1528+ }
1529+
1530+ // Leak a read lock once we finish iterating on definitions, to prevent adding new ones.
1531+ definitions. leak ( ) ;
1532+ } )
15071533 }
15081534
15091535 pub fn def_path_table ( self ) -> & ' tcx rustc_hir:: definitions:: DefPathTable {
15101536 // Create a dependency to the crate to be sure we re-execute this when the amount of
15111537 // definitions change.
1512- self . ensure ( ) . hir_crate ( ( ) ) ;
1538+ self . dep_graph . read_index ( DepNodeIndex :: FOREVER_RED_NODE ) ;
1539+
15131540 // Leak a read lock once we start iterating on definitions, to prevent adding new ones
15141541 // while iterating. If some query needs to add definitions, it should be `ensure`d above.
15151542 let definitions = self . definitions . leak ( ) ;
0 commit comments