Skip to content

Commit 72014a8

Browse files
committed
Auto merge of #2801 - RalfJung:fd-cleanup, r=oli-obk
a bit of FileDescriptor trait cleanup - add default impl for `is_tty` - `as_epoll_handle` was just dyn downcasting in disguise; this can be done more generally
2 parents 3f88f4c + 30859d9 commit 72014a8

File tree

6 files changed

+73
-45
lines changed

6 files changed

+73
-45
lines changed

src/tools/miri/src/helpers.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod convert;
22

3+
use std::any::Any;
34
use std::cmp;
45
use std::iter;
56
use std::num::NonZeroUsize;
@@ -23,7 +24,23 @@ use rand::RngCore;
2324

2425
use crate::*;
2526

26-
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
27+
/// A trait to work around not having trait object upcasting:
28+
/// Add `AsAny` as supertrait and your trait objects can be turned into `&dyn Any` on which you can
29+
/// then call `downcast`.
30+
pub trait AsAny: Any {
31+
fn as_any(&self) -> &dyn Any;
32+
fn as_any_mut(&mut self) -> &mut dyn Any;
33+
}
34+
impl<T: Any> AsAny for T {
35+
#[inline(always)]
36+
fn as_any(&self) -> &dyn Any {
37+
self
38+
}
39+
#[inline(always)]
40+
fn as_any_mut(&mut self) -> &mut dyn Any {
41+
self
42+
}
43+
}
2744

2845
// This mapping should match `decode_error_kind` in
2946
// <https://github.com/rust-lang/rust/blob/master/library/std/src/sys/unix/mod.rs>.
@@ -119,6 +136,7 @@ fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option<Namespace>)
119136
}
120137
}
121138

139+
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
122140
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
123141
/// Checks if the given crate/module exists.
124142
fn have_module(&self, path: &[&str]) -> bool {

src/tools/miri/src/shims/unix/fs.rs

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,16 @@ use crate::shims::os_str::bytes_to_os_str;
1717
use crate::*;
1818
use shims::os_str::os_str_to_bytes;
1919
use shims::time::system_time_to_duration;
20-
use shims::unix::linux::fd::epoll::Epoll;
2120

2221
#[derive(Debug)]
2322
pub struct FileHandle {
2423
file: File,
2524
writable: bool,
2625
}
2726

28-
pub trait FileDescriptor: std::fmt::Debug {
27+
pub trait FileDescriptor: std::fmt::Debug + helpers::AsAny {
2928
fn name(&self) -> &'static str;
3029

31-
fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle> {
32-
throw_unsup_format!("{} cannot be used as FileHandle", self.name());
33-
}
34-
35-
fn as_epoll_handle<'tcx>(&mut self) -> InterpResult<'tcx, &mut Epoll> {
36-
throw_unsup_format!("not an epoll file descriptor");
37-
}
38-
3930
fn read<'tcx>(
4031
&mut self,
4132
_communicate_allowed: bool,
@@ -69,7 +60,9 @@ pub trait FileDescriptor: std::fmt::Debug {
6960

7061
fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>>;
7162

72-
fn is_tty(&self) -> bool;
63+
fn is_tty(&self) -> bool {
64+
false
65+
}
7366

7467
#[cfg(unix)]
7568
fn as_unix_host_fd(&self) -> Option<i32> {
@@ -82,10 +75,6 @@ impl FileDescriptor for FileHandle {
8275
"FILE"
8376
}
8477

85-
fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle> {
86-
Ok(self)
87-
}
88-
8978
fn read<'tcx>(
9079
&mut self,
9180
communicate_allowed: bool,
@@ -271,10 +260,6 @@ impl FileDescriptor for NullOutput {
271260
fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
272261
Ok(Box::new(NullOutput))
273262
}
274-
275-
fn is_tty(&self) -> bool {
276-
false
277-
}
278263
}
279264

280265
#[derive(Debug)]
@@ -694,7 +679,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
694679
} else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") {
695680
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
696681
// FIXME: Support fullfsync for all FDs
697-
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
682+
let FileHandle { file, writable } =
683+
file_descriptor.as_any().downcast_ref::<FileHandle>().ok_or_else(|| {
684+
err_unsup_format!(
685+
"`F_FULLFSYNC` is only supported on file-backed file descriptors"
686+
)
687+
})?;
698688
let io_result = maybe_sync_file(file, *writable, File::sync_all);
699689
this.try_unwrap_io_result(io_result)
700690
} else {
@@ -1530,7 +1520,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
15301520
Ok(Scalar::from_i32(
15311521
if let Some(file_descriptor) = this.machine.file_handler.handles.get_mut(&fd) {
15321522
// FIXME: Support ftruncate64 for all FDs
1533-
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
1523+
let FileHandle { file, writable } =
1524+
file_descriptor.as_any().downcast_ref::<FileHandle>().ok_or_else(|| {
1525+
err_unsup_format!(
1526+
"`ftruncate64` is only supported on file-backed file descriptors"
1527+
)
1528+
})?;
15341529
if *writable {
15351530
if let Ok(length) = length.try_into() {
15361531
let result = file.set_len(length);
@@ -1571,7 +1566,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
15711566

15721567
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
15731568
// FIXME: Support fsync for all FDs
1574-
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
1569+
let FileHandle { file, writable } =
1570+
file_descriptor.as_any().downcast_ref::<FileHandle>().ok_or_else(|| {
1571+
err_unsup_format!("`fsync` is only supported on file-backed file descriptors")
1572+
})?;
15751573
let io_result = maybe_sync_file(file, *writable, File::sync_all);
15761574
this.try_unwrap_io_result(io_result)
15771575
} else {
@@ -1593,7 +1591,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
15931591

15941592
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
15951593
// FIXME: Support fdatasync for all FDs
1596-
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
1594+
let FileHandle { file, writable } =
1595+
file_descriptor.as_any().downcast_ref::<FileHandle>().ok_or_else(|| {
1596+
err_unsup_format!(
1597+
"`fdatasync` is only supported on file-backed file descriptors"
1598+
)
1599+
})?;
15971600
let io_result = maybe_sync_file(file, *writable, File::sync_data);
15981601
this.try_unwrap_io_result(io_result)
15991602
} else {
@@ -1638,7 +1641,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
16381641

16391642
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
16401643
// FIXME: Support sync_data_range for all FDs
1641-
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
1644+
let FileHandle { file, writable } =
1645+
file_descriptor.as_any().downcast_ref::<FileHandle>().ok_or_else(|| {
1646+
err_unsup_format!(
1647+
"`sync_data_range` is only supported on file-backed file descriptors"
1648+
)
1649+
})?;
16421650
let io_result = maybe_sync_file(file, *writable, File::sync_data);
16431651
Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?))
16441652
} else {
@@ -1942,7 +1950,16 @@ impl FileMetadata {
19421950
) -> InterpResult<'tcx, Option<FileMetadata>> {
19431951
let option = ecx.machine.file_handler.handles.get(&fd);
19441952
let file = match option {
1945-
Some(file_descriptor) => &file_descriptor.as_file_handle()?.file,
1953+
Some(file_descriptor) =>
1954+
&file_descriptor
1955+
.as_any()
1956+
.downcast_ref::<FileHandle>()
1957+
.ok_or_else(|| {
1958+
err_unsup_format!(
1959+
"obtaining metadata is only supported on file-backed file descriptors"
1960+
)
1961+
})?
1962+
.file,
19461963
None => return ecx.handle_not_found().map(|_: i32| None),
19471964
};
19481965
let metadata = file.metadata();

src/tools/miri/src/shims/unix/linux/fd.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
8080
let event = EpollEvent { events, data };
8181

8282
if let Some(epfd) = this.machine.file_handler.handles.get_mut(&epfd) {
83-
let epfd = epfd.as_epoll_handle()?;
83+
let epfd = epfd
84+
.as_any_mut()
85+
.downcast_mut::<Epoll>()
86+
.ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?;
8487

8588
epfd.file_descriptors.insert(fd, event);
8689
Ok(Scalar::from_i32(0))
@@ -89,7 +92,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
8992
}
9093
} else if op == epoll_ctl_del {
9194
if let Some(epfd) = this.machine.file_handler.handles.get_mut(&epfd) {
92-
let epfd = epfd.as_epoll_handle()?;
95+
let epfd = epfd
96+
.as_any_mut()
97+
.downcast_mut::<Epoll>()
98+
.ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?;
9399

94100
epfd.file_descriptors.remove(&fd);
95101
Ok(Scalar::from_i32(0))
@@ -148,7 +154,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
148154

149155
let numevents = 0;
150156
if let Some(epfd) = this.machine.file_handler.handles.get_mut(&epfd) {
151-
let _epfd = epfd.as_epoll_handle()?;
157+
let _epfd = epfd
158+
.as_any_mut()
159+
.downcast_mut::<Epoll>()
160+
.ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))?;
152161

153162
// FIXME return number of events ready when scheme for marking events ready exists
154163
Ok(Scalar::from_i32(numevents))

src/tools/miri/src/shims/unix/linux/fd/epoll.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,10 @@ impl FileDescriptor for Epoll {
3232
"epoll"
3333
}
3434

35-
fn as_epoll_handle<'tcx>(&mut self) -> InterpResult<'tcx, &mut Epoll> {
36-
Ok(self)
37-
}
38-
3935
fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
4036
Ok(Box::new(self.clone()))
4137
}
4238

43-
fn is_tty(&self) -> bool {
44-
false
45-
}
46-
4739
fn close<'tcx>(
4840
self: Box<Self>,
4941
_communicate_allowed: bool,

src/tools/miri/src/shims/unix/linux/fd/event.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@ impl FileDescriptor for Event {
2828
Ok(Box::new(Event { val: self.val.clone() }))
2929
}
3030

31-
fn is_tty(&self) -> bool {
32-
false
33-
}
34-
3531
fn close<'tcx>(
3632
self: Box<Self>,
3733
_communicate_allowed: bool,

src/tools/miri/src/shims/unix/linux/fd/socketpair.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@ impl FileDescriptor for SocketPair {
1919
Ok(Box::new(SocketPair))
2020
}
2121

22-
fn is_tty(&self) -> bool {
23-
false
24-
}
25-
2622
fn close<'tcx>(
2723
self: Box<Self>,
2824
_communicate_allowed: bool,

0 commit comments

Comments
 (0)