11use std:: collections:: HashMap ;
2- use std:: fs:: { File , OpenOptions } ;
3- use std:: io:: { Read , Write } ;
2+ use std:: fs:: { File , OpenOptions } ;
3+ use std:: io:: { Read , Write } ;
44
55use rustc:: ty:: layout:: Size ;
66
@@ -130,10 +130,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
130130
131131 let fd = this. read_scalar ( fd_op) ?. to_i32 ( ) ?;
132132
133- this. remove_handle_and (
134- fd,
135- |handle, this| this. consume_result ( handle. file . sync_all ( ) . map ( |_| 0i32 ) ) ,
136- )
133+ this. remove_handle_and ( fd, |handle, this| {
134+ this. consume_result ( handle. file . sync_all ( ) . map ( |_| 0i32 ) )
135+ } )
137136 }
138137
139138 fn read (
@@ -155,22 +154,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
155154 let count = this. read_scalar ( count_op) ?. to_usize ( & * this. tcx ) ?;
156155
157156 // Remove the file handle to avoid borrowing issues
158- this. remove_handle_and (
159- fd,
160- |mut handle, this| {
161- let bytes = handle
162- . file
163- . read ( this. memory_mut ( ) . get_mut ( buf. alloc_id ) ?. get_bytes_mut (
164- tcx,
165- buf,
166- Size :: from_bytes ( count) ,
167- ) ?)
168- . map ( |bytes| bytes as i64 ) ;
169- // Reinsert the file handle
170- this. machine . file_handler . handles . insert ( fd, handle) ;
171- this. consume_result ( bytes)
172- } ,
173- )
157+ this. remove_handle_and ( fd, |mut handle, this| {
158+ // Don't use `?` to avoid returning before reinserting the handle
159+ let bytes = this
160+ . memory_mut ( )
161+ . get_mut ( buf. alloc_id ) ?
162+ . get_bytes_mut ( tcx, buf, Size :: from_bytes ( count) )
163+ . map ( |buffer| handle. file . read ( buffer) . map ( |bytes| bytes as i64 ) ) ;
164+ // Reinsert the file handle
165+ this. machine . file_handler . handles . insert ( fd, handle) ;
166+ this. consume_result ( bytes?)
167+ } )
174168 }
175169
176170 fn write (
@@ -191,13 +185,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
191185 let buf = this. force_ptr ( this. read_scalar ( buf_op) ?. not_undef ( ) ?) ?;
192186 let count = this. read_scalar ( count_op) ?. to_usize ( & * this. tcx ) ?;
193187
194- // `to_vec` is needed to avoid borrowing issues when writing to the file.
195- let bytes = this. memory ( ) . get ( buf. alloc_id ) ?. get_bytes ( tcx, buf, Size :: from_bytes ( count) ) ?. to_vec ( ) ;
196-
197188 this. remove_handle_and ( fd, |mut handle, this| {
198- let bytes = handle. file . write ( & bytes) . map ( |bytes| bytes as i64 ) ;
189+ let bytes = this. memory ( ) . get ( buf. alloc_id ) . and_then ( |alloc| {
190+ alloc
191+ . get_bytes ( tcx, buf, Size :: from_bytes ( count) )
192+ . map ( |bytes| handle. file . write ( bytes) . map ( |bytes| bytes as i64 ) )
193+ } ) ;
199194 this. machine . file_handler . handles . insert ( fd, handle) ;
200- this. consume_result ( bytes)
195+ this. consume_result ( bytes? )
201196 } )
202197 }
203198
@@ -251,7 +246,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
251246 ///
252247 /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
253248 /// functions return different integer types (like `read`, that returns an `i64`)
254- fn consume_result < T : From < i32 > > ( & mut self , result : std:: io:: Result < T > ) -> InterpResult < ' tcx , T > {
249+ fn consume_result < T : From < i32 > > (
250+ & mut self ,
251+ result : std:: io:: Result < T > ,
252+ ) -> InterpResult < ' tcx , T > {
255253 match result {
256254 Ok ( ok) => Ok ( ok) ,
257255 Err ( e) => {
0 commit comments