@@ -7,7 +7,6 @@ use std::collections::BTreeMap;
77use std:: io:: { self , ErrorKind , IsTerminal , Read , SeekFrom , Write } ;
88use std:: rc:: Rc ;
99
10- use rustc_middle:: ty:: TyCtxt ;
1110use rustc_target:: abi:: Size ;
1211
1312use crate :: shims:: unix:: * ;
@@ -22,7 +21,7 @@ pub trait FileDescription: std::fmt::Debug + Any {
2221 & mut self ,
2322 _communicate_allowed : bool ,
2423 _bytes : & mut [ u8 ] ,
25- _tcx : TyCtxt < ' tcx > ,
24+ _ecx : & mut MiriInterpCx < ' _ , ' tcx > ,
2625 ) -> InterpResult < ' tcx , io:: Result < usize > > {
2726 throw_unsup_format ! ( "cannot read from {}" , self . name( ) ) ;
2827 }
@@ -32,7 +31,7 @@ pub trait FileDescription: std::fmt::Debug + Any {
3231 & mut self ,
3332 _communicate_allowed : bool ,
3433 _bytes : & [ u8 ] ,
35- _tcx : TyCtxt < ' tcx > ,
34+ _ecx : & mut MiriInterpCx < ' _ , ' tcx > ,
3635 ) -> InterpResult < ' tcx , io:: Result < usize > > {
3736 throw_unsup_format ! ( "cannot write to {}" , self . name( ) ) ;
3837 }
@@ -82,7 +81,7 @@ impl FileDescription for io::Stdin {
8281 & mut self ,
8382 communicate_allowed : bool ,
8483 bytes : & mut [ u8 ] ,
85- _tcx : TyCtxt < ' tcx > ,
84+ _ecx : & mut MiriInterpCx < ' _ , ' tcx > ,
8685 ) -> InterpResult < ' tcx , io:: Result < usize > > {
8786 if !communicate_allowed {
8887 // We want isolation mode to be deterministic, so we have to disallow all reads, even stdin.
@@ -105,7 +104,7 @@ impl FileDescription for io::Stdout {
105104 & mut self ,
106105 _communicate_allowed : bool ,
107106 bytes : & [ u8 ] ,
108- _tcx : TyCtxt < ' tcx > ,
107+ _ecx : & mut MiriInterpCx < ' _ , ' tcx > ,
109108 ) -> InterpResult < ' tcx , io:: Result < usize > > {
110109 // We allow writing to stderr even with isolation enabled.
111110 let result = Write :: write ( self , bytes) ;
@@ -133,7 +132,7 @@ impl FileDescription for io::Stderr {
133132 & mut self ,
134133 _communicate_allowed : bool ,
135134 bytes : & [ u8 ] ,
136- _tcx : TyCtxt < ' tcx > ,
135+ _ecx : & mut MiriInterpCx < ' _ , ' tcx > ,
137136 ) -> InterpResult < ' tcx , io:: Result < usize > > {
138137 // We allow writing to stderr even with isolation enabled.
139138 // No need to flush, stderr is not buffered.
@@ -158,7 +157,7 @@ impl FileDescription for NullOutput {
158157 & mut self ,
159158 _communicate_allowed : bool ,
160159 bytes : & [ u8 ] ,
161- _tcx : TyCtxt < ' tcx > ,
160+ _ecx : & mut MiriInterpCx < ' _ , ' tcx > ,
162161 ) -> InterpResult < ' tcx , io:: Result < usize > > {
163162 // We just don't write anything, but report to the user that we did.
164163 Ok ( Ok ( bytes. len ( ) ) )
@@ -173,6 +172,14 @@ impl FileDescriptor {
173172 FileDescriptor ( Rc :: new ( RefCell :: new ( Box :: new ( fd) ) ) )
174173 }
175174
175+ pub fn borrow ( & self ) -> Ref < ' _ , dyn FileDescription > {
176+ Ref :: map ( self . 0 . borrow ( ) , |fd| fd. as_ref ( ) )
177+ }
178+
179+ pub fn borrow_mut ( & self ) -> RefMut < ' _ , dyn FileDescription > {
180+ RefMut :: map ( self . 0 . borrow_mut ( ) , |fd| fd. as_mut ( ) )
181+ }
182+
176183 pub fn close < ' ctx > ( self , communicate_allowed : bool ) -> InterpResult < ' ctx , io:: Result < ( ) > > {
177184 // Destroy this `Rc` using `into_inner` so we can call `close` instead of
178185 // implicitly running the destructor of the file description.
@@ -242,12 +249,12 @@ impl FdTable {
242249
243250 pub fn get ( & self , fd : i32 ) -> Option < Ref < ' _ , dyn FileDescription > > {
244251 let fd = self . fds . get ( & fd) ?;
245- Some ( Ref :: map ( fd. 0 . borrow ( ) , |fd| fd . as_ref ( ) ) )
252+ Some ( fd. borrow ( ) )
246253 }
247254
248255 pub fn get_mut ( & self , fd : i32 ) -> Option < RefMut < ' _ , dyn FileDescription > > {
249256 let fd = self . fds . get ( & fd) ?;
250- Some ( RefMut :: map ( fd. 0 . borrow_mut ( ) , |fd| fd . as_mut ( ) ) )
257+ Some ( fd. borrow_mut ( ) )
251258 }
252259
253260 pub fn dup ( & self , fd : i32 ) -> Option < FileDescriptor > {
@@ -370,7 +377,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
370377 . min ( u64:: try_from ( isize:: MAX ) . unwrap ( ) ) ;
371378 let communicate = this. machine . communicate ( ) ;
372379
373- let Some ( mut file_descriptor) = this. machine . fds . get_mut ( fd) else {
380+ // We temporarily dup the FD to be able to retain mutable access to `this`.
381+ let Some ( file_descriptor) = this. machine . fds . dup ( fd) else {
374382 trace ! ( "read: FD not found" ) ;
375383 return this. fd_not_found ( ) ;
376384 } ;
@@ -383,7 +391,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
383391 // `File::read` never returns a value larger than `count`,
384392 // so this cannot fail.
385393 let result = file_descriptor
386- . read ( communicate, & mut bytes, * this. tcx ) ?
394+ . borrow_mut ( )
395+ . read ( communicate, & mut bytes, this) ?
387396 . map ( |c| i64:: try_from ( c) . unwrap ( ) ) ;
388397 drop ( file_descriptor) ;
389398
@@ -421,12 +430,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
421430 let communicate = this. machine . communicate ( ) ;
422431
423432 let bytes = this. read_bytes_ptr_strip_provenance ( buf, Size :: from_bytes ( count) ) ?. to_owned ( ) ;
424- let Some ( mut file_descriptor) = this. machine . fds . get_mut ( fd) else {
433+ // We temporarily dup the FD to be able to retain mutable access to `this`.
434+ let Some ( file_descriptor) = this. machine . fds . dup ( fd) else {
425435 return this. fd_not_found ( ) ;
426436 } ;
427437
428438 let result = file_descriptor
429- . write ( communicate, & bytes, * this. tcx ) ?
439+ . borrow_mut ( )
440+ . write ( communicate, & bytes, this) ?
430441 . map ( |c| i64:: try_from ( c) . unwrap ( ) ) ;
431442 drop ( file_descriptor) ;
432443
0 commit comments