Skip to content

Commit 3dbb4da

Browse files
committed
Auto merge of rust-lang#117301 - saethlin:finish-rmeta-encoding, r=WaffleLapkin
Call FileEncoder::finish in rmeta encoding Fixes rust-lang#117254 The bug here was that rmeta encoding never called FileEncoder::finish. Now it does. Most of the changes here are needed to support that, since rmeta encoding wants to finish _then_ access the File in the encoder, so finish can't move out. I tried adding a `cfg(debug_assertions)` exploding Drop impl to FileEncoder that checked for finish being called before dropping, but fatal errors cause unwinding so this isn't really possible. If we encounter a fatal error with a dirty FileEncoder, the Drop impl ICEs even though the implementation is correct. If we try to paper over that by wrapping FileEncoder in ManuallyDrop then that just erases the fact that Drop automatically checks that we call finish on all paths. I also changed the name of DepGraph::encode to DepGraph::finish_encoding, because that's what it does and it makes the fact that it is the path to FileEncoder::finish less confusing. r? `@WaffleLapkin`
2 parents 0b8a61b + fbaa24e commit 3dbb4da

File tree

14 files changed

+82
-41
lines changed

14 files changed

+82
-41
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4038,6 +4038,7 @@ dependencies = [
40384038
"rustc_query_impl",
40394039
"rustc_query_system",
40404040
"rustc_resolve",
4041+
"rustc_serialize",
40414042
"rustc_session",
40424043
"rustc_span",
40434044
"rustc_symbol_mangling",

compiler/rustc_codegen_ssa/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ impl CodegenResults {
224224
encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes());
225225
encoder.emit_str(sess.cfg_version);
226226
Encodable::encode(codegen_results, &mut encoder);
227-
encoder.finish()
227+
encoder.finish().map_err(|(_path, err)| err)
228228
}
229229

230230
pub fn deserialize_rlink(sess: &Session, data: Vec<u8>) -> Result<Self, CodegenErrors> {

compiler/rustc_incremental/src/persist/file_format.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ where
8080
);
8181
debug!("save: data written to disk successfully");
8282
}
83-
Err(err) => {
84-
sess.emit_err(errors::WriteNew { name, path: path_buf, err });
83+
Err((path, err)) => {
84+
sess.emit_err(errors::WriteNew { name, path, err });
8585
}
8686
}
8787
}

