Skip to content

Commit 07766f6

Browse files
committed
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.
1 parent 7612727 commit 07766f6

File tree

6 files changed

+57
-58
lines changed

6 files changed

+57
-58
lines changed

src/doc/unstable-book/src/SUMMARY.md

+2
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@
130130
- [derive_eq](library-features/derive-eq.md)
131131
- [discriminant_value](library-features/discriminant-value.md)
132132
- [error_type_id](library-features/error-type-id.md)
133+
- [eprint](library-features/eprint.md)
134+
- [eprint_internal](library-features/eprint-internal.md)
133135
- [exact_size_is_empty](library-features/exact-size-is-empty.md)
134136
- [fd](library-features/fd.md)
135137
- [fd_read](library-features/fd-read.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# `eprint_internal`
2+
3+
This feature is internal to the Rust compiler and is not intended for general use.
4+
5+
------------------------
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# `eprint`
2+
3+
The tracking issue for this feature is: [#40528]
4+
5+
[#40528]: https://github.com/rust-lang/rust/issues/40528
6+
7+
------------------------
8+
9+
This feature enables the `eprint!` and `eprintln!` global macros,
10+
which are just like `print!` and `println!`, respectively, except that
11+
they send output to the standard _error_ stream, rather than standard
12+
output. (`panic!` messages have always been written to standard error.)
13+

src/libstd/io/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat};
290290
pub use self::stdio::{stdin, stdout, stderr, _print, Stdin, Stdout, Stderr};
291291
#[stable(feature = "rust1", since = "1.0.0")]
292292
pub use self::stdio::{StdoutLock, StderrLock, StdinLock};
293-
#[unstable(feature = "eprint", issue="39228")]
293+
#[unstable(feature = "eprint", issue="40528")]
294294
pub use self::stdio::_eprint;
295295
#[unstable(feature = "libstd_io_internals", issue = "0")]
296296
#[doc(no_inline, hidden)]

src/libstd/io/stdio.rs

+29-50
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use io::{self, BufReader, LineWriter};
1717
use sync::{Arc, Mutex, MutexGuard};
1818
use sys::stdio;
1919
use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
20-
use thread::LocalKeyState;
20+
use thread::{LocalKey, LocalKeyState};
2121

2222
/// Stdout used by print! and println! macros
2323
thread_local! {
@@ -659,75 +659,54 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
659659
})
660660
}
661661

