Auto merge of #1509 - samrat:fd-trait-fixes, r=RalfJung

Remove lifetime from FileDescriptor trait

Also:
- Type annotate `handles` declaration, instead of annotating every insert.
- Add note about flush being unnecessary when writing to stderr

Addresses comments in #1495 and #1497
This commit is contained in:
bors 2020-08-13 11:57:46 +00:00
commit 99a57a3f9e
2 changed files with 35 additions and 34 deletions

View File

@ -249,7 +249,7 @@ pub struct Evaluator<'mir, 'tcx> {
/// Whether to enforce the validity invariant.
pub(crate) validate: bool,
pub(crate) file_handler: shims::posix::FileHandler<'tcx>,
pub(crate) file_handler: shims::posix::FileHandler,
pub(crate) dir_handler: shims::posix::DirHandler,
/// The temporary used for storing the argument of

View File

@ -22,41 +22,41 @@ struct FileHandle {
writable: bool,
}
trait FileDescriptor<'tcx> : std::fmt::Debug {
fn as_file_handle(&self) -> InterpResult<'tcx, &FileHandle>;
trait FileDescriptor : std::fmt::Debug {
fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle>;
fn read(&mut self, communicate_allowed: bool, bytes: &mut [u8]) -> InterpResult<'tcx, io::Result<usize>>;
fn write(&mut self, communicate_allowed: bool, bytes: &[u8]) -> InterpResult<'tcx, io::Result<usize>>;
fn seek(&mut self, communicate_allowed: bool, offset: SeekFrom) -> InterpResult<'tcx, io::Result<u64>>;
fn read<'tcx>(&mut self, communicate_allowed: bool, bytes: &mut [u8]) -> InterpResult<'tcx, io::Result<usize>>;
fn write<'tcx>(&mut self, communicate_allowed: bool, bytes: &[u8]) -> InterpResult<'tcx, io::Result<usize>>;
fn seek<'tcx>(&mut self, communicate_allowed: bool, offset: SeekFrom) -> InterpResult<'tcx, io::Result<u64>>;
}
impl<'tcx> FileDescriptor<'tcx> for FileHandle {
fn as_file_handle(&self) -> InterpResult<'tcx, &FileHandle> {
impl FileDescriptor for FileHandle {
fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle> {
Ok(&self)
}
fn read(&mut self, communicate_allowed: bool, bytes: &mut [u8]) -> InterpResult<'tcx, io::Result<usize>> {
fn read<'tcx>(&mut self, communicate_allowed: bool, bytes: &mut [u8]) -> InterpResult<'tcx, io::Result<usize>> {
assert!(communicate_allowed, "isolation should have prevented even opening a file");
Ok(self.file.read(bytes))
}
fn write(&mut self, communicate_allowed: bool, bytes: &[u8]) -> InterpResult<'tcx, io::Result<usize>> {
fn write<'tcx>(&mut self, communicate_allowed: bool, bytes: &[u8]) -> InterpResult<'tcx, io::Result<usize>> {
assert!(communicate_allowed, "isolation should have prevented even opening a file");
Ok(self.file.write(bytes))
}
fn seek(&mut self, communicate_allowed: bool, offset: SeekFrom) -> InterpResult<'tcx, io::Result<u64>> {
fn seek<'tcx>(&mut self, communicate_allowed: bool, offset: SeekFrom) -> InterpResult<'tcx, io::Result<u64>> {
assert!(communicate_allowed, "isolation should have prevented even opening a file");
Ok(self.file.seek(offset))
}
}
impl<'tcx> FileDescriptor<'tcx> for io::Stdin {
fn as_file_handle(&self) -> InterpResult<'tcx, &FileHandle> {
impl FileDescriptor for io::Stdin {
fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle> {
throw_unsup_format!("stdin cannot be used as FileHandle");
}
fn read(&mut self, communicate_allowed: bool, bytes: &mut [u8]) -> InterpResult<'tcx, io::Result<usize>> {
fn read<'tcx>(&mut self, communicate_allowed: bool, bytes: &mut [u8]) -> InterpResult<'tcx, io::Result<usize>> {
if !communicate_allowed {
// We want isolation mode to be deterministic, so we have to disallow all reads, even stdin.
helpers::isolation_error("read")?;
@ -64,25 +64,25 @@ impl<'tcx> FileDescriptor<'tcx> for io::Stdin {
Ok(Read::read(self, bytes))
}
fn write(&mut self, _communicate_allowed: bool, _bytes: &[u8]) -> InterpResult<'tcx, io::Result<usize>> {
fn write<'tcx>(&mut self, _communicate_allowed: bool, _bytes: &[u8]) -> InterpResult<'tcx, io::Result<usize>> {
throw_unsup_format!("cannot write to stdin");
}
fn seek(&mut self, _communicate_allowed: bool, _offset: SeekFrom) -> InterpResult<'tcx, io::Result<u64>> {
fn seek<'tcx>(&mut self, _communicate_allowed: bool, _offset: SeekFrom) -> InterpResult<'tcx, io::Result<u64>> {
throw_unsup_format!("cannot seek on stdin");
}
}
impl<'tcx> FileDescriptor<'tcx> for io::Stdout {
fn as_file_handle(&self) -> InterpResult<'tcx, &FileHandle> {
impl FileDescriptor for io::Stdout {
fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle> {
throw_unsup_format!("stdout cannot be used as FileHandle");
}
fn read(&mut self, _communicate_allowed: bool, _bytes: &mut [u8]) -> InterpResult<'tcx, io::Result<usize>> {
fn read<'tcx>(&mut self, _communicate_allowed: bool, _bytes: &mut [u8]) -> InterpResult<'tcx, io::Result<usize>> {
throw_unsup_format!("cannot read from stdout");
}
fn write(&mut self, _communicate_allowed: bool, bytes: &[u8]) -> InterpResult<'tcx, io::Result<usize>> {
fn write<'tcx>(&mut self, _communicate_allowed: bool, bytes: &[u8]) -> InterpResult<'tcx, io::Result<usize>> {
// We allow writing to stderr even with isolation enabled.
let result = Write::write(self, bytes);
// Stdout is buffered, flush to make sure it appears on the
@ -95,41 +95,42 @@ impl<'tcx> FileDescriptor<'tcx> for io::Stdout {
Ok(result)
}
fn seek(&mut self, _communicate_allowed: bool, _offset: SeekFrom) -> InterpResult<'tcx, io::Result<u64>> {
fn seek<'tcx>(&mut self, _communicate_allowed: bool, _offset: SeekFrom) -> InterpResult<'tcx, io::Result<u64>> {
throw_unsup_format!("cannot seek on stdout");
}
}
impl<'tcx> FileDescriptor<'tcx> for io::Stderr {
fn as_file_handle(&self) -> InterpResult<'tcx, &FileHandle> {
impl FileDescriptor for io::Stderr {
fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle> {
throw_unsup_format!("stdout cannot be used as FileHandle");
}
fn read(&mut self, _communicate_allowed: bool, _bytes: &mut [u8]) -> InterpResult<'tcx, io::Result<usize>> {
fn read<'tcx>(&mut self, _communicate_allowed: bool, _bytes: &mut [u8]) -> InterpResult<'tcx, io::Result<usize>> {
throw_unsup_format!("cannot read from stderr");
}
fn write(&mut self, _communicate_allowed: bool, bytes: &[u8]) -> InterpResult<'tcx, io::Result<usize>> {
fn write<'tcx>(&mut self, _communicate_allowed: bool, bytes: &[u8]) -> InterpResult<'tcx, io::Result<usize>> {
// We allow writing to stderr even with isolation enabled.
// No need to flush, stderr is not buffered.
Ok(Write::write(self, bytes))
}
fn seek(&mut self, _communicate_allowed: bool, _offset: SeekFrom) -> InterpResult<'tcx, io::Result<u64>> {
fn seek<'tcx>(&mut self, _communicate_allowed: bool, _offset: SeekFrom) -> InterpResult<'tcx, io::Result<u64>> {
throw_unsup_format!("cannot seek on stderr");
}
}
#[derive(Debug)]
pub struct FileHandler<'tcx> {
handles: BTreeMap<i32, Box<dyn FileDescriptor<'tcx>>>,
pub struct FileHandler {
handles: BTreeMap<i32, Box<dyn FileDescriptor>>,
}
impl<'tcx> Default for FileHandler<'tcx> {
impl<'tcx> Default for FileHandler {
fn default() -> Self {
let mut handles = BTreeMap::new();
handles.insert(0i32, Box::new(io::stdin()) as Box<dyn FileDescriptor<'_>>);
handles.insert(1i32, Box::new(io::stdout()) as Box<dyn FileDescriptor<'_>>);
handles.insert(2i32, Box::new(io::stderr()) as Box<dyn FileDescriptor<'_>>);
let mut handles: BTreeMap<_, Box<dyn FileDescriptor>> = BTreeMap::new();
handles.insert(0i32, Box::new(io::stdin()));
handles.insert(1i32, Box::new(io::stdout()));
handles.insert(2i32, Box::new(io::stderr()));
FileHandler {
handles
}
@ -140,7 +141,7 @@ impl<'tcx> Default for FileHandler<'tcx> {
// fd numbers 0, 1, and 2 are reserved for stdin, stdout, and stderr
const MIN_NORMAL_FILE_FD: i32 = 3;
impl<'tcx> FileHandler<'tcx> {
impl<'tcx> FileHandler {
fn insert_fd(&mut self, file_handle: FileHandle) -> i32 {
self.insert_fd_with_min_fd(file_handle, 0)
}