compiler/rustc_incremental/src/persist/save.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) {
5050
join(
5151
move || {
5252
sess.time("incr_comp_persist_dep_graph", || {
53-
if let Err(err) = tcx.dep_graph.encode(&tcx.sess.prof) {
54-
sess.emit_err(errors::WriteDepGraph { path: &staging_dep_graph_path, err });
55-
}
5653
if let Err(err) = fs::rename(&staging_dep_graph_path, &dep_graph_path) {
5754
sess.emit_err(errors::MoveDepGraph {
5855
from: &staging_dep_graph_path,

compiler/rustc_interface/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ rustc_privacy = { path = "../rustc_privacy" }
4040
rustc_query_impl = { path = "../rustc_query_impl" }
4141
rustc_query_system = { path = "../rustc_query_system" }
4242
rustc_resolve = { path = "../rustc_resolve" }
43+
rustc_serialize = { path = "../rustc_serialize" }
4344
rustc_session = { path = "../rustc_session" }
4445
rustc_span = { path = "../rustc_span" }
4546
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }

compiler/rustc_interface/src/queries.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation};
22
use crate::interface::{Compiler, Result};
3-
use crate::{passes, util};
3+
use crate::{errors, passes, util};
44

55
use rustc_ast as ast;
66
use rustc_codegen_ssa::traits::CodegenBackend;
@@ -15,6 +15,7 @@ use rustc_metadata::creader::CStore;
1515
use rustc_middle::arena::Arena;
1616
use rustc_middle::dep_graph::DepGraph;
1717
use rustc_middle::ty::{GlobalCtxt, TyCtxt};
18+
use rustc_serialize::opaque::FileEncodeResult;
1819
use rustc_session::config::{self, CrateType, OutputFilenames, OutputType};
1920
use rustc_session::cstore::Untracked;
2021
use rustc_session::output::find_crate_name;
@@ -102,6 +103,10 @@ impl<'tcx> Queries<'tcx> {
102103
}
103104
}
104105

106+
pub fn finish(&self) -> FileEncodeResult {
107+
if let Some(gcx) = self.gcx_cell.get() { gcx.finish() } else { Ok(0) }
108+
}
109+
105110
pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> {
106111
self.parse.compute(|| {
107112
passes::parse(&self.compiler.sess).map_err(|mut parse_error| parse_error.emit())
@@ -317,6 +322,9 @@ impl Compiler {
317322
// The timer's lifetime spans the dropping of `queries`, which contains
318323
// the global context.
319324
_timer = Some(self.sess.timer("free_global_ctxt"));
325+
if let Err((path, error)) = queries.finish() {
326+
self.sess.emit_err(errors::FailedWritingFile { path: &path, error });
327+
}
320328

321329
ret
322330
}

compiler/rustc_metadata/messages.ftl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,8 @@ metadata_extern_location_not_file =
6363
metadata_fail_create_file_encoder =
6464
failed to create file encoder: {$err}
6565
66-
metadata_fail_seek_file =
67-
failed to seek the file: {$err}
68-
6966
metadata_fail_write_file =
70-
failed to write to the file: {$err}
67+
failed to write to `{$path}`: {$err}
7168
7269
metadata_failed_copy_to_stdout =
7370
failed to copy {$filename} to stdout: {$err}

compiler/rustc_metadata/src/errors.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -307,15 +307,10 @@ pub struct FailCreateFileEncoder {
307307
pub err: Error,
308308
}
309309

310-
#[derive(Diagnostic)]
311-
#[diag(metadata_fail_seek_file)]
312-
pub struct FailSeekFile {
313-
pub err: Error,
314-
}
315-
316310
#[derive(Diagnostic)]
317311
#[diag(metadata_fail_write_file)]
318-
pub struct FailWriteFile {
312+
pub struct FailWriteFile<'a> {
313+
pub path: &'a Path,
319314
pub err: Error,
320315
}
321316

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile};
1+
use crate::errors::{FailCreateFileEncoder, FailWriteFile};
22
use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
33
use crate::rmeta::table::TableBuilder;
44
use crate::rmeta::*;
@@ -42,6 +42,7 @@ use rustc_span::symbol::{sym, Symbol};
4242
use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SpanData, SyntaxContext};
4343
use std::borrow::Borrow;
4444
use std::collections::hash_map::Entry;
45+
use std::fs::File;
4546
use std::hash::Hash;
4647
use std::io::{Read, Seek, Write};
4748
use std::num::NonZeroUsize;
@@ -2255,25 +2256,34 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
22552256
// culminating in the `CrateRoot` which points to all of it.
22562257
let root = ecx.encode_crate_root();
22572258

2258-
ecx.opaque.flush();
2259+
// Make sure we report any errors from writing to the file.
2260+
// If we forget this, compilation can succeed with an incomplete rmeta file,
2261+
// causing an ICE when the rmeta file is read by another compilation.
2262+
if let Err((path, err)) = ecx.opaque.finish() {
2263+
tcx.sess.emit_err(FailWriteFile { path: &path, err });
2264+
}
2265+
2266+
let file = ecx.opaque.file();
2267+
if let Err(err) = encode_root_position(file, root.position.get()) {
2268+
tcx.sess.emit_err(FailWriteFile { path: ecx.opaque.path(), err });
2269+
}
2270+
2271+
// Record metadata size for self-profiling
2272+
tcx.prof.artifact_size("crate_metadata", "crate_metadata", file.metadata().unwrap().len());
2273+
}
22592274

2260-
let mut file = ecx.opaque.file();
2275+
fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> {
22612276
// We will return to this position after writing the root position.
22622277
let pos_before_seek = file.stream_position().unwrap();
22632278

22642279
// Encode the root position.
22652280
let header = METADATA_HEADER.len();
2266-
file.seek(std::io::SeekFrom::Start(header as u64))
2267-
.unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err }));
2268-
let pos = root.position.get();
2269-
file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])
2270-
.unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err }));
2281+
file.seek(std::io::SeekFrom::Start(header as u64))?;
2282+
file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])?;
22712283

22722284
// Return to the position where we are before writing the root position.
2273-
file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap();
2274-
2275-
// Record metadata size for self-profiling
2276-
tcx.prof.artifact_size("crate_metadata", "crate_metadata", file.metadata().unwrap().len());
2285+
file.seek(std::io::SeekFrom::Start(pos_before_seek))?;
2286+
Ok(())
22772287
}
22782288

22792289
pub fn provide(providers: &mut Providers) {

compiler/rustc_middle/src/query/on_disk_cache.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ use rustc_span::source_map::{SourceMap, StableSourceFileId};
2525
use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, RelativeBytePos, SourceFile, Span};
2626
use rustc_span::{CachingSourceMapView, Symbol};
2727
use std::collections::hash_map::Entry;
28-
use std::io;
2928
use std::mem;
3029

3130
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
@@ -862,7 +861,7 @@ impl<'a, 'tcx> CacheEncoder<'a, 'tcx> {
862861
}
863862

864863
#[inline]
865-
fn finish(self) -> Result<usize, io::Error> {
864+
fn finish(mut self) -> FileEncodeResult {
866865
self.encoder.finish()
867866
}
868867
}

0 commit comments

Comments
 (0)