Io::std{out,err}() and set_{print,panic}()


We are, I hope, nearing completion of the RFC for a println!-alike that writes to stderr. (In an utterly textbook case of the bikeshed effect, there is consensus that the macro should be added, but we are still arguing over what it should be called. :unamused:) In the process, a library wart came up, and I thought I’d split it off and bring it up here.

println! writes to io::stdout - or does it? There is an undocumented, unstable hook, set_print, that redirects println! to an arbitrary io::Write instance. But it only affects println!; other uses of io::stdout are unaffected. And it only affects the thread on which it is called. Similarly, there is a set_panic hook that redirects the output of panic!, assert!, etc, but only for the current thread, and does not affect io::stderr. (As currently planned, it will affect the new println!-alike.)

The question for discussion is: should set_print and set_panic affect io::stdout and io::stderr, and if they do, should it be in a thread-local or process-global fashion?

I do not know what existing users of these functions expect. There is only one use of set_print in the rust core tree, in librustdoc, and frankly I don’t understand what it’s trying to do. There are more uses of set_panic, but they are in conjunction with using the compiler as a library, and I don’t understand the semantics of that.


I’m surprised that such API even exists in Rust. I thought global mutable state was a no-no.

It absolutely shouldn’t be process-global. It’ll become a guaranteed subtle bug for multithreaded programs, like PHP’s setlocale is impossible to use correctly.

set_print is an API trap that PHP has also fallen into: code doing equivalent of set_print(buffer); println!(…); set_print(stdout) breaks when print arguments want to do the same recursively.

Is it possible not to support it for the new function? And maybe even deprecate or remove it for println?


Removing such API should allow fixing


Tracking issue suggests we would like to get rid of these somehow:


Luckily set_print and set_panic are both behind an unstable feature gate, and hidden from the docs, so I don’t think these are or will be called from user-land code anytime soon.

It’s interesting that these are use during testing though to suppress output. I wonder if that could be done with a subprocess instead?


I don’t think we can just take these APIs away without first understanding why they were added, what they are currently being used for, and what alternatives might be possible.

I also think it’s important to keep in mind that not all programs are multithreaded, that programs that are multithreaded generally will have a setup phase in which only one thread exists, and that both Unix and Windows have a great deal of mutable process-global state which we can’t just ignore the existence of. C does give people freopen.