about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2017-01-21 13:38:11 -0500
committerZack Weinberg <zackw@panix.com>2017-05-10 09:29:16 -0400
commit76127275a09d970169952bcf616f966faa9ed6db (patch)
treedef3a13636f3b6fa69cc4cf4fe7782da05994082 /src/libstd
parent2b97174ada7fb1854269558ed2cf3b089e58beee (diff)
downloadrust-76127275a09d970169952bcf616f966faa9ed6db.tar.gz
rust-76127275a09d970169952bcf616f966faa9ed6db.zip
Add `eprint!` and `eprintln!` macros to the prelude.
These are exactly the same as `print!` and `println!` except that
they write to stderr instead of stdout.  Issue #39228.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/io/mod.rs2
-rw-r--r--src/libstd/io/stdio.rs36
-rw-r--r--src/libstd/macros.rs45
3 files changed, 83 insertions, 0 deletions
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index e2832873e2e..b6d3c920fb9 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -290,6 +290,8 @@ 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")]
+pub use self::stdio::_eprint;
 #[unstable(feature = "libstd_io_internals", issue = "0")]
 #[doc(no_inline, hidden)]
 pub use self::stdio::{set_panic, set_print};
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 38ad23e14b3..de80cb49804 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -694,6 +694,42 @@ pub fn _print(args: fmt::Arguments) {
     }
 }
 
+#[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);
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use thread;
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index a1f092621cb..d1c304ec46e 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -68,6 +68,9 @@ macro_rules! panic {
 /// necessary to use `io::stdout().flush()` to ensure the output is emitted
 /// immediately.
 ///
+/// Use `print!` only for the primary output of your program.  Use
+/// `eprint!` instead to print error and progress messages.
+///
 /// # Panics
 ///
 /// Panics if writing to `io::stdout()` fails.
@@ -105,6 +108,9 @@ macro_rules! print {
 /// Use the `format!` syntax to write data to the standard output.
 /// See `std::fmt` for more information.
 ///
+/// Use `println!` only for the primary output of your program.  Use
+/// `eprintln!` instead to print error and progress messages.
+///
 /// # Panics
 ///
 /// Panics if writing to `io::stdout()` fails.
@@ -124,6 +130,45 @@ macro_rules! println {
     ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
 }
 
+/// 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
+/// example usage.
+///
+/// Use `eprint!` only for error and progress messages.  Use `print!`
+/// instead for the primary output of your program.
+///
+/// # Panics
+///
+/// Panics if writing to `io::stderr()` fails.
+#[macro_export]
+#[unstable(feature = "eprint", issue="39228")]
+#[allow_internal_unstable]
+macro_rules! eprint {
+    ($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*)));
+}
+
+/// 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
+/// example usage.
+///
+/// Use `eprintln!` only for error and progress messages.  Use `println!`
+/// instead for the primary output of your program.
+///
+/// # Panics
+///
+/// Panics if writing to `io::stderr()` fails.
+#[macro_export]
+#[unstable(feature = "eprint", issue="39228")]
+macro_rules! eprintln {
+    () => (eprint!("\n"));
+    ($fmt:expr) => (eprint!(concat!($fmt, "\n")));
+    ($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*));
+}
+
 /// A macro to select an event from a number of receivers.
 ///
 /// This macro is used to wait for the first event to occur on a number of