diff options
| author | Zack Weinberg <zackw@panix.com> | 2017-04-13 10:48:09 -0400 |
|---|---|---|
| committer | Zack Weinberg <zackw@panix.com> | 2017-05-10 09:41:42 -0400 |
| commit | 07766f675caaabc1d64ef59db6ddfa43e72e6d4f (patch) | |
| tree | f7d1f4a1d192f2705668b283b4b35cf69063b38c /src/libstd | |
| parent | 76127275a09d970169952bcf616f966faa9ed6db (diff) | |
| download | rust-07766f675caaabc1d64ef59db6ddfa43e72e6d4f.tar.gz rust-07766f675caaabc1d64ef59db6ddfa43e72e6d4f.zip | |
Revise the eprint(ln)! feature.
* Factor out the nigh-identical bodies of `_print` and `_eprint` to a helper function `print_to` (I was sorely tempted to call it `_doprnt`). * Update the issue number for the unstable `eprint` feature. * Add entries to the "unstable book" for `eprint` and `eprint_internal`. * Style corrections to the documentation.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/io/mod.rs | 2 | ||||
| -rw-r--r-- | src/libstd/io/stdio.rs | 79 | ||||
| -rw-r--r-- | src/libstd/macros.rs | 14 |
3 files changed, 37 insertions, 58 deletions
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index b6d3c920fb9..9320bfe9abe 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -290,7 +290,7 @@ pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat}; pub use self::stdio::{stdin, stdout, stderr, _print, Stdin, Stdout, Stderr}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::stdio::{StdoutLock, StderrLock, StdinLock}; -#[unstable(feature = "eprint", issue="39228")] +#[unstable(feature = "eprint", issue="40528")] pub use self::stdio::_eprint; #[unstable(feature = "libstd_io_internals", issue = "0")] #[doc(no_inline, hidden)] diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index de80cb49804..363c99c666e 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -17,7 +17,7 @@ use io::{self, BufReader, LineWriter}; use sync::{Arc, Mutex, MutexGuard}; use sys::stdio; use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; -use thread::LocalKeyState; +use thread::{LocalKey, LocalKeyState}; /// Stdout used by print! and println! macros thread_local! { @@ -659,75 +659,54 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> { }) } -#[unstable(feature = "print", - reason = "implementation detail which may disappear or be replaced at any time", - issue = "0")] -#[doc(hidden)] -pub fn _print(args: fmt::Arguments) { - // As an implementation of the `println!` macro, we want to try our best to - // not panic wherever possible and get the output somewhere. There are - // currently two possible vectors for panics we take care of here: - // - // 1. If the TLS key for the local stdout has been destroyed, accessing it - // would cause a panic. Note that we just lump in the uninitialized case - // here for convenience, we're not trying to avoid a panic. - // 2. If the local stdout is currently in use (e.g. we're in the middle of - // already printing) then accessing again would cause a panic. - // - // If, however, the actual I/O causes an error, we do indeed panic. - let result = match LOCAL_STDOUT.state() { +/// Write `args` to output stream `local_s` if possible, `global_s` +/// otherwise. `label` identifies the stream in a panic message. +/// +/// This function is used to print error messages, so it takes extra +/// care to avoid causing a panic when `local_stream` is unusable. +/// For instance, if the TLS key for the local stream is uninitialized +/// or already destroyed, or if the local stream is locked by another +/// thread, it will just fall back to the global stream. +/// +/// 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<Write+Send>>>>, + global_s: fn() -> T, + label: &str) where T: Write { + let result = match local_s.state() { LocalKeyState::Uninitialized | - LocalKeyState::Destroyed => stdout().write_fmt(args), + LocalKeyState::Destroyed => global_s().write_fmt(args), LocalKeyState::Valid => { - LOCAL_STDOUT.with(|s| { + local_s.with(|s| { if let Ok(mut borrowed) = s.try_borrow_mut() { if let Some(w) = borrowed.as_mut() { return w.write_fmt(args); } } - stdout().write_fmt(args) + global_s().write_fmt(args) }) } }; if let Err(e) = result { - panic!("failed printing to stdout: {}", e); + panic!("failed printing to {}: {}", label, e); } } +#[unstable(feature = "print", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "0")] +#[doc(hidden)] +pub fn _print(args: fmt::Arguments) { + print_to(args, &LOCAL_STDOUT, stdout, "stdout"); +} + #[unstable(feature = "eprint_internal", reason = "implementation detail which may disappear or be replaced at any time", issue = "0")] #[doc(hidden)] pub fn _eprint(args: fmt::Arguments) { - // As an implementation of the `eprintln!` macro, we want to try our best to - // not panic wherever possible and get the output somewhere. There are - // currently two possible vectors for panics we take care of here: - // - // 1. If the TLS key for the local stderr has been destroyed, accessing it - // would cause a panic. Note that we just lump in the uninitialized case - // here for convenience, we're not trying to avoid a panic. - // 2. If the local stderr is currently in use (e.g. we're in the middle of - // already printing) then accessing again would cause a panic. - // - // If, however, the actual I/O causes an error, we do indeed panic. use panicking::LOCAL_STDERR; - let result = match LOCAL_STDERR.state() { - LocalKeyState::Uninitialized | - LocalKeyState::Destroyed => stderr().write_fmt(args), - LocalKeyState::Valid => { - LOCAL_STDERR.with(|s| { - if let Ok(mut borrowed) = s.try_borrow_mut() { - if let Some(w) = borrowed.as_mut() { - return w.write_fmt(args); - } - } - stderr().write_fmt(args) - }) - } - }; - if let Err(e) = result { - panic!("failed printing to stderr: {}", e); - } + print_to(args, &LOCAL_STDERR, stderr, "stderr"); } #[cfg(test)] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index d1c304ec46e..98c635d127f 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -113,7 +113,7 @@ macro_rules! print { /// /// # Panics /// -/// Panics if writing to `io::stdout()` fails. +/// Panics if writing to `io::stdout` fails. /// /// # Examples /// @@ -133,7 +133,7 @@ macro_rules! println { /// Macro for printing to the standard error. /// /// Equivalent to the `print!` macro, except that output goes to -/// `io::stderr()` instead of `io::stdout()`. See `print!` for +/// `io::stderr` instead of `io::stdout`. See `print!` for /// example usage. /// /// Use `eprint!` only for error and progress messages. Use `print!` @@ -141,9 +141,9 @@ macro_rules! println { /// /// # Panics /// -/// Panics if writing to `io::stderr()` fails. +/// Panics if writing to `io::stderr` fails. #[macro_export] -#[unstable(feature = "eprint", issue="39228")] +#[unstable(feature = "eprint", issue="40528")] #[allow_internal_unstable] macro_rules! eprint { ($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*))); @@ -152,7 +152,7 @@ macro_rules! eprint { /// Macro for printing to the standard error, with a newline. /// /// Equivalent to the `println!` macro, except that output goes to -/// `io::stderr()` instead of `io::stdout()`. See `println!` for +/// `io::stderr` instead of `io::stdout`. See `println!` for /// example usage. /// /// Use `eprintln!` only for error and progress messages. Use `println!` @@ -160,9 +160,9 @@ macro_rules! eprint { /// /// # Panics /// -/// Panics if writing to `io::stderr()` fails. +/// Panics if writing to `io::stderr` fails. #[macro_export] -#[unstable(feature = "eprint", issue="39228")] +#[unstable(feature = "eprint", issue="40528")] macro_rules! eprintln { () => (eprint!("\n")); ($fmt:expr) => (eprint!(concat!($fmt, "\n"))); |