662-
#[unstable(feature = "print",
663-
reason = "implementation detail which may disappear or be replaced at any time",
664-
issue = "0")]
665-
#[doc(hidden)]
666-
pub fn _print(args: fmt::Arguments) {
667-
// As an implementation of the `println!` macro, we want to try our best to
668-
// not panic wherever possible and get the output somewhere. There are
669-
// currently two possible vectors for panics we take care of here:
670-
//
671-
// 1. If the TLS key for the local stdout has been destroyed, accessing it
672-
// would cause a panic. Note that we just lump in the uninitialized case
673-
// here for convenience, we're not trying to avoid a panic.
674-
// 2. If the local stdout is currently in use (e.g. we're in the middle of
675-
// already printing) then accessing again would cause a panic.
676-
//
677-
// If, however, the actual I/O causes an error, we do indeed panic.
678-
let result = match LOCAL_STDOUT.state() {
662+
/// Write `args` to output stream `local_s` if possible, `global_s`
663+
/// otherwise. `label` identifies the stream in a panic message.
664+
///
665+
/// This function is used to print error messages, so it takes extra
666+
/// care to avoid causing a panic when `local_stream` is unusable.
667+
/// For instance, if the TLS key for the local stream is uninitialized
668+
/// or already destroyed, or if the local stream is locked by another
669+
/// thread, it will just fall back to the global stream.
670+
///
671+
/// However, if the actual I/O causes an error, this function does panic.
672+
fn print_to<T>(args: fmt::Arguments,
673+
local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>,
674+
global_s: fn() -> T,
675+
label: &str) where T: Write {
676+
let result = match local_s.state() {
679677
LocalKeyState::Uninitialized |
680-
LocalKeyState::Destroyed => stdout().write_fmt(args),
678+
LocalKeyState::Destroyed => global_s().write_fmt(args),
681679
LocalKeyState::Valid => {
682-
LOCAL_STDOUT.with(|s| {
680+
local_s.with(|s| {
683681
if let Ok(mut borrowed) = s.try_borrow_mut() {
684682
if let Some(w) = borrowed.as_mut() {
685683
return w.write_fmt(args);
686684
}
687685
}
688-
stdout().write_fmt(args)
686+
global_s().write_fmt(args)
689687
})
690688
}
691689
};
692690
if let Err(e) = result {
693-
panic!("failed printing to stdout: {}", e);
691+
panic!("failed printing to {}: {}", label, e);
694692
}
695693
}
696694

695+
#[unstable(feature = "print",
696+
reason = "implementation detail which may disappear or be replaced at any time",
697+
issue = "0")]
698+
#[doc(hidden)]
699+
pub fn _print(args: fmt::Arguments) {
700+
print_to(args, &LOCAL_STDOUT, stdout, "stdout");
701+
}
702+
697703
#[unstable(feature = "eprint_internal",
698704
reason = "implementation detail which may disappear or be replaced at any time",
699705
issue = "0")]
700706
#[doc(hidden)]
701707
pub fn _eprint(args: fmt::Arguments) {
702-
// As an implementation of the `eprintln!` macro, we want to try our best to
703-
// not panic wherever possible and get the output somewhere. There are
704-
// currently two possible vectors for panics we take care of here:
705-
//
706-
// 1. If the TLS key for the local stderr has been destroyed, accessing it
707-
// would cause a panic. Note that we just lump in the uninitialized case
708-
// here for convenience, we're not trying to avoid a panic.
709-
// 2. If the local stderr is currently in use (e.g. we're in the middle of
710-
// already printing) then accessing again would cause a panic.
711-
//
712-
// If, however, the actual I/O causes an error, we do indeed panic.
713708
use panicking::LOCAL_STDERR;
714-
let result = match LOCAL_STDERR.state() {
715-
LocalKeyState::Uninitialized |
716-
LocalKeyState::Destroyed => stderr().write_fmt(args),
717-
LocalKeyState::Valid => {
718-
LOCAL_STDERR.with(|s| {
719-
if let Ok(mut borrowed) = s.try_borrow_mut() {
720-
if let Some(w) = borrowed.as_mut() {
721-
return w.write_fmt(args);
722-
}
723-
}
724-
stderr().write_fmt(args)
725-
})
726-
}
727-
};
728-
if let Err(e) = result {
729-
panic!("failed printing to stderr: {}", e);
730-
}
709+
print_to(args, &LOCAL_STDERR, stderr, "stderr");
731710
}
732711

733712
#[cfg(test)]

src/libstd/macros.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ macro_rules! print {
113113
///
114114
/// # Panics
115115
///
116-
/// Panics if writing to `io::stdout()` fails.
116+
/// Panics if writing to `io::stdout` fails.
117117
///
118118
/// # Examples
119119
///
@@ -133,17 +133,17 @@ macro_rules! println {
133133
/// Macro for printing to the standard error.
134134
///
135135
/// Equivalent to the `print!` macro, except that output goes to
136-
/// `io::stderr()` instead of `io::stdout()`. See `print!` for
136+
/// `io::stderr` instead of `io::stdout`. See `print!` for
137137
/// example usage.
138138
///
139139
/// Use `eprint!` only for error and progress messages. Use `print!`
140140
/// instead for the primary output of your program.
141141
///
142142
/// # Panics
143143
///
144-
/// Panics if writing to `io::stderr()` fails.
144+
/// Panics if writing to `io::stderr` fails.
145145
#[macro_export]
146-
#[unstable(feature = "eprint", issue="39228")]
146+
#[unstable(feature = "eprint", issue="40528")]
147147
#[allow_internal_unstable]
148148
macro_rules! eprint {
149149
($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*)));
@@ -152,17 +152,17 @@ macro_rules! eprint {
152152
/// Macro for printing to the standard error, with a newline.
153153
///
154154
/// Equivalent to the `println!` macro, except that output goes to
155-
/// `io::stderr()` instead of `io::stdout()`. See `println!` for
155+
/// `io::stderr` instead of `io::stdout`. See `println!` for
156156
/// example usage.
157157
///
158158
/// Use `eprintln!` only for error and progress messages. Use `println!`
159159
/// instead for the primary output of your program.
160160
///
161161
/// # Panics
162162
///
163-
/// Panics if writing to `io::stderr()` fails.
163+
/// Panics if writing to `io::stderr` fails.
164164
#[macro_export]
165-
#[unstable(feature = "eprint", issue="39228")]
165+
#[unstable(feature = "eprint", issue="40528")]
166166
macro_rules! eprintln {
167167
() => (eprint!("\n"));
168168
($fmt:expr) => (eprint!(concat!($fmt, "\n")));

0 commit comments

Comments
 (0)