about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2017-04-13 10:48:09 -0400
committerZack Weinberg <zackw@panix.com>2017-05-10 09:41:42 -0400
commit07766f675caaabc1d64ef59db6ddfa43e72e6d4f (patch)
treef7d1f4a1d192f2705668b283b4b35cf69063b38c /src
parent76127275a09d970169952bcf616f966faa9ed6db (diff)
downloadrust-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')
-rw-r--r--src/doc/unstable-book/src/SUMMARY.md2
-rw-r--r--src/doc/unstable-book/src/library-features/eprint-internal.md5
-rw-r--r--src/doc/unstable-book/src/library-features/eprint.md13
-rw-r--r--src/libstd/io/mod.rs2
-rw-r--r--src/libstd/io/stdio.rs79
-rw-r--r--src/libstd/macros.rs14
6 files changed, 57 insertions, 58 deletions
diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md
index 3d9e7c7fd86..9229f445297 100644
--- a/src/doc/unstable-book/src/SUMMARY.md
+++ b/src/doc/unstable-book/src/SUMMARY.md
@@ -130,6 +130,8 @@
     - [derive_eq](library-features/derive-eq.md)
     - [discriminant_value](library-features/discriminant-value.md)
     - [error_type_id](library-features/error-type-id.md)
+    - [eprint](library-features/eprint.md)
+    - [eprint_internal](library-features/eprint-internal.md)
     - [exact_size_is_empty](library-features/exact-size-is-empty.md)
     - [fd](library-features/fd.md)
     - [fd_read](library-features/fd-read.md)
diff --git a/src/doc/unstable-book/src/library-features/eprint-internal.md b/src/doc/unstable-book/src/library-features/eprint-internal.md
new file mode 100644
index 00000000000..d3230d8bfa8
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/eprint-internal.md
@@ -0,0 +1,5 @@
+# `eprint_internal`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/eprint.md b/src/doc/unstable-book/src/library-features/eprint.md
new file mode 100644
index 00000000000..69f781b2241
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/eprint.md
@@ -0,0 +1,13 @@
+# `eprint`
+
+The tracking issue for this feature is: [#40528]
+
+[#40528]: https://github.com/rust-lang/rust/issues/40528
+
+------------------------
+
+This feature enables the `eprint!` and `eprintln!` global macros,
+which are just like `print!` and `println!`, respectively, except that
+they send output to the standard _error_ stream, rather than standard
+output.  (`panic!` messages have always been written to standard error.)
+
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")));