diff options
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/ffi/c_str.rs | 3 | ||||
| -rw-r--r-- | library/std/src/io/impls.rs | 6 | ||||
| -rw-r--r-- | library/std/src/io/mod.rs | 4 | ||||
| -rw-r--r-- | library/std/src/io/stdio.rs | 38 | ||||
| -rw-r--r-- | library/std/src/panicking.rs | 2 | ||||
| -rw-r--r-- | library/std/src/path.rs | 11 | ||||
| -rw-r--r-- | library/std/src/thread/mod.rs | 5 |
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. |
