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,18 @@ 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 ) . and_then ( |alloc|
162+ alloc. get_bytes_mut ( tcx, buf, Size :: from_bytes ( count) )
163+ . map ( |buffer| handle. file . read ( buffer) . map ( |bytes| bytes as i64 ) )
164+ ) ;
165+ // Reinsert the file handle
166+ this. machine . file_handler . handles . insert ( fd, handle) ;
167+ this. consume_result ( bytes?)
168+ } )
174169 }
175170
176171 fn write (
@@ -191,13 +186,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
191186 let buf = this. force_ptr ( this. read_scalar ( buf_op) ?. not_undef ( ) ?) ?;
192187 let count = this. read_scalar ( count_op) ?. to_usize ( & * this. tcx ) ?;
193188
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-
197189 this. remove_handle_and ( fd, |mut handle, this| {
198- let bytes = handle. file . write ( & bytes) . map ( |bytes| bytes as i64 ) ;
190+ let bytes = this. memory ( ) . get ( buf. alloc_id ) . and_then ( |alloc| {
191+ alloc
192+ . get_bytes ( tcx, buf, Size :: from_bytes ( count) )
193+ . map ( |bytes| handle. file . write ( bytes) . map ( |bytes| bytes as i64 ) )
194+ } ) ;
199195 this. machine . file_handler . handles . insert ( fd, handle) ;
200- this. consume_result ( bytes)
196+ this. consume_result ( bytes? )
201197 } )
202198 }
203199
@@ -251,7 +247,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
251247 ///
252248 /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
253249 /// 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 > {
250+ fn consume_result < T : From < i32 > > (
251+ & mut self ,
252+ result : std:: io:: Result < T > ,
253+ ) -> InterpResult < ' tcx , T > {
255254 match result {
256255 Ok ( ok) => Ok ( ok) ,
257256 Err ( e) => {
0 commit comments