rustc_incremental/persist/
save.rs1use std::fs;
2use std::sync::Arc;
3
4use rustc_data_structures::fx::FxIndexMap;
5use rustc_data_structures::sync::join;
6use rustc_middle::dep_graph::{
7 DepGraph, SerializedDepGraph, WorkProduct, WorkProductId, WorkProductMap,
8};
9use rustc_middle::ty::TyCtxt;
10use rustc_serialize::Encodable as RustcEncodable;
11use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
12use rustc_session::Session;
13use tracing::debug;
14
15use super::data::*;
16use super::fs::*;
17use super::{dirty_clean, file_format, work_product};
18use crate::assert_dep_graph::assert_dep_graph;
19use crate::errors;
20
21pub(crate) fn save_dep_graph(tcx: TyCtxt<'_>) {
29 debug!("save_dep_graph()");
30 tcx.dep_graph.with_ignore(|| {
31 let sess = tcx.sess;
32 if sess.opts.incremental.is_none() {
33 return;
34 }
35 if sess.dcx().has_errors_or_delayed_bugs().is_some() {
37 return;
38 }
39
40 let query_cache_path = query_cache_path(sess);
41 let dep_graph_path = dep_graph_path(sess);
42 let staging_dep_graph_path = staging_dep_graph_path(sess);
43
44 sess.time("assert_dep_graph", || assert_dep_graph(tcx));
45 sess.time("check_dirty_clean", || dirty_clean::check_dirty_clean_annotations(tcx));
46
47 if sess.opts.unstable_opts.incremental_info {
48 tcx.dep_graph.print_incremental_info()
49 }
50
51 join(
52 move || {
53 sess.time("incr_comp_persist_dep_graph", || {
54 if let Err(err) = fs::rename(&staging_dep_graph_path, &dep_graph_path) {
55 sess.dcx().emit_err(errors::MoveDepGraph {
56 from: &staging_dep_graph_path,
57 to: &dep_graph_path,
58 err,
59 });
60 }
61 });
62 },
63 move || {
64 sess.time("incr_comp_persist_result_cache", || {
67 if let Some(odc) = &tcx.query_system.on_disk_cache {
69 odc.drop_serialized_data(tcx);
70 }
71
72 file_format::save_in(sess, query_cache_path, "query cache", |e| {
73 encode_query_cache(tcx, e)
74 });
75 });
76 },
77 );
78 })
79}
80
81pub fn save_work_product_index(
83 sess: &Session,
84 dep_graph: &DepGraph,
85 new_work_products: FxIndexMap<WorkProductId, WorkProduct>,
86) {
87 if sess.opts.incremental.is_none() {
88 return;
89 }
90 if sess.dcx().has_errors().is_some() {
92 return;
93 }
94
95 debug!("save_work_product_index()");
96 dep_graph.assert_ignored();
97 let path = work_products_path(sess);
98 file_format::save_in(sess, path, "work product index", |mut e| {
99 encode_work_product_index(&new_work_products, &mut e);
100 e.finish()
101 });
102
103 let previous_work_products = dep_graph.previous_work_products();
107 for (id, wp) in previous_work_products.to_sorted_stable_ord() {
108 if !new_work_products.contains_key(id) {
109 work_product::delete_workproduct_files(sess, wp);
110 debug_assert!(
111 !wp.saved_files.items().all(|(_, path)| in_incr_comp_dir_sess(sess, path).exists())
112 );
113 }
114 }
115
116 debug_assert!({
118 new_work_products.iter().all(|(_, wp)| {
119 wp.saved_files.items().all(|(_, path)| in_incr_comp_dir_sess(sess, path).exists())
120 })
121 });
122}
123
124fn encode_work_product_index(
125 work_products: &FxIndexMap<WorkProductId, WorkProduct>,
126 encoder: &mut FileEncoder,
127) {
128 let serialized_products: Vec<_> = work_products
129 .iter()
130 .map(|(id, work_product)| SerializedWorkProduct {
131 id: *id,
132 work_product: work_product.clone(),
133 })
134 .collect();
135
136 serialized_products.encode(encoder)
137}
138
139fn encode_query_cache(tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult {
140 tcx.sess.time("incr_comp_serialize_result_cache", || tcx.serialize_query_result_cache(encoder))
141}
142
143pub(crate) fn build_dep_graph(
150 sess: &Session,
151 prev_graph: Arc<SerializedDepGraph>,
152 prev_work_products: WorkProductMap,
153) -> Option<DepGraph> {
154 if sess.opts.incremental.is_none() {
155 return None;
157 }
158
159 let path_buf = staging_dep_graph_path(sess);
161
162 let mut encoder = match FileEncoder::new(&path_buf) {
163 Ok(encoder) => encoder,
164 Err(err) => {
165 sess.dcx().emit_err(errors::CreateDepGraph { path: &path_buf, err });
166 return None;
167 }
168 };
169
170 file_format::write_file_header(&mut encoder, sess);
171
172 sess.opts.dep_tracking_hash(false).encode(&mut encoder);
174
175 Some(DepGraph::new(
176 &sess.prof,
177 prev_graph,
178 prev_work_products,
179 encoder,
180 sess.opts.unstable_opts.query_dep_graph,
181 sess.opts.unstable_opts.incremental_info,
182 ))
183}