about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/ffi/c_str.rs3
-rw-r--r--library/std/src/io/impls.rs6
-rw-r--r--library/std/src/io/mod.rs4
-rw-r--r--library/std/src/io/stdio.rs38
-rw-r--r--library/std/src/panicking.rs2
-rw-r--r--library/std/src/path.rs11
-rw-r--r--library/std/src/thread/mod.rs5
7 files changed, 52 insertions, 17 deletions
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index 6df4eb99259..8c6d6c80402 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -110,6 +110,7 @@ use crate::sys;
 /// of `CString` instances can lead to invalid memory accesses, memory leaks,
 /// and other memory errors.
 #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "cstring_type")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct CString {
     // Invariant 1: the slice ends with a zero byte and has a length of at least one.
@@ -1265,7 +1266,7 @@ impl CStr {
     /// behavior when `ptr` is used inside the `unsafe` block:
     ///
     /// ```no_run
-    /// # #![allow(unused_must_use)]
+    /// # #![allow(unused_must_use)] #![cfg_attr(not(bootstrap), allow(temporary_cstring_as_ptr))]
     /// use std::ffi::CString;
     ///
     /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs
index e09e7ba978e..66426101d27 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -213,13 +213,13 @@ impl<B: BufRead + ?Sized> BufRead for Box<B> {
 #[cfg(test)]
 /// This impl is only used by printing logic, so any error returned is always
 /// of kind `Other`, and should be ignored.
-impl Write for Box<dyn (::realstd::io::Write) + Send> {
+impl Write for dyn ::realstd::io::LocalOutput {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        (**self).write(buf).map_err(|_| ErrorKind::Other.into())
+        (*self).write(buf).map_err(|_| ErrorKind::Other.into())
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        (**self).flush().map_err(|_| ErrorKind::Other.into())
+        (*self).flush().map_err(|_| ErrorKind::Other.into())
     }
 }
 
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index d9d03807819..e6efe6ec57e 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -277,10 +277,12 @@ pub use self::stdio::{StderrLock, StdinLock, StdoutLock};
 pub use self::stdio::{_eprint, _print};
 #[unstable(feature = "libstd_io_internals", issue = "42788")]
 #[doc(no_inline, hidden)]
-pub use self::stdio::{set_panic, set_print};
+pub use self::stdio::{set_panic, set_print, LocalOutput};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::util::{copy, empty, repeat, sink, Empty, Repeat, Sink};
 
+pub(crate) use self::stdio::clone_io;
+
 mod buffered;
 mod cursor;
 mod error;
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 36b49401591..2eb5fb45286 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -18,14 +18,14 @@ use crate::thread::LocalKey;
 
 thread_local! {
     /// Used by the test crate to capture the output of the print! and println! macros.
-    static LOCAL_STDOUT: RefCell<Option<Box<dyn Write + Send>>> = {
+    static LOCAL_STDOUT: RefCell<Option<Box<dyn LocalOutput>>> = {
         RefCell::new(None)
     }
 }
 
 thread_local! {
     /// Used by the test crate to capture the output of the eprint! and eprintln! macros, and panics.
-    static LOCAL_STDERR: RefCell<Option<Box<dyn Write + Send>>> = {
+    static LOCAL_STDERR: RefCell<Option<Box<dyn LocalOutput>>> = {
         RefCell::new(None)
     }
 }
@@ -888,6 +888,18 @@ impl fmt::Debug for StderrLock<'_> {
     }
 }
 
+/// A writer than can be cloned to new threads.
+#[unstable(
+    feature = "set_stdio",
+    reason = "this trait may disappear completely or be replaced \
+                     with a more general mechanism",
+    issue = "none"
+)]
+#[doc(hidden)]
+pub trait LocalOutput: Write + Send {
+    fn clone_box(&self) -> Box<dyn LocalOutput>;
+}
+
 /// Resets the thread-local stderr handle to the specified writer
 ///
 /// This will replace the current thread's stderr handle, returning the old
@@ -903,7 +915,7 @@ impl fmt::Debug for StderrLock<'_> {
     issue = "none"
 )]
 #[doc(hidden)]
-pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
+pub fn set_panic(sink: Option<Box<dyn LocalOutput>>) -> Option<Box<dyn LocalOutput>> {
     use crate::mem;
     if sink.is_none() && !LOCAL_STREAMS.load(Ordering::Relaxed) {
         // LOCAL_STDERR is definitely None since LOCAL_STREAMS is false.
@@ -934,7 +946,7 @@ pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write +
     issue = "none"
 )]
 #[doc(hidden)]
-pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
+pub fn set_print(sink: Option<Box<dyn LocalOutput>>) -> Option<Box<dyn LocalOutput>> {
     use crate::mem;
     if sink.is_none() && !LOCAL_STREAMS.load(Ordering::Relaxed) {
         // LOCAL_STDOUT is definitely None since LOCAL_STREAMS is false.
@@ -950,6 +962,22 @@ pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write +
     s
 }
 
+pub(crate) fn clone_io() -> (Option<Box<dyn LocalOutput>>, Option<Box<dyn LocalOutput>>) {
+    // Don't waste time when LOCAL_{STDOUT,STDERR} are definitely None.
+    if !LOCAL_STREAMS.load(Ordering::Relaxed) {
+        return (None, None);
+    }
+
+    LOCAL_STDOUT.with(|stdout| {
+        LOCAL_STDERR.with(|stderr| {
+            (
+                stdout.borrow().as_ref().map(|o| o.clone_box()),
+                stderr.borrow().as_ref().map(|o| o.clone_box()),
+            )
+        })
+    })
+}
+
 /// Write `args` to output stream `local_s` if possible, `global_s`
 /// otherwise. `label` identifies the stream in a panic message.
 ///
@@ -962,7 +990,7 @@ pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write +
 /// However, if the actual I/O causes an error, this function does panic.
 fn print_to<T>(
     args: fmt::Arguments<'_>,
-    local_s: &'static LocalKey<RefCell<Option<Box<dyn Write + Send>>>>,
+    local_s: &'static LocalKey<RefCell<Option<Box<dyn LocalOutput>>>>,
     global_s: fn() -> T,
     label: &str,
 ) where
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 221ae809e23..fbbc61f4e60 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -220,7 +220,7 @@ fn default_hook(info: &PanicInfo<'_>) {
 
     if let Some(mut local) = set_panic(None) {
         // NB. In `cfg(test)` this uses the forwarding impl
-        // for `Box<dyn (::realstd::io::Write) + Send>`.
+        // for `dyn ::realstd::io::LocalOutput`.
         write(&mut local);
         set_panic(Some(local));
     } else if let Some(mut out) = panic_output() {
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 50bd2a03b62..8a75c1d6058 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -446,7 +446,7 @@ impl Hash for PrefixComponent<'_> {
 /// (`/` or `\`).
 ///
 /// This `enum` is created by iterating over [`Components`], which in turn is
-/// created by the [`components`][`Path::components`] method on [`Path`].
+/// created by the [`components`](Path::components) method on [`Path`].
 ///
 /// # Examples
 ///
@@ -1319,7 +1319,7 @@ impl PathBuf {
         self.inner
     }
 
-    /// Converts this `PathBuf` into a [boxed][`Box`] [`Path`].
+    /// Converts this `PathBuf` into a [boxed](Box) [`Path`].
     #[stable(feature = "into_boxed_path", since = "1.20.0")]
     pub fn into_boxed_path(self) -> Box<Path> {
         let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut Path;
@@ -1686,8 +1686,7 @@ pub struct Path {
     inner: OsStr,
 }
 
-/// An error returned from [`Path::strip_prefix`][`strip_prefix`] if the prefix
-/// was not found.
+/// An error returned from [`Path::strip_prefix`] if the prefix was not found.
 ///
 /// This `struct` is created by the [`strip_prefix`] method on [`Path`].
 /// See its documentation for more.
@@ -2470,7 +2469,7 @@ impl Path {
         fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
     }
 
-    /// Converts a [`Box<Path>`][`Box`] into a [`PathBuf`] without copying or
+    /// Converts a [`Box<Path>`](Box) into a [`PathBuf`] without copying or
     /// allocating.
     #[stable(feature = "into_boxed_path", since = "1.20.0")]
     pub fn into_path_buf(self: Box<Path>) -> PathBuf {
@@ -2498,7 +2497,7 @@ impl fmt::Debug for Path {
 ///
 /// A [`Path`] might contain non-Unicode data. This `struct` implements the
 /// [`Display`] trait in a way that mitigates that. It is created by the
-/// [`display`][`Path::display`] method on [`Path`].
+/// [`display`](Path::display) method on [`Path`].
 ///
 /// # Examples
 ///
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 45c10266ba2..bdb8fc7807b 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -457,11 +457,16 @@ impl Builder {
         let my_packet: Arc<UnsafeCell<Option<Result<T>>>> = Arc::new(UnsafeCell::new(None));
         let their_packet = my_packet.clone();
 
+        let (stdout, stderr) = crate::io::clone_io();
+
         let main = move || {
             if let Some(name) = their_thread.cname() {
                 imp::Thread::set_name(name);
             }
 
+            crate::io::set_print(stdout);
+            crate::io::set_panic(stderr);
+
             // SAFETY: the stack guard passed is the one for the current thread.
             // This means the current thread's stack and the new thread's stack
             // are properly set and protected from each other.