about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2020-11-03 21:44:21 +0100
committerMara Bos <m-ou.se@m-ou.se>2020-11-10 21:58:09 +0100
commitf534b75f050f2daca87c15f6c8d04bf9dc5b68a6 (patch)
tree955d68e656130dbaf65cd0ac2f220c9911c2ed0a
parentccbce1d3b2b9f74619d19c6d3377d20dd06e0050 (diff)
downloadrust-f534b75f050f2daca87c15f6c8d04bf9dc5b68a6.tar.gz
rust-f534b75f050f2daca87c15f6c8d04bf9dc5b68a6.zip
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).
-rw-r--r--compiler/rustc_interface/src/util.rs8
-rw-r--r--library/std/src/io/stdio.rs61
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/panicking.rs23
-rw-r--r--src/test/ui/panic-while-printing.rs15
5 files changed, 29 insertions, 79 deletions
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index d90fff3bae5..94a7a5ba793 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<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()
                 })
             };
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index e3e8a763591..f6038f4ce11 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<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 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 bc218b77c87..a0c2a27438a 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 9e9584baeb3..a5d4d72b00d 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<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);
diff --git a/src/test/ui/panic-while-printing.rs b/src/test/ui/panic-while-printing.rs
index 555b90fbd19..fa740c5baa8 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<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);
     })