Skip to content

Remove the need for a callback to be passed to format_args! #20136

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

Merged
merged 6 commits into from
Dec 28, 2014
Merged
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
9 changes: 9 additions & 0 deletions src/libcollections/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,15 @@ pub trait ToString {
}

impl<T: fmt::Show> ToString for T {
// NOTE(stage0): Remove cfg after a snapshot
#[cfg(not(stage0))]
fn to_string(&self) -> String {
let mut buf = Vec::<u8>::new();
let _ = fmt::write(&mut buf, format_args!("{}", *self));
String::from_utf8(buf).unwrap()
}
// NOTE(stage0): Remove method after a snapshot
#[cfg(stage0)]
fn to_string(&self) -> String {
let mut buf = Vec::<u8>::new();
let _ = format_args!(|args| fmt::write(&mut buf, args), "{}", self);
Expand Down
7 changes: 7 additions & 0 deletions src/libcore/fmt/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,13 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(

let mut filler = Filler { buf: &mut buf, end: &mut end };
match sign {
// NOTE(stage0): Remove cfg after a snapshot
#[cfg(not(stage0))]
SignNeg => {
let _ = fmt::write(&mut filler, format_args!("{:-}", exp));
}
// NOTE(stage0): Remove match arm after a snapshot
#[cfg(stage0)]
SignNeg => {
let _ = format_args!(|args| {
fmt::write(&mut filler, args)
Expand Down
86 changes: 86 additions & 0 deletions src/libcore/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ pub trait FormatWriter {
/// This function will return an instance of `FormatError` on error.
fn write(&mut self, bytes: &[u8]) -> Result;

// NOTE(stage0): Remove cfg after a snapshot
#[cfg(not(stage0))]
/// Glue for usage of the `write!` macro with implementers of this trait.
///
/// This method should generally not be invoked manually, but rather through
/// the `write!` macro itself.
fn write_fmt(&mut self, args: Arguments) -> Result { write(self, args) }

// NOTE(stage0): Remove method after a snapshot
#[cfg(stage0)]
/// Glue for usage of the `write!` macro with implementers of this trait.
///
/// This method should generally not be invoked manually, but rather through
Expand Down Expand Up @@ -180,6 +190,7 @@ impl<'a> Arguments<'a> {
/// macro validates the format string at compile-time so usage of the `write`
/// and `format` functions can be safely performed.
#[stable]
#[deriving(Copy)]
pub struct Arguments<'a> {
// Format string pieces to print.
pieces: &'a [&'a str],
Expand All @@ -193,6 +204,14 @@ pub struct Arguments<'a> {
}

impl<'a> Show for Arguments<'a> {
// NOTE(stage0): Remove cfg after a snapshot
#[cfg(not(stage0))]
fn fmt(&self, fmt: &mut Formatter) -> Result {
write(fmt.buf, *self)
}

// NOTE(stage0): Remove method after a snapshot
#[cfg(stage0)]
fn fmt(&self, fmt: &mut Formatter) -> Result {
write(fmt.buf, self)
}
Expand Down Expand Up @@ -268,6 +287,63 @@ static DEFAULT_ARGUMENT: rt::Argument<'static> = rt::Argument {
}
};

// NOTE(stage0): Remove cfg after a snapshot
#[cfg(not(stage0))]
/// The `write` function takes an output stream, a precompiled format string,
/// and a list of arguments. The arguments will be formatted according to the
/// specified format string into the output stream provided.
///
/// # Arguments
///
/// * output - the buffer to write output to
/// * args - the precompiled arguments generated by `format_args!`
#[experimental = "libcore and I/O have yet to be reconciled, and this is an \
implementation detail which should not otherwise be exported"]
pub fn write(output: &mut FormatWriter, args: Arguments) -> Result {
let mut formatter = Formatter {
flags: 0,
width: None,
precision: None,
buf: output,
align: rt::AlignUnknown,
fill: ' ',
args: args.args,
curarg: args.args.iter(),
};

let mut pieces = args.pieces.iter();

match args.fmt {
None => {
// We can use default formatting parameters for all arguments.
for _ in range(0, args.args.len()) {
try!(formatter.buf.write(pieces.next().unwrap().as_bytes()));
try!(formatter.run(&DEFAULT_ARGUMENT));
}
}
Some(fmt) => {
// Every spec has a corresponding argument that is preceded by
// a string piece.
for (arg, piece) in fmt.iter().zip(pieces.by_ref()) {
try!(formatter.buf.write(piece.as_bytes()));
try!(formatter.run(arg));
}
}
}

// There can be only one trailing string piece left.
match pieces.next() {
Some(piece) => {
try!(formatter.buf.write(piece.as_bytes()));
}
None => {}
}

Ok(())
}

// NOTE(stage0): Remove function after a snapshot
#[cfg(stage0)]
/// The `write` function takes an output stream, a precompiled format string,
/// and a list of arguments. The arguments will be formatted according to the
/// specified format string into the output stream provided.
Expand Down Expand Up @@ -527,6 +603,16 @@ impl<'a> Formatter<'a> {
self.buf.write(data)
}

// NOTE(stage0): Remove cfg after a snapshot
#[cfg(not(stage0))]
/// Writes some formatted information into this instance
#[unstable = "reconciling core and I/O may alter this definition"]
pub fn write_fmt(&mut self, fmt: Arguments) -> Result {
write(self.buf, fmt)
}

// NOTE(stage0): Remove method after a snapshot
#[cfg(stage0)]
/// Writes some formatted information into this instance
#[unstable = "reconciling core and I/O may alter this definition"]
pub fn write_fmt(&mut self, fmt: &Arguments) -> Result {
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
//! distribution.
//!
//! * `rust_begin_unwind` - This function takes three arguments, a
//! `&fmt::Arguments`, a `&str`, and a `uint`. These three arguments dictate
//! `fmt::Arguments`, a `&str`, and a `uint`. These three arguments dictate
//! the panic message, the file at which panic was invoked, and the line.
//! It is up to consumers of this core library to define this panic
//! function; it is only required to never return.
Expand Down
34 changes: 34 additions & 0 deletions src/libcore/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,30 @@

#![macro_escape]

// NOTE(stage0): Remove cfg after a snapshot
#[cfg(not(stage0))]
/// Entry point of task panic, for details, see std::macros
#[macro_export]
macro_rules! panic {
() => (
panic!("explicit panic")
);
($msg:expr) => ({
static _MSG_FILE_LINE: (&'static str, &'static str, uint) = ($msg, file!(), line!());
::core::panicking::panic(&_MSG_FILE_LINE)
});
($fmt:expr, $($arg:tt)*) => ({
// The leading _'s are to avoid dead code warnings if this is
// used inside a dead function. Just `#[allow(dead_code)]` is
// insufficient, since the user may have
// `#[forbid(dead_code)]` and which cannot be overridden.
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
::core::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE)
});
}

// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
/// Entry point of task panic, for details, see std::macros
#[macro_export]
macro_rules! panic {
Expand Down Expand Up @@ -105,6 +129,16 @@ macro_rules! try {
($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
}

// NOTE(stage0): Remove cfg after a snapshot
#[cfg(not(stage0))]
/// Writing a formatted string into a writer
#[macro_export]
macro_rules! write {
($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*)))
}

// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
/// Writing a formatted string into a writer
#[macro_export]
macro_rules! write {
Expand Down
43 changes: 41 additions & 2 deletions src/libcore/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//! interface for panicking is:
//!
//! ```ignore
//! fn panic_impl(fmt: &fmt::Arguments, &(&'static str, uint)) -> !;
//! fn panic_impl(fmt: fmt::Arguments, &(&'static str, uint)) -> !;
//! ```
//!
//! This definition allows for panicking with any general message, but it does not
Expand All @@ -31,8 +31,20 @@
#![allow(dead_code, missing_docs)]

use fmt;
use intrinsics;
// NOTE(stage0): Remove import after a snapshot
#[cfg(stage0)] use intrinsics;

// NOTE(stage0): Remove cfg after a snapshot
#[cfg(not(stage0))]
#[cold] #[inline(never)] // this is the slow path, always
#[lang="panic"]
pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
let (expr, file, line) = *expr_file_line;
panic_fmt(format_args!("{}", expr), &(file, line))
}

// NOTE(stage0): Remove function after a snapshot
#[cfg(stage0)]
#[cold] #[inline(never)] // this is the slow path, always
#[lang="panic"]
pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
Expand All @@ -45,6 +57,18 @@ pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
unsafe { intrinsics::abort() }
}

// NOTE(stage0): Remove cfg after a snapshot
#[cfg(not(stage0))]
#[cold] #[inline(never)]
#[lang="panic_bounds_check"]
fn panic_bounds_check(file_line: &(&'static str, uint),
index: uint, len: uint) -> ! {
panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
len, index), file_line)
}

// NOTE(stage0): Remove function after a snapshot
#[cfg(stage0)]
#[cold] #[inline(never)]
#[lang="panic_bounds_check"]
fn panic_bounds_check(file_line: &(&'static str, uint),
Expand All @@ -55,6 +79,21 @@ fn panic_bounds_check(file_line: &(&'static str, uint),
unsafe { intrinsics::abort() }
}

// NOTE(stage0): Remove cfg after a snapshot
#[cfg(not(stage0))]
#[cold] #[inline(never)]
pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
#[allow(improper_ctypes)]
extern {
#[lang = "panic_fmt"]
fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: uint) -> !;
}
let (file, line) = *file_line;
unsafe { panic_impl(fmt, file, line) }
}

// NOTE(stage0): Remove function after a snapshot
#[cfg(stage0)]
#[cold] #[inline(never)]
pub fn panic_fmt(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
#[allow(improper_ctypes)]
Expand Down
42 changes: 40 additions & 2 deletions src/liblog/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ impl Drop for DefaultLogger {
}
}

// NOTE(stage0): Remove cfg after a snapshot
#[cfg(not(stage0))]
/// This function is called directly by the compiler when using the logging
/// macros. This function does not take into account whether the log level
/// specified is active or not, it will always log something if this method is
Expand All @@ -276,7 +278,7 @@ impl Drop for DefaultLogger {
/// It is not recommended to call this function directly, rather it should be
/// invoked through the logging family of macros.
#[doc(hidden)]
pub fn log(level: u32, loc: &'static LogLocation, args: &fmt::Arguments) {
pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
// Test the literal string from args against the current filter, if there
// is one.
match unsafe { FILTER.as_ref() } {
Expand All @@ -302,6 +304,42 @@ pub fn log(level: u32, loc: &'static LogLocation, args: &fmt::Arguments) {
set_logger(logger);
}

// NOTE(stage0): Remove function after a snapshot
#[cfg(stage0)]
/// This function is called directly by the compiler when using the logging
/// macros. This function does not take into account whether the log level
/// specified is active or not, it will always log something if this method is
/// called.
///
/// It is not recommended to call this function directly, rather it should be
/// invoked through the logging family of macros.
#[doc(hidden)]
pub fn log(level: u32, loc: &'static LogLocation, args: &fmt::Arguments) {
// Test the literal string from args against the current filter, if there
// is one.
match unsafe { FILTER.as_ref() } {
Some(filter) if !filter.is_match(args.to_string().as_slice()) => return,
_ => {}
}

// Completely remove the local logger from TLS in case anyone attempts to
// frob the slot while we're doing the logging. This will destroy any logger
// set during logging.
let mut logger = LOCAL_LOGGER.with(|s| {
s.borrow_mut().take()
}).unwrap_or_else(|| {
box DefaultLogger { handle: io::stderr() } as Box<Logger + Send>
});
logger.log(&LogRecord {
level: LogLevel(level),
args: *args,
file: loc.file,
module_path: loc.module_path,
line: loc.line,
});
set_logger(logger);
}

/// Getter for the global log level. This is a function so that it can be called
/// safely
#[doc(hidden)]
Expand Down Expand Up @@ -329,7 +367,7 @@ pub struct LogRecord<'a> {
pub level: LogLevel,

/// The arguments from the log line.
pub args: &'a fmt::Arguments<'a>,
pub args: fmt::Arguments<'a>,

/// The file of where the LogRecord originated.
pub file: &'a str,
Expand Down
Loading