From f534b75f050f2daca87c15f6c8d04bf9dc5b68a6 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 3 Nov 2020 21:44:21 +0100 Subject: [PATCH] Use Vec for LOCAL_STD{OUT,ERR} instead of dyn Write. It was only ever used with Vec anyway. This simplifies some things. - It no longer needs to be flushed, because that's a no-op anyway for a Vec. - Writing to a Vec never fails. - No #[cfg(test)] code is needed anymore to use `realstd` instead of `std`, because Vec comes from alloc, not std (like Write). --- compiler/rustc_interface/src/util.rs | 8 +--- library/std/src/io/stdio.rs | 61 +++++++++++----------------- library/std/src/lib.rs | 1 + library/std/src/panicking.rs | 23 +---------- src/test/ui/panic-while-printing.rs | 15 +------ 5 files changed, 29 insertions(+), 79 deletions(-) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index d90fff3bae59a..94a7a5ba79322 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -148,9 +148,7 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals 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 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() }) }; diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index e3e8a7635919c..f6038f4ce11ec 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -16,7 +16,7 @@ use crate::sys_common; use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; use crate::thread::LocalKey; -type LocalStream = Arc>; +type LocalStream = Arc>>; 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) -> Option { // 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) -> Option { // 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, Option) { @@ -956,9 +946,10 @@ pub(crate) fn clone_io() -> (Option, Option) { 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( ) 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 let Err(e) = result { + 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) = global_s().write_fmt(args) { panic!("failed printing to {}: {}", label, e); } } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index bc218b77c878f..a0c2a27438a92 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -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)] diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 9e9584baeb3bc..a5d4d72b00dd8 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -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 { - 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); diff --git a/src/test/ui/panic-while-printing.rs b/src/test/ui/panic-while-printing.rs index 555b90fbd19e5..fa740c5baa816 100644 --- a/src/test/ui/panic-while-printing.rs +++ b/src/test/ui/panic-while-printing.rs @@ -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 @@ impl Display for A { } } -struct Sink; - -impl Write for Sink { - fn write(&mut self, buf: &[u8]) -> io::Result { - 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); })