Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provides an alternative print and println macro that don't panic. #29464

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/libstd/io/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,17 +576,25 @@ pub fn set_print(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
issue = "0")]
#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
let result = LOCAL_STDOUT.with(|s| {
let result = _try_print(args);
if let Err(e) = result {
panic!("failed printing to stdout: {}", e);
}
}

#[unstable(feature = "print",
reason = "implementation detail which may disappear or be replaced at any time",
issue = "0")]
#[doc(hidden)]
pub fn _try_print(args: fmt::Arguments) -> io::Result<()> {
LOCAL_STDOUT.with(|s| {
if s.borrow_state() == BorrowState::Unused {
if let Some(w) = s.borrow_mut().as_mut() {
return w.write_fmt(args);
}
}
stdout().write_fmt(args)
});
if let Err(e) = result {
panic!("failed printing to stdout: {}", e);
}
})
}

#[cfg(test)]
Expand Down
52 changes: 52 additions & 0 deletions src/libstd/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,41 @@ macro_rules! print {
($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
}

/// Macro for printing to the standard output.
///
/// Equivalent to the `print!` macro except it does not panic if it fails to
/// write to stdout.
///
/// Note that stdout is frequently line-buffered by default so it may be
/// necessary to use `io::stdout().flush()` to ensure the output is emitted
/// immediately.
///
///
/// # Examples
///
/// ```
/// use std::io::{self, Write};
///
/// try_print!("this ").unwrap();
/// try_print!("will ").unwrap();
/// try_print!("be ").unwrap();
/// try_print!("on ").unwrap();
/// try_print!("the ").unwrap();
/// try_print!("same ").unwrap();
/// try_print!("line ").unwrap();
///
/// io::stdout().flush().unwrap();
///
/// try_print!("this string has a newline, why not choose println! instead?\n").unwrap();
///
/// io::stdout().flush().unwrap();
/// ```
#[macro_export]
#[allow_internal_unstable]
macro_rules! try_print {
($($arg:tt)*) => ($crate::io::_try_print(format_args!($($arg)*)));
}

/// Macro for printing to the standard output, with a newline.
///
/// Use the `format!` syntax to write data to the standard output.
Expand All @@ -120,6 +155,23 @@ macro_rules! println {
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}

/// Macro for printing to the standard output, with a newline.
///
/// Use the `format!` syntax to write data to the standard output.
/// See `std::fmt` for more information.
///
/// # Examples
///
/// ```
/// try_println!("hello there!").unwrap();
/// try_println!("format {} arguments", "some").unwrap();
/// ```
#[macro_export]
macro_rules! try_println {
($fmt:expr) => (try_print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (try_print!(concat!($fmt, "\n"), $($arg)*));
}

/// Helper macro for unwrapping `Result` values while returning early with an
/// error if the value of the expression is `Err`. Can only be used in
/// functions that return `Result` because of the early return of `Err` that
Expand Down