1- use crate :: errors:: { FailCreateFileEncoder , FailSeekFile , FailWriteFile } ;
1+ use crate :: errors:: { FailCreateFileEncoder , FailWriteFile } ;
22use crate :: rmeta:: def_path_hash_map:: DefPathHashMapRef ;
33use crate :: rmeta:: table:: TableBuilder ;
44use crate :: rmeta:: * ;
@@ -41,6 +41,7 @@ use rustc_span::symbol::{sym, Symbol};
4141use rustc_span:: { self , ExternalSource , FileName , SourceFile , Span , SpanData , SyntaxContext } ;
4242use std:: borrow:: Borrow ;
4343use std:: collections:: hash_map:: Entry ;
44+ use std:: fs:: File ;
4445use std:: hash:: Hash ;
4546use std:: io:: { Read , Seek , Write } ;
4647use std:: num:: NonZeroUsize ;
@@ -2251,22 +2252,17 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
22512252 // culminating in the `CrateRoot` which points to all of it.
22522253 let root = ecx. encode_crate_root ( ) ;
22532254
2254- ecx. opaque . flush ( ) ;
2255-
2256- let mut file = ecx. opaque . file ( ) ;
2257- // We will return to this position after writing the root position.
2258- let pos_before_seek = file. stream_position ( ) . unwrap ( ) ;
2259-
2260- // Encode the root position.
2261- let header = METADATA_HEADER . len ( ) ;
2262- file. seek ( std:: io:: SeekFrom :: Start ( header as u64 ) )
2263- . unwrap_or_else ( |err| tcx. sess . emit_fatal ( FailSeekFile { err } ) ) ;
2264- let pos = root. position . get ( ) ;
2265- file. write_all ( & [ ( pos >> 24 ) as u8 , ( pos >> 16 ) as u8 , ( pos >> 8 ) as u8 , ( pos >> 0 ) as u8 ] )
2266- . unwrap_or_else ( |err| tcx. sess . emit_fatal ( FailWriteFile { err } ) ) ;
2255+ // Make sure we report any errors from writing to the file.
2256+ // If we forget this, compilation can succeed with an incomplete rmeta file,
2257+ // causing an ICE when the rmeta file is read by another compilation.
2258+ if let Err ( ( path, err) ) = ecx. opaque . finish ( ) {
2259+ tcx. sess . emit_err ( FailWriteFile { path : & path, err } ) ;
2260+ }
22672261
2268- // Return to the position where we are before writing the root position.
2269- file. seek ( std:: io:: SeekFrom :: Start ( pos_before_seek) ) . unwrap ( ) ;
2262+ let file = ecx. opaque . file ( ) ;
2263+ if let Err ( err) = encode_root_position ( file, root. position . get ( ) ) {
2264+ tcx. sess . emit_err ( FailWriteFile { path : ecx. opaque . path ( ) , err } ) ;
2265+ }
22702266
22712267 // Record metadata size for self-profiling
22722268 tcx. prof . artifact_size (
@@ -2276,6 +2272,20 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
22762272 ) ;
22772273}
22782274
2275+ fn encode_root_position ( mut file : & File , pos : usize ) -> Result < ( ) , std:: io:: Error > {
2276+ // We will return to this position after writing the root position.
2277+ let pos_before_seek = file. stream_position ( ) . unwrap ( ) ;
2278+
2279+ // Encode the root position.
2280+ let header = METADATA_HEADER . len ( ) ;
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 ] ) ?;
2283+
2284+ // Return to the position where we are before writing the root position.
2285+ file. seek ( std:: io:: SeekFrom :: Start ( pos_before_seek) ) ?;
2286+ Ok ( ( ) )
2287+ }
2288+
22792289pub fn provide ( providers : & mut Providers ) {
22802290 * providers = Providers {
22812291 doc_link_resolutions : |tcx, def_id| {
0 commit comments