|
1 | | -use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile}; |
| 1 | +use crate::errors::{FailCreateFileEncoder, FailWriteFile}; |
2 | 2 | use crate::rmeta::def_path_hash_map::DefPathHashMapRef; |
3 | 3 | use crate::rmeta::table::TableBuilder; |
4 | 4 | use crate::rmeta::*; |
@@ -42,6 +42,7 @@ use rustc_span::symbol::{sym, Symbol}; |
42 | 42 | use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SpanData, SyntaxContext}; |
43 | 43 | use std::borrow::Borrow; |
44 | 44 | use std::collections::hash_map::Entry; |
| 45 | +use std::fs::File; |
45 | 46 | use std::hash::Hash; |
46 | 47 | use std::io::{Read, Seek, Write}; |
47 | 48 | use std::num::NonZeroUsize; |
@@ -2255,25 +2256,34 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { |
2255 | 2256 | // culminating in the `CrateRoot` which points to all of it. |
2256 | 2257 | let root = ecx.encode_crate_root(); |
2257 | 2258 |
|
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 | +} |
2259 | 2274 |
|
2260 | | - let mut file = ecx.opaque.file(); |
| 2275 | +fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> { |
2261 | 2276 | // We will return to this position after writing the root position. |
2262 | 2277 | let pos_before_seek = file.stream_position().unwrap(); |
2263 | 2278 |
|
2264 | 2279 | // Encode the root position. |
2265 | 2280 | 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])?; |
2271 | 2283 |
|
2272 | 2284 | // 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(()) |
2277 | 2287 | } |
2278 | 2288 |
|
2279 | 2289 | pub fn provide(providers: &mut Providers) { |
|
0 commit comments