Use Vec<u8> for LOCAL_STD{OUT,ERR} instead of dyn Write.

It was only ever used with Vec<u8> anyway. This simplifies some things.

- It no longer needs to be flushed, because that's a no-op anyway for
  a Vec<u8>.

- Writing to a Vec<u8> never fails.

- No #[cfg(test)] code is needed anymore to use `realstd` instead of
  `std`, because Vec comes from alloc, not std (like Write).
This commit is contained in:
Mara Bos 2020-11-03 21:44:21 +01:00
parent ccbce1d3b2
commit f534b75f05
5 changed files with 28 additions and 78 deletions

View File

@ -148,9 +148,7 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals<F: FnOnce() -> R + Se
let main_handler = move || {
rustc_span::with_session_globals(edition, || {
if let Some(stderr) = stderr {
io::set_panic(Some(stderr.clone()));
}
io::set_panic(stderr.clone());
f()
})
};
@ -188,9 +186,7 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals<F: FnOnce() -> R + Se
// on the new threads.
let main_handler = move |thread: rayon::ThreadBuilder| {
rustc_span::SESSION_GLOBALS.set(session_globals, || {
if let Some(stderr) = stderr {
io::set_panic(Some(stderr.clone()));
}
io::set_panic(stderr.clone());
thread.run()
})
};

View File

@ -16,7 +16,7 @@
use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
use crate::thread::LocalKey;
type LocalStream = Arc<Mutex<dyn Write + Send>>;
type LocalStream = Arc<Mutex<Vec<u8>>>;
thread_local! {
/// Used by the test crate to capture the output of the print! and println! macros.
@ -911,13 +911,8 @@ pub fn set_panic(sink: Option<LocalStream>) -> Option<LocalStream> {
// LOCAL_STDERR is definitely None since LOCAL_STREAMS is false.
return None;
}
let s =
LOCAL_STDERR.with(move |slot| mem::replace(&mut *slot.borrow_mut(), sink)).and_then(|s| {
let _ = s.lock().unwrap_or_else(|e| e.into_inner()).flush();
Some(s)
});
LOCAL_STREAMS.store(true, Ordering::Relaxed);
s
LOCAL_STDERR.with(move |slot| mem::replace(&mut *slot.borrow_mut(), sink))
}
/// Resets the thread-local stdout handle to the specified writer
@ -941,13 +936,8 @@ pub fn set_print(sink: Option<LocalStream>) -> Option<LocalStream> {
// LOCAL_STDOUT is definitely None since LOCAL_STREAMS is false.
return None;
}
let s =
LOCAL_STDOUT.with(move |slot| mem::replace(&mut *slot.borrow_mut(), sink)).and_then(|s| {
let _ = s.lock().unwrap_or_else(|e| e.into_inner()).flush();
Some(s)
});
LOCAL_STREAMS.store(true, Ordering::Relaxed);
s
LOCAL_STDOUT.with(move |slot| mem::replace(&mut *slot.borrow_mut(), sink))
}
pub(crate) fn clone_io() -> (Option<LocalStream>, Option<LocalStream>) {
@ -956,9 +946,10 @@ pub(crate) fn clone_io() -> (Option<LocalStream>, Option<LocalStream>) {
return (None, None);
}
LOCAL_STDOUT.with(|stdout| {
LOCAL_STDERR.with(|stderr| (stdout.borrow().clone(), stderr.borrow().clone()))
})
(
LOCAL_STDOUT.with(|s| s.borrow().clone()),
LOCAL_STDERR.with(|s| s.borrow().clone()),
)
}
/// Write `args` to output stream `local_s` if possible, `global_s`
@ -979,28 +970,22 @@ fn print_to<T>(
) where
T: Write,
{
let result = LOCAL_STREAMS
.load(Ordering::Relaxed)
.then(|| {
local_s
.try_with(|s| {
// Note that we completely remove a local sink to write to in case
// our printing recursively panics/prints, so the recursive
// panic/print goes to the global sink instead of our local sink.
let prev = s.borrow_mut().take();
if let Some(w) = prev {
let result = w.lock().unwrap_or_else(|e| e.into_inner()).write_fmt(args);
*s.borrow_mut() = Some(w);
return result;
}
global_s().write_fmt(args)
})
.ok()
})
.flatten()
.unwrap_or_else(|| global_s().write_fmt(args));
if LOCAL_STREAMS.load(Ordering::Relaxed)
&& local_s.try_with(|s| {
// Note that we completely remove a local sink to write to in case
// our printing recursively panics/prints, so the recursive
// panic/print goes to the global sink instead of our local sink.
s.take().map(|w| {
let _ = w.lock().unwrap_or_else(|e| e.into_inner()).write_fmt(args);
*s.borrow_mut() = Some(w);
})
}) == Ok(Some(()))
{
// Succesfully wrote to local stream.
return;
}
if let Err(e) = result {
if let Err(e) = global_s().write_fmt(args) {
panic!("failed printing to {}: {}", label, e);
}
}

View File

@ -297,6 +297,7 @@
#![feature(raw)]
#![feature(raw_ref_macros)]
#![feature(ready_macro)]
#![feature(refcell_take)]
#![feature(rustc_attrs)]
#![feature(rustc_private)]
#![feature(shrink_to)]

View File

@ -219,28 +219,7 @@ fn default_hook(info: &PanicInfo<'_>) {
};
if let Some(local) = set_panic(None) {
let mut stream = local.lock().unwrap_or_else(|e| e.into_inner());
#[cfg(test)]
{
use crate::io;
struct Wrapper<'a>(&'a mut (dyn ::realstd::io::Write + Send));
impl io::Write for Wrapper<'_> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf).map_err(|_| io::ErrorKind::Other.into())
}
fn flush(&mut self) -> io::Result<()> {
self.0.flush().map_err(|_| io::ErrorKind::Other.into())
}
}
write(&mut Wrapper(&mut *stream));
}
#[cfg(not(test))]
write(&mut *stream);
drop(stream);
write(&mut *local.lock().unwrap_or_else(|e| e.into_inner()));
set_panic(Some(local));
} else if let Some(mut out) = panic_output() {
write(&mut out);

View File

@ -5,7 +5,7 @@
use std::fmt;
use std::fmt::{Display, Formatter};
use std::io::{self, set_panic, Write};
use std::io::set_panic;
use std::sync::{Arc, Mutex};
pub struct A;
@ -16,19 +16,8 @@ fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
}
}
struct Sink;
impl Write for Sink {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
fn main() {
set_panic(Some(Arc::new(Mutex::new(Sink))));
set_panic(Some(Arc::new(Mutex::new(Vec::new()))));
assert!(std::panic::catch_unwind(|| {
eprintln!("{}", A);
})