pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  incremental_hashes_map: &IncrementalHashesMap,
                                  dep_graph_data: &[u8],
                                  work_products_data: &[u8])
                                  -> Result<(), String>
{
    // Decode the list of work_products
    let mut work_product_decoder = Decoder::new(work_products_data, 0);
    let work_products = <Vec<SerializedWorkProduct>>::decode(&mut work_product_decoder)?;

    // Deserialize the directory and dep-graph.
    let mut dep_graph_decoder = Decoder::new(dep_graph_data, 0);
    let prev_commandline_args_hash = u64::decode(&mut dep_graph_decoder)?;

    if prev_commandline_args_hash != tcx.sess.opts.dep_tracking_hash() {
        if tcx.sess.opts.debugging_opts.incremental_info {
            println!("incremental: completely ignoring cache because of \
                      differing commandline arguments");
        }
        // We can't reuse the cache, purge it.
        debug!("decode_dep_graph: differing commandline arg hashes");
        for swp in work_products {
            delete_dirty_work_product(tcx, swp);
        }

        // No need to do any further work
        return Ok(());
    }

    let directory = DefIdDirectory::decode(&mut dep_graph_decoder)?;
    let serialized_dep_graph = SerializedDepGraph::decode(&mut dep_graph_decoder)?;

    let edge_map: FxHashMap<_, _> = serialized_dep_graph.edges
                                                        .into_iter()
                                                        .map(|s| (s.source, s.targets))
                                                        .collect();

    // Retrace the paths in the directory to find their current location (if any).
    let retraced = directory.retrace(tcx);

    // Compute the set of nodes from the old graph where some input
    // has changed or been removed. These are "raw" source nodes,
    // which means that they still use the original `DefPathIndex`
    // values from the encoding, rather than having been retraced to a
    // `DefId`. The reason for this is that this way we can include
    // nodes that have been removed (which no longer have a `DefId` in
    // the current compilation).
    let dirty_raw_nodes = initial_dirty_nodes(tcx,
                                              incremental_hashes_map,
                                              &serialized_dep_graph.hashes,
                                              &retraced);
    let dirty_raw_nodes = transitive_dirty_nodes(&edge_map, dirty_raw_nodes);

    // Recreate the edges in the graph that are still clean.
    let mut clean_work_products = FxHashSet();
    let mut dirty_work_products = FxHashSet(); // incomplete; just used to suppress debug output
    let mut extra_edges = vec![];
    for (source, targets) in &edge_map {
        for target in targets {
            process_edges(tcx, source, target, &edge_map, &directory, &retraced, &dirty_raw_nodes,
                          &mut clean_work_products, &mut dirty_work_products, &mut extra_edges);
        }
    }

    // Recreate bootstrap outputs, which are outputs that have no incoming edges (and hence cannot
    // be dirty).
    for bootstrap_output in &serialized_dep_graph.bootstrap_outputs {
        if let Some(n) = retraced.map(bootstrap_output) {
            if let DepNode::WorkProduct(ref wp) = n {
                clean_work_products.insert(wp.clone());
            }

            tcx.dep_graph.with_task(n, (), (), create_node);

            fn create_node((): (), (): ()) {
                // just create the node with no inputs
            }
        }
    }

    // Subtle. Sometimes we have intermediate nodes that we can't recreate in the new graph.
    // This is pretty unusual but it arises in a scenario like this:
    //
    //     Hir(X) -> Foo(Y) -> Bar
    //
    // Note that the `Hir(Y)` is not an input to `Foo(Y)` -- this
    // almost never happens, but can happen in some obscure
    // scenarios. In that case, if `Y` is removed, then we can't
    // recreate `Foo(Y)` (the def-id `Y` no longer exists); what we do
    // then is to push the edge `Hir(X) -> Bar` onto `extra_edges`
    // (along with any other targets of `Foo(Y)`). We will then add
    // the edge from `Hir(X)` to `Bar` (or, if `Bar` itself cannot be
    // recreated, to the targets of `Bar`).
    while let Some((source, target)) = extra_edges.pop() {
        process_edges(tcx, source, target, &edge_map, &directory, &retraced, &dirty_raw_nodes,
                      &mut clean_work_products, &mut dirty_work_products, &mut extra_edges);
    }

    // Add in work-products that are still clean, and delete those that are
    // dirty.
    reconcile_work_products(tcx, work_products, &clean_work_products);

    dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_nodes, &retraced);

    load_prev_metadata_hashes(tcx,
                              &retraced,
                              &mut *incremental_hashes_map.prev_metadata_hashes.borrow_mut());
    Ok(())
}
/// Decode the dep graph and load the edges/nodes that are still clean
/// into `tcx.dep_graph`.
Decode the dep graph and load the edges/nodes that are still clean
into `tcx.dep_graph`.
Decode the dep graph and load the edges / nodes that are still clean into ` tcx . dep_graph ` .
pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  incremental_hashes_map: &IncrementalHashesMap,
                                  dep_graph_data: &[u8],
                                  work_products_data: &[u8])
                                  -> Result<(), String>
{
    // Decode the list of work_products
    let mut work_product_decoder = Decoder::new(work_products_data, 0);
    let work_products = <Vec<SerializedWorkProduct>>::decode(&mut work_product_decoder)?;
    // Deserialize the directory and dep-graph.
    let mut dep_graph_decoder = Decoder::new(dep_graph_data, 0);
    let prev_commandline_args_hash = u64::decode(&mut dep_graph_decoder)?;
    if prev_commandline_args_hash != tcx.sess.opts.dep_tracking_hash() {
        if tcx.sess.opts.debugging_opts.incremental_info {
            println!("incremental: completely ignoring cache because of \
                      differing commandline arguments");
        }
        // We can't reuse the cache, purge it.
        debug!("decode_dep_graph: differing commandline arg hashes");
        for swp in work_products {
            delete_dirty_work_product(tcx, swp);
        }
        // No need to do any further work
        return Ok(());
    }
    let directory = DefIdDirectory::decode(&mut dep_graph_decoder)?;
    let serialized_dep_graph = SerializedDepGraph::decode(&mut dep_graph_decoder)?;
    let edge_map: FxHashMap<_, _> = serialized_dep_graph.edges
                                                        .into_iter()
                                                        .map(|s| (s.source, s.targets))
                                                        .collect();
    // Retrace the paths in the directory to find their current location (if any).
    let retraced = directory.retrace(tcx);
    // Compute the set of nodes from the old graph where some input
    // has changed or been removed. These are "raw" source nodes,
    // which means that they still use the original `DefPathIndex`
    // values from the encoding, rather than having been retraced to a
    // `DefId`. The reason for this is that this way we can include
    // nodes that have been removed (which no longer have a `DefId` in
    // the current compilation).
    let dirty_raw_nodes = initial_dirty_nodes(tcx,
                                              incremental_hashes_map,
                                              &serialized_dep_graph.hashes,
                                              &retraced);
    let dirty_raw_nodes = transitive_dirty_nodes(&edge_map, dirty_raw_nodes);
    // Recreate the edges in the graph that are still clean.
    let mut clean_work_products = FxHashSet();
    let mut dirty_work_products = FxHashSet(); // incomplete; just used to suppress debug output
    let mut extra_edges = vec![];
    for (source, targets) in &edge_map {
        for target in targets {
            process_edges(tcx, source, target, &edge_map, &directory, &retraced, &dirty_raw_nodes,
                          &mut clean_work_products, &mut dirty_work_products, &mut extra_edges);
        }
    }
    // Recreate bootstrap outputs, which are outputs that have no incoming edges (and hence cannot
    // be dirty).
    for bootstrap_output in &serialized_dep_graph.bootstrap_outputs {
        if let Some(n) = retraced.map(bootstrap_output) {
            if let DepNode::WorkProduct(ref wp) = n {
                clean_work_products.insert(wp.clone());
            }
            tcx.dep_graph.with_task(n, (), (), create_node);
            fn create_node((): (), (): ()) {
                // just create the node with no inputs
            }
        }
    }
    // Subtle. Sometimes we have intermediate nodes that we can't recreate in the new graph.
    // This is pretty unusual but it arises in a scenario like this:
    //
    //     Hir(X) -> Foo(Y) -> Bar
    //
    // Note that the `Hir(Y)` is not an input to `Foo(Y)` -- this
    // almost never happens, but can happen in some obscure
    // scenarios. In that case, if `Y` is removed, then we can't
    // recreate `Foo(Y)` (the def-id `Y` no longer exists); what we do
    // then is to push the edge `Hir(X) -> Bar` onto `extra_edges`
    // (along with any other targets of `Foo(Y)`). We will then add
    // the edge from `Hir(X)` to `Bar` (or, if `Bar` itself cannot be
    // recreated, to the targets of `Bar`).
    while let Some((source, target)) = extra_edges.pop() {
        process_edges(tcx, source, target, &edge_map, &directory, &retraced, &dirty_raw_nodes,
                      &mut clean_work_products, &mut dirty_work_products, &mut extra_edges);
    }
    // Add in work-products that are still clean, and delete those that are
    // dirty.
    reconcile_work_products(tcx, work_products, &clean_work_products);
    dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_nodes, &retraced);
    load_prev_metadata_hashes(tcx,
                              &retraced,
                              &mut *incremental_hashes_map.prev_metadata_hashes.borrow_mut());
    Ok(())
}
pub fn decode_dep_graph < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , incremental_hashes_map : & IncrementalHashesMap , dep_graph_data : & [ u8 ] , work_products_data : & [ u8 ] ) -> Result < ( ) , String > { // Decode the list of work_products let mut work_product_decoder = Decoder :: new ( work_products_data , 0 ) ; let work_products = < Vec < SerializedWorkProduct > > :: decode ( & mut work_product_decoder ) ? ; // Deserialize the directory and dep-graph. let mut dep_graph_decoder = Decoder :: new ( dep_graph_data , 0 ) ; let prev_commandline_args_hash = u64 :: decode ( & mut dep_graph_decoder ) ? ; if prev_commandline_args_hash != tcx . sess . opts . dep_tracking_hash ( ) { if tcx . sess . opts . debugging_opts . incremental_info { println ! ( " \
 " ) ; } // We can't reuse the cache, purge it. debug ! ( " " ) ; for swp in work_products { delete_dirty_work_product ( tcx , swp ) ; } // No need to do any further work return Ok ( ( ) ) ; } let directory = DefIdDirectory :: decode ( & mut dep_graph_decoder ) ? ; let serialized_dep_graph = SerializedDepGraph :: decode ( & mut dep_graph_decoder ) ? ; let edge_map : FxHashMap < _ , _ > = serialized_dep_graph . edges . into_iter ( ) . map ( | s | ( s . source , s . targets ) ) . collect ( ) ; // Retrace the paths in the directory to find their current location (if any). let retraced = directory . retrace ( tcx ) ; // Compute the set of nodes from the old graph where some input // has changed or been removed. These are "raw" source nodes, // which means that they still use the original `DefPathIndex` // values from the encoding, rather than having been retraced to a // `DefId`. The reason for this is that this way we can include // nodes that have been removed (which no longer have a `DefId` in // the current compilation). let dirty_raw_nodes = initial_dirty_nodes ( tcx , incremental_hashes_map , & serialized_dep_graph . hashes , & retraced ) ; let dirty_raw_nodes = transitive_dirty_nodes ( & edge_map , dirty_raw_nodes ) ; // Recreate the edges in the graph that are still clean. let mut clean_work_products = FxHashSet ( ) ; let mut dirty_work_products = FxHashSet ( ) ; // incomplete; just used to suppress debug output let mut extra_edges = vec ! [ ] ; for ( source , targets ) in & edge_map { for target in targets { process_edges ( tcx , source , target , & edge_map , & directory , & retraced , & dirty_raw_nodes , & mut clean_work_products , & mut dirty_work_products , & mut extra_edges ) ; } } // Recreate bootstrap outputs, which are outputs that have no incoming edges (and hence cannot // be dirty). for bootstrap_output in & serialized_dep_graph . bootstrap_outputs { if let Some ( n ) = retraced . map ( bootstrap_output ) { if let DepNode :: WorkProduct ( ref wp ) = n { clean_work_products . insert ( wp . clone ( ) ) ; } tcx . dep_graph . with_task ( n , ( ) , ( ) , create_node ) ; fn create_node ( ( ) : ( ) , ( ) : ( ) ) { // just create the node with no inputs } } } // Subtle. Sometimes we have intermediate nodes that we can't recreate in the new graph. // This is pretty unusual but it arises in a scenario like this: // //     Hir(X) -> Foo(Y) -> Bar // // Note that the `Hir(Y)` is not an input to `Foo(Y)` -- this // almost never happens, but can happen in some obscure // scenarios. In that case, if `Y` is removed, then we can't // recreate `Foo(Y)` (the def-id `Y` no longer exists); what we do // then is to push the edge `Hir(X) -> Bar` onto `extra_edges` // (along with any other targets of `Foo(Y)`). We will then add // the edge from `Hir(X)` to `Bar` (or, if `Bar` itself cannot be // recreated, to the targets of `Bar`). while let Some ( ( source , target ) ) = extra_edges . pop ( ) { process_edges ( tcx , source , target , & edge_map , & directory , & retraced , & dirty_raw_nodes , & mut clean_work_products , & mut dirty_work_products , & mut extra_edges ) ; } // Add in work-products that are still clean, and delete those that are // dirty. reconcile_work_products ( tcx , work_products , & clean_work_products ) ; dirty_clean :: check_dirty_clean_annotations ( tcx , & dirty_raw_nodes , & retraced ) ; load_prev_metadata_hashes ( tcx , & retraced , & mut * incremental_hashes_map . prev_metadata_hashes . borrow_mut ( ) ) ; Ok ( ( ) ) }
Decode the dep graph and load the edges/nodes that are still clean
into `tcx.dep_graph`.
Decode the dep graph and load the edges / nodes that are still clean into ` tcx . dep_graph ` .
tcx
TyCtxt<'a, 'tcx, 'tcx>
incremental_hashes_map
&IncrementalHashesMap
dep_graph_data
&[u8]
work_products_data
&[u8]
tcx
TyCtxt<'a, 'tcx, 'tcx>
incremental_hashes_map
&IncrementalHashesMap
dep_graph_data
&[u8]
work_products_data
&[u8]