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:
parent
ccbce1d3b2
commit
f534b75f05
5 changed files with 28 additions and 78 deletions
|
@ -148,9 +148,7 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals<F: FnOnce() -> R + Se
|
||||||
|
|
||||||
let main_handler = move || {
|
let main_handler = move || {
|
||||||
rustc_span::with_session_globals(edition, || {
|
rustc_span::with_session_globals(edition, || {
|
||||||
if let Some(stderr) = stderr {
|
io::set_panic(stderr.clone());
|
||||||
io::set_panic(Some(stderr.clone()));
|
|
||||||
}
|
|
||||||
f()
|
f()
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -188,9 +186,7 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals<F: FnOnce() -> R + Se
|
||||||
// on the new threads.
|
// on the new threads.
|
||||||
let main_handler = move |thread: rayon::ThreadBuilder| {
|
let main_handler = move |thread: rayon::ThreadBuilder| {
|
||||||
rustc_span::SESSION_GLOBALS.set(session_globals, || {
|
rustc_span::SESSION_GLOBALS.set(session_globals, || {
|
||||||
if let Some(stderr) = stderr {
|
io::set_panic(stderr.clone());
|
||||||
io::set_panic(Some(stderr.clone()));
|
|
||||||
}
|
|
||||||
thread.run()
|
thread.run()
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::sys_common;
|
||||||
use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
|
use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
|
||||||
use crate::thread::LocalKey;
|
use crate::thread::LocalKey;
|
||||||
|
|
||||||
type LocalStream = Arc<Mutex<dyn Write + Send>>;
|
type LocalStream = Arc<Mutex<Vec<u8>>>;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
/// Used by the test crate to capture the output of the print! and println! macros.
|
/// 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.
|
// LOCAL_STDERR is definitely None since LOCAL_STREAMS is false.
|
||||||
return None;
|
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);
|
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
|
/// 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.
|
// LOCAL_STDOUT is definitely None since LOCAL_STREAMS is false.
|
||||||
return None;
|
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);
|
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>) {
|
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);
|
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`
|
/// Write `args` to output stream `local_s` if possible, `global_s`
|
||||||
|
@ -979,28 +970,22 @@ fn print_to<T>(
|
||||||
) where
|
) where
|
||||||
T: Write,
|
T: Write,
|
||||||
{
|
{
|
||||||
let result = LOCAL_STREAMS
|
if LOCAL_STREAMS.load(Ordering::Relaxed)
|
||||||
.load(Ordering::Relaxed)
|
&& local_s.try_with(|s| {
|
||||||
.then(|| {
|
|
||||||
local_s
|
|
||||||
.try_with(|s| {
|
|
||||||
// Note that we completely remove a local sink to write to in case
|
// Note that we completely remove a local sink to write to in case
|
||||||
// our printing recursively panics/prints, so the recursive
|
// our printing recursively panics/prints, so the recursive
|
||||||
// panic/print goes to the global sink instead of our local sink.
|
// panic/print goes to the global sink instead of our local sink.
|
||||||
let prev = s.borrow_mut().take();
|
s.take().map(|w| {
|
||||||
if let Some(w) = prev {
|
let _ = w.lock().unwrap_or_else(|e| e.into_inner()).write_fmt(args);
|
||||||
let result = w.lock().unwrap_or_else(|e| e.into_inner()).write_fmt(args);
|
|
||||||
*s.borrow_mut() = Some(w);
|
*s.borrow_mut() = Some(w);
|
||||||
return result;
|
})
|
||||||
|
}) == Ok(Some(()))
|
||||||
|
{
|
||||||
|
// Succesfully wrote to local stream.
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
global_s().write_fmt(args)
|
|
||||||
})
|
|
||||||
.ok()
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.unwrap_or_else(|| global_s().write_fmt(args));
|
|
||||||
|
|
||||||
if let Err(e) = result {
|
if let Err(e) = global_s().write_fmt(args) {
|
||||||
panic!("failed printing to {}: {}", label, e);
|
panic!("failed printing to {}: {}", label, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,6 +297,7 @@
|
||||||
#![feature(raw)]
|
#![feature(raw)]
|
||||||
#![feature(raw_ref_macros)]
|
#![feature(raw_ref_macros)]
|
||||||
#![feature(ready_macro)]
|
#![feature(ready_macro)]
|
||||||
|
#![feature(refcell_take)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(shrink_to)]
|
#![feature(shrink_to)]
|
||||||
|
|
|
@ -219,28 +219,7 @@ fn default_hook(info: &PanicInfo<'_>) {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(local) = set_panic(None) {
|
if let Some(local) = set_panic(None) {
|
||||||
let mut stream = local.lock().unwrap_or_else(|e| e.into_inner());
|
write(&mut *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);
|
|
||||||
|
|
||||||
set_panic(Some(local));
|
set_panic(Some(local));
|
||||||
} else if let Some(mut out) = panic_output() {
|
} else if let Some(mut out) = panic_output() {
|
||||||
write(&mut out);
|
write(&mut out);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::io::{self, set_panic, Write};
|
use std::io::set_panic;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
pub struct A;
|
pub struct A;
|
||||||
|
@ -16,19 +16,8 @@ impl Display for A {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
fn main() {
|
||||||
set_panic(Some(Arc::new(Mutex::new(Sink))));
|
set_panic(Some(Arc::new(Mutex::new(Vec::new()))));
|
||||||
assert!(std::panic::catch_unwind(|| {
|
assert!(std::panic::catch_unwind(|| {
|
||||||
eprintln!("{}", A);
|
eprintln!("{}", A);
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue