Auto merge of #117301 - saethlin:finish-rmeta-encoding, r=WaffleLapkin
Call FileEncoder::finish in rmeta encoding Fixes https://github.com/rust-lang/rust/issues/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`
This commit is contained in:
commit
3dbb4da042
14 changed files with 82 additions and 41 deletions
|
@ -63,11 +63,8 @@ metadata_extern_location_not_file =
|
|||
metadata_fail_create_file_encoder =
|
||||
failed to create file encoder: {$err}
|
||||
|
||||
metadata_fail_seek_file =
|
||||
failed to seek the file: {$err}
|
||||
|
||||
metadata_fail_write_file =
|
||||
failed to write to the file: {$err}
|
||||
failed to write to `{$path}`: {$err}
|
||||
|
||||
metadata_failed_copy_to_stdout =
|
||||
failed to copy {$filename} to stdout: {$err}
|
||||
|
|
|
@ -307,15 +307,10 @@ pub struct FailCreateFileEncoder {
|
|||
pub err: Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_fail_seek_file)]
|
||||
pub struct FailSeekFile {
|
||||
pub err: Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_fail_write_file)]
|
||||
pub struct FailWriteFile {
|
||||
pub struct FailWriteFile<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: Error,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile};
|
||||
use crate::errors::{FailCreateFileEncoder, FailWriteFile};
|
||||
use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
|
||||
use crate::rmeta::table::TableBuilder;
|
||||
use crate::rmeta::*;
|
||||
|
@ -42,6 +42,7 @@ use rustc_span::symbol::{sym, Symbol};
|
|||
use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SpanData, SyntaxContext};
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::fs::File;
|
||||
use std::hash::Hash;
|
||||
use std::io::{Read, Seek, Write};
|
||||
use std::num::NonZeroUsize;
|
||||
|
@ -2255,25 +2256,34 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
|
|||
// culminating in the `CrateRoot` which points to all of it.
|
||||
let root = ecx.encode_crate_root();
|
||||
|
||||
ecx.opaque.flush();
|
||||
// Make sure we report any errors from writing to the file.
|
||||
// If we forget this, compilation can succeed with an incomplete rmeta file,
|
||||
// causing an ICE when the rmeta file is read by another compilation.
|
||||
if let Err((path, err)) = ecx.opaque.finish() {
|
||||
tcx.sess.emit_err(FailWriteFile { path: &path, err });
|
||||
}
|
||||
|
||||
let mut file = ecx.opaque.file();
|
||||
let file = ecx.opaque.file();
|
||||
if let Err(err) = encode_root_position(file, root.position.get()) {
|
||||
tcx.sess.emit_err(FailWriteFile { path: ecx.opaque.path(), err });
|
||||
}
|
||||
|
||||
// Record metadata size for self-profiling
|
||||
tcx.prof.artifact_size("crate_metadata", "crate_metadata", file.metadata().unwrap().len());
|
||||
}
|
||||
|
||||
fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> {
|
||||
// We will return to this position after writing the root position.
|
||||
let pos_before_seek = file.stream_position().unwrap();
|
||||
|
||||
// Encode the root position.
|
||||
let header = METADATA_HEADER.len();
|
||||
file.seek(std::io::SeekFrom::Start(header as u64))
|
||||
.unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err }));
|
||||
let pos = root.position.get();
|
||||
file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])
|
||||
.unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err }));
|
||||
file.seek(std::io::SeekFrom::Start(header as u64))?;
|
||||
file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])?;
|
||||
|
||||
// Return to the position where we are before writing the root position.
|
||||
file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap();
|
||||
|
||||
// Record metadata size for self-profiling
|
||||
tcx.prof.artifact_size("crate_metadata", "crate_metadata", file.metadata().unwrap().len());
|
||||
file.seek(std::io::SeekFrom::Start(pos_before_seek))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue