Skip to content

Commit

Permalink
Auto merge of rust-lang#75772 - tmiasko:io-maybe-no, r=dtolnay
Browse files Browse the repository at this point in the history
Remove unused `Maybe` wrapper around raw standard streams

* Remove result type from raw standard streams constructors
* Make raw standard stream constructors const
* Remove wrapper type handling absent raw standard streams

cargo checked with:

```shell
env CC=true ./x.py check library/std/ \
  --target i686-unknown-linux-gnu \
  --target wasm32-unknown-emscripten \
  --target wasm32-wasi \
  --target x86_64-fortanix-unknown-sgx \
  --target x86_64-pc-windows-gnu \
  --target x86_64-unknown-cloudabi \
  --target x86_64-unknown-hermit \
  --target x86_64-unknown-linux-gnu \
  --target x86_64-uwp-windows-gnu \
  --target x86_64-wrs-vxworks
```

Note: Last target doesn't compile currently.
  • Loading branch information
bors committed Aug 22, 2020
2 parents e3a4b16 + 78e0946 commit ebc03f7
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 175 deletions.
156 changes: 42 additions & 114 deletions library/std/src/io/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ struct StderrRaw(stdio::Stderr);
/// handles is **not** available to raw handles returned from this function.
///
/// The returned handle has no external synchronization or buffering.
fn stdin_raw() -> io::Result<StdinRaw> {
stdio::Stdin::new().map(StdinRaw)
#[unstable(feature = "libstd_sys_internals", issue = "none")]
const fn stdin_raw() -> StdinRaw {
StdinRaw(stdio::Stdin::new())
}

/// Constructs a new raw handle to the standard output stream of this process.
Expand All @@ -63,8 +64,9 @@ fn stdin_raw() -> io::Result<StdinRaw> {
///
/// The returned handle has no external synchronization or buffering layered on
/// top.
fn stdout_raw() -> io::Result<StdoutRaw> {
stdio::Stdout::new().map(StdoutRaw)
#[unstable(feature = "libstd_sys_internals", issue = "none")]
const fn stdout_raw() -> StdoutRaw {
StdoutRaw(stdio::Stdout::new())
}

/// Constructs a new raw handle to the standard error stream of this process.
Expand All @@ -74,17 +76,18 @@ fn stdout_raw() -> io::Result<StdoutRaw> {
///
/// The returned handle has no external synchronization or buffering layered on
/// top.
fn stderr_raw() -> io::Result<StderrRaw> {
stdio::Stderr::new().map(StderrRaw)
#[unstable(feature = "libstd_sys_internals", issue = "none")]
const fn stderr_raw() -> StderrRaw {
StderrRaw(stdio::Stderr::new())
}

impl Read for StdinRaw {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
handle_ebadf(self.0.read(buf), 0)
}

fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.0.read_vectored(bufs)
handle_ebadf(self.0.read_vectored(bufs), 0)
}

#[inline]
Expand All @@ -98,25 +101,22 @@ impl Read for StdinRaw {
}

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.0.read_to_end(buf)
handle_ebadf(self.0.read_to_end(buf), 0)
}

fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
self.0.read_to_string(buf)
}

fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
self.0.read_exact(buf)
handle_ebadf(self.0.read_to_string(buf), 0)
}
}

impl Write for StdoutRaw {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
handle_ebadf(self.0.write(buf), buf.len())
}

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.0.write_vectored(bufs)
let total = bufs.iter().map(|b| b.len()).sum();
handle_ebadf(self.0.write_vectored(bufs), total)
}

#[inline]
Expand All @@ -125,29 +125,30 @@ impl Write for StdoutRaw {
}

fn flush(&mut self) -> io::Result<()> {
self.0.flush()
handle_ebadf(self.0.flush(), ())
}

fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.0.write_all(buf)
handle_ebadf(self.0.write_all(buf), ())
}

fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
self.0.write_all_vectored(bufs)
handle_ebadf(self.0.write_all_vectored(bufs), ())
}

fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
self.0.write_fmt(fmt)
handle_ebadf(self.0.write_fmt(fmt), ())
}
}

