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:: * ;
@@ -41,6 +41,7 @@ use rustc_span::symbol::{sym, Symbol};
41
41
use rustc_span:: { self , ExternalSource , FileName , SourceFile , Span , SpanData , SyntaxContext } ;
42
42
use std:: borrow:: Borrow ;
43
43
use std:: collections:: hash_map:: Entry ;
44
+ use std:: fs:: File ;
44
45
use std:: hash:: Hash ;
45
46
use std:: io:: { Read , Seek , Write } ;
46
47
use std:: num:: NonZeroUsize ;
@@ -2251,22 +2252,17 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
2251
2252
// culminating in the `CrateRoot` which points to all of it.
2252
2253
let root = ecx. encode_crate_root ( ) ;
2253
2254
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
+ }
2267
2261
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
+ }
2270
2266
2271
2267
// Record metadata size for self-profiling
2272
2268
tcx. prof . artifact_size (
@@ -2276,6 +2272,20 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
2276
2272
) ;
2277
2273
}
2278
2274
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
+
2279
2289
pub fn provide ( providers : & mut Providers ) {
2280
2290
* providers = Providers {
2281
2291
doc_link_resolutions : |tcx, def_id| {
0 commit comments