@@ -18,14 +18,14 @@ use crate::thread::LocalKey;
18
18
19
19
thread_local ! {
20
20
/// 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 >>> = {
22
22
RefCell :: new( None )
23
23
}
24
24
}
25
25
26
26
thread_local ! {
27
27
/// 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 >>> = {
29
29
RefCell :: new( None )
30
30
}
31
31
}
@@ -888,6 +888,18 @@ impl fmt::Debug for StderrLock<'_> {
888
888
}
889
889
}
890
890
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
+
891
903
/// Resets the thread-local stderr handle to the specified writer
892
904
///
893
905
/// This will replace the current thread's stderr handle, returning the old
@@ -903,7 +915,7 @@ impl fmt::Debug for StderrLock<'_> {
903
915
issue = "none"
904
916
) ]
905
917
#[ 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 > > {
907
919
use crate :: mem;
908
920
if sink. is_none ( ) && !LOCAL_STREAMS . load ( Ordering :: Relaxed ) {
909
921
// 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 +
934
946
issue = "none"
935
947
) ]
936
948
#[ 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 > > {
938
950
use crate :: mem;
939
951
if sink. is_none ( ) && !LOCAL_STREAMS . load ( Ordering :: Relaxed ) {
940
952
// 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 +
950
962
s
951
963
}
952
964
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
+
953
981
/// Write `args` to output stream `local_s` if possible, `global_s`
954
982
/// otherwise. `label` identifies the stream in a panic message.
955
983
///
@@ -962,7 +990,7 @@ pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write +
962
990
/// However, if the actual I/O causes an error, this function does panic.
963
991
fn print_to < T > (
964
992
args : fmt:: Arguments < ' _ > ,
965
- local_s : & ' static LocalKey < RefCell < Option < Box < dyn Write + Send > > > > ,
993
+ local_s : & ' static LocalKey < RefCell < Option < Box < dyn LocalOutput > > > > ,
966
994
global_s : fn ( ) -> T ,
967
995
label : & str ,
968
996
) where
0 commit comments