impl Write for StderrRaw {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
handle_ebadf(self.0.write(buf), buf.len())
}

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.0.write_vectored(bufs)
let total = bufs.iter().map(|b| b.len()).sum();
handle_ebadf(self.0.write_vectored(bufs), total)
}

#[inline]
Expand All @@ -156,80 +157,19 @@ impl Write for StderrRaw {
}

fn flush(&mut self) -> io::Result<()> {
self.0.flush()
handle_ebadf(self.0.flush(), ())
}

fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.0.write_all(buf)
handle_ebadf(self.0.write_all(buf), ())
}

fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
self.0.write_all_vectored(bufs)
handle_ebadf(self.0.write_all_vectored(bufs), ())
}

fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
self.0.write_fmt(fmt)
}
}

enum Maybe<T> {
Real(T),
Fake,
}

impl<W: io::Write> io::Write for Maybe<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match *self {
Maybe::Real(ref mut w) => handle_ebadf(w.write(buf), buf.len()),
Maybe::Fake => Ok(buf.len()),
}
}

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
let total = bufs.iter().map(|b| b.len()).sum();
match self {
Maybe::Real(w) => handle_ebadf(w.write_vectored(bufs), total),
Maybe::Fake => Ok(total),
}
}

#[inline]
fn is_write_vectored(&self) -> bool {
match self {
Maybe::Real(w) => w.is_write_vectored(),
Maybe::Fake => true,
}
}

fn flush(&mut self) -> io::Result<()> {
match *self {
Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()),
Maybe::Fake => Ok(()),
}
}
}

impl<R: io::Read> io::Read for Maybe<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match *self {
Maybe::Real(ref mut r) => handle_ebadf(r.read(buf), 0),
Maybe::Fake => Ok(0),
}
}

fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
match self {
Maybe::Real(r) => handle_ebadf(r.read_vectored(bufs), 0),
Maybe::Fake => Ok(0),
}
}

#[inline]
fn is_read_vectored(&self) -> bool {
match self {
Maybe::Real(w) => w.is_read_vectored(),
Maybe::Fake => true,
}
handle_ebadf(self.0.write_fmt(fmt), ())
}
}

Expand Down Expand Up @@ -274,7 +214,7 @@ fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdin {
inner: Arc<Mutex<BufReader<Maybe<StdinRaw>>>>,
inner: Arc<Mutex<BufReader<StdinRaw>>>,
}

/// A locked reference to the `Stdin` handle.
Expand Down Expand Up @@ -305,7 +245,7 @@ pub struct Stdin {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdinLock<'a> {
inner: MutexGuard<'a, BufReader<Maybe<StdinRaw>>>,
inner: MutexGuard<'a, BufReader<StdinRaw>>,
}

/// Constructs a new handle to the standard input of the current process.
Expand Down Expand Up @@ -349,18 +289,14 @@ pub struct StdinLock<'a> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdin() -> Stdin {
static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new();
static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = Lazy::new();
return Stdin {
inner: unsafe { INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown") },
};

fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
fn stdin_init() -> Arc<Mutex<BufReader<StdinRaw>>> {
// This must not reentrantly access `INSTANCE`
let stdin = match stdin_raw() {
Ok(stdin) => Maybe::Real(stdin),
_ => Maybe::Fake,
};

let stdin = stdin_raw();
Arc::new(Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin)))
}
}
Expand Down Expand Up @@ -537,7 +473,7 @@ pub struct Stdout {
// FIXME: this should be LineWriter or BufWriter depending on the state of
// stdout (tty or not). Note that if this is not line buffered it
// should also flush-on-panic or some form of flush-on-abort.
inner: Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>,
inner: Arc<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
}

/// A locked reference to the `Stdout` handle.
Expand All @@ -551,7 +487,7 @@ pub struct Stdout {
/// an error.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdoutLock<'a> {
inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>,
inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
}

