@@ -18,14 +18,14 @@ use crate::thread::LocalKey;
1818
1919thread_local ! {
2020 /// Used by the test crate to capture the output of the print! and println! macros.
21- static LOCAL_STDOUT : RefCell <Option <Box <dyn Write + Send >>> = {
21+ static LOCAL_STDOUT : RefCell <Option <Box <dyn LocalOutput >>> = {
2222 RefCell :: new( None )
2323 }
2424}
2525
2626thread_local ! {
2727 /// Used by the test crate to capture the output of the eprint! and eprintln! macros, and panics.
28- static LOCAL_STDERR : RefCell <Option <Box <dyn Write + Send >>> = {
28+ static LOCAL_STDERR : RefCell <Option <Box <dyn LocalOutput >>> = {
2929 RefCell :: new( None )
3030 }
3131}
@@ -888,6 +888,18 @@ impl fmt::Debug for StderrLock<'_> {
888888 }
889889}
890890
891+ /// A writer than can be cloned to new threads.
892+ #[ unstable(
893+ feature = "set_stdio" ,
894+ reason = "this trait may disappear completely or be replaced \
895+ with a more general mechanism",
896+ issue = "none"
897+ ) ]
898+ #[ doc( hidden) ]
899+ pub trait LocalOutput : Write + Send {
900+ fn clone_box ( & self ) -> Box < dyn LocalOutput > ;
901+ }
902+
891903/// Resets the thread-local stderr handle to the specified writer
892904///
893905/// This will replace the current thread's stderr handle, returning the old
@@ -903,7 +915,7 @@ impl fmt::Debug for StderrLock<'_> {
903915 issue = "none"
904916) ]
905917#[ doc( hidden) ]
906- pub fn set_panic ( sink : Option < Box < dyn Write + Send > > ) -> Option < Box < dyn Write + Send > > {
918+ pub fn set_panic ( sink : Option < Box < dyn LocalOutput > > ) -> Option < Box < dyn LocalOutput > > {
907919 use crate :: mem;
908920 if sink. is_none ( ) && !LOCAL_STREAMS . load ( Ordering :: Relaxed ) {
909921 // 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 +
934946 issue = "none"
935947) ]
936948#[ doc( hidden) ]
937- pub fn set_print ( sink : Option < Box < dyn Write + Send > > ) -> Option < Box < dyn Write + Send > > {
949+ pub fn set_print ( sink : Option < Box < dyn LocalOutput > > ) -> Option < Box < dyn LocalOutput > > {
938950 use crate :: mem;
939951 if sink. is_none ( ) && !LOCAL_STREAMS . load ( Ordering :: Relaxed ) {
940952 // 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 +
950962 s
951963}
952964
965+ pub ( crate ) fn clone_io ( ) -> ( Option < Box < dyn LocalOutput > > , Option < Box < dyn LocalOutput > > ) {
966+ // Don't waste time when LOCAL_{STDOUT,STDERR} are definitely None.
967+ if !LOCAL_STREAMS . load ( Ordering :: Relaxed ) {
968+ return ( None , None ) ;
969+ }
970+
971+ LOCAL_STDOUT . with ( |stdout| {
972+ LOCAL_STDERR . with ( |stderr| {
973+ (
974+ stdout. borrow ( ) . as_ref ( ) . map ( |o| o. clone_box ( ) ) ,
975+ stderr. borrow ( ) . as_ref ( ) . map ( |o| o. clone_box ( ) ) ,
976+ )
977+ } )
978+ } )
979+ }
980+
953981/// Write `args` to output stream `local_s` if possible, `global_s`
954982/// otherwise. `label` identifies the stream in a panic message.
955983///
@@ -962,7 +990,7 @@ pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write +
962990/// However, if the actual I/O causes an error, this function does panic.
963991fn print_to < T > (
964992 args : fmt:: Arguments < ' _ > ,
965- local_s : & ' static LocalKey < RefCell < Option < Box < dyn Write + Send > > > > ,
993+ local_s : & ' static LocalKey < RefCell < Option < Box < dyn LocalOutput > > > > ,
966994 global_s : fn ( ) -> T ,
967995 label : & str ,
968996) where
0 commit comments