/// Constructs a new handle to the standard output of the current process.
Expand Down Expand Up @@ -595,17 +531,14 @@ pub struct StdoutLock<'a> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdout() -> Stdout {
static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> = Lazy::new();
static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = Lazy::new();
return Stdout {
inner: unsafe { INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown") },
};

fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> {
// This must not reentrantly access `INSTANCE`
let stdout = match stdout_raw() {
Ok(stdout) => Maybe::Real(stdout),
_ => Maybe::Fake,
};
let stdout = stdout_raw();
unsafe {
let ret = Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout))));
ret.init();
Expand Down Expand Up @@ -715,7 +648,7 @@ impl fmt::Debug for StdoutLock<'_> {
/// an error.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stderr {
inner: &'static ReentrantMutex<RefCell<Maybe<StderrRaw>>>,
inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
}

/// A locked reference to the `Stderr` handle.
Expand All @@ -729,7 +662,7 @@ pub struct Stderr {
/// an error.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StderrLock<'a> {
inner: ReentrantMutexGuard<'a, RefCell<Maybe<StderrRaw>>>,
inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
}

/// Constructs a new handle to the standard error of the current process.
Expand Down Expand Up @@ -778,19 +711,14 @@ pub fn stderr() -> Stderr {
//
// This has the added benefit of allowing `stderr` to be usable during
// process shutdown as well!
static INSTANCE: ReentrantMutex<RefCell<Maybe<StderrRaw>>> =
unsafe { ReentrantMutex::new(RefCell::new(Maybe::Fake)) };
static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) };

// When accessing stderr we need one-time initialization of the reentrant
// mutex, followed by one-time detection of whether we actually have a
// stderr handle or not. Afterwards we can just always use the now-filled-in
// `INSTANCE` value.
// mutex. Afterwards we can just always use the now-filled-in `INSTANCE` value.
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
INSTANCE.init();
if let Ok(stderr) = stderr_raw() {
*INSTANCE.lock().borrow_mut() = Maybe::Real(stderr);
}
});
Stderr { inner: &INSTANCE }
}
Expand Down
14 changes: 7 additions & 7 deletions library/std/src/sys/cloudabi/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ pub struct Stdout(());
pub struct Stderr(());

impl Stdin {
pub fn new() -> io::Result<Stdin> {
Ok(Stdin(()))
pub const fn new() -> Stdin {
Stdin(())
}
}

Expand All @@ -18,8 +18,8 @@ impl io::Read for Stdin {
}

impl Stdout {
pub fn new() -> io::Result<Stdout> {
Ok(Stdout(()))
pub const fn new() -> Stdout {
Stdout(())
}
}

Expand All @@ -37,8 +37,8 @@ impl io::Write for Stdout {
}

impl Stderr {
pub fn new() -> io::Result<Stderr> {
Ok(Stderr(()))
pub const fn new() -> Stderr {
Stderr(())
}
}

Expand All @@ -62,5 +62,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;

pub fn panic_output() -> Option<impl io::Write> {
Stderr::new().ok()
Some(Stderr::new())
}
14 changes: 7 additions & 7 deletions library/std/src/sys/hermit/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ pub struct Stdout;
pub struct Stderr;

impl Stdin {
pub fn new() -> io::Result<Stdin> {
Ok(Stdin)
pub const fn new() -> Stdin {
Stdin
}
}

Expand All @@ -28,8 +28,8 @@ impl io::Read for Stdin {
}

impl Stdout {
pub fn new() -> io::Result<Stdout> {
Ok(Stdout)
pub const fn new() -> Stdout {
Stdout
}
}

Expand Down Expand Up @@ -69,8 +69,8 @@ impl io::Write for Stdout {
}

impl Stderr {
pub fn new() -> io::Result<Stderr> {
Ok(Stderr)
pub const fn new() -> Stderr {
Stderr
}
}

Expand Down Expand Up @@ -116,5 +116,5 @@ pub fn is_ebadf(_err: &io::Error) -> bool {
}

pub fn panic_output() -> Option<impl io::Write> {
Stderr::new().ok()
Some(Stderr::new())
}
Loading

0 comments on commit ebc03f7

Please sign in to comment.