diff options
| author | Eduard Burtescu <edy.burt@gmail.com> | 2014-12-27 23:57:43 +0200 |
|---|---|---|
| committer | Eduard Burtescu <edy.burt@gmail.com> | 2014-12-27 23:57:43 +0200 |
| commit | 647e54d6d154e1a267e84c8ae9f1315e3f9b93fc (patch) | |
| tree | a25d8f7f938435e2dfcb2056353cbd4c3c3d8a55 /src/libstd | |
| parent | fc3f22bf2510dacb1fc4f5422b025a51bfda410e (diff) | |
| download | rust-647e54d6d154e1a267e84c8ae9f1315e3f9b93fc.tar.gz rust-647e54d6d154e1a267e84c8ae9f1315e3f9b93fc.zip | |
Fallout of changing format_args!(f, args) to f(format_args!(args)).
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/fmt.rs | 61 | ||||
| -rw-r--r-- | src/libstd/io/mod.rs | 42 | ||||
| -rw-r--r-- | src/libstd/io/stdio.rs | 20 | ||||
| -rw-r--r-- | src/libstd/macros.rs | 136 | ||||
| -rw-r--r-- | src/libstd/rt/macros.rs | 18 | ||||
| -rw-r--r-- | src/libstd/rt/unwind.rs | 49 | ||||
| -rw-r--r-- | src/libstd/rt/util.rs | 15 |
7 files changed, 304 insertions, 37 deletions
diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs index d0c9df9d914..b75cf9a196b 100644 --- a/src/libstd/fmt.rs +++ b/src/libstd/fmt.rs @@ -16,13 +16,6 @@ //! This macro is implemented in the compiler to emit calls to this module in //! order to format arguments at runtime into strings and streams. //! -//! The functions contained in this module should not normally be used in -//! everyday use cases of `format!`. The assumptions made by these functions are -//! unsafe for all inputs, and the compiler performs a large amount of -//! validation on the arguments to `format!` in order to ensure safety at -//! runtime. While it is possible to call these functions directly, it is not -//! recommended to do so in the general case. -//! //! ## Usage //! //! The `format!` macro is intended to be familiar to those coming from C's @@ -275,35 +268,28 @@ //! //! # #[allow(unused_must_use)] //! # fn main() { -//! format_args!(fmt::format, "this returns {}", "String"); +//! fmt::format(format_args!("this returns {}", "String")); //! //! let some_writer: &mut io::Writer = &mut io::stdout(); -//! format_args!(|args| { write!(some_writer, "{}", args) }, -//! "print with a {}", "closure"); +//! write!(some_writer, "{}", format_args!("print with a {}", "macro")); //! -//! fn my_fmt_fn(args: &fmt::Arguments) { +//! fn my_fmt_fn(args: fmt::Arguments) { //! write!(&mut io::stdout(), "{}", args); //! } -//! format_args!(my_fmt_fn, "or a {} too", "function"); +//! my_fmt_fn(format_args!("or a {} too", "function")); //! # } //! ``` //! -//! The first argument of the `format_args!` macro is a function (or closure) -//! which takes one argument of type `&fmt::Arguments`. This structure can then -//! be passed to the `write` and `format` functions inside this module in order -//! to process the format string. The goal of this macro is to even further -//! prevent intermediate allocations when dealing formatting strings. +//! The result of the `format_args!` macro is a value of type `fmt::Arguments`. +//! This structure can then be passed to the `write` and `format` functions +//! inside this module in order to process the format string. +//! The goal of this macro is to even further prevent intermediate allocations +//! when dealing formatting strings. //! //! For example, a logging library could use the standard formatting syntax, but //! it would internally pass around this structure until it has been determined //! where output should go to. //! -//! It is unsafe to programmatically create an instance of `fmt::Arguments` -//! because the operations performed when executing a format string require the -//! compile-time checks provided by the compiler. The `format_args!` macro is -//! the only method of safely creating these structures, but they can be -//! unsafely created with the constructor provided. -//! //! ## Syntax //! //! The syntax for the formatting language used is drawn from other languages, @@ -420,14 +406,39 @@ pub use core::fmt::{Argument, Arguments, write, radix, Radix, RadixFmt}; #[doc(hidden)] pub use core::fmt::{argument, argumentuint}; +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] +/// The format function takes a precompiled format string and a list of +/// arguments, to return the resulting formatted string. +/// +/// # Arguments +/// +/// * args - a structure of arguments generated via the `format_args!` macro. +/// +/// # Example +/// +/// ```rust +/// use std::fmt; +/// +/// let s = fmt::format(format_args!("Hello, {}!", "world")); +/// assert_eq!(s, "Hello, world!".to_string()); +/// ``` +#[experimental = "this is an implementation detail of format! and should not \ + be called directly"] +pub fn format(args: Arguments) -> string::String { + let mut output = Vec::new(); + let _ = write!(&mut output as &mut Writer, "{}", args); + string::String::from_utf8(output).unwrap() +} + +// NOTE(stage0): Remove function after a snapshot +#[cfg(stage0)] /// The format function takes a precompiled format string and a list of /// arguments, to return the resulting formatted string. /// /// # Arguments /// /// * args - a structure of arguments generated via the `format_args!` macro. -/// Because this structure can only be safely generated at -/// compile-time, this function is safe. /// /// # Example /// diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 233ad781093..b6f8bb25b65 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1017,6 +1017,48 @@ pub trait Writer { /// decide whether their stream needs to be buffered or not. fn flush(&mut self) -> IoResult<()> { Ok(()) } + // NOTE(stage0): Remove cfg after a snapshot + #[cfg(not(stage0))] + /// Writes a formatted string into this writer, returning any error + /// encountered. + /// + /// This method is primarily used to interface with the `format_args!` + /// macro, but it is rare that this should explicitly be called. The + /// `write!` macro should be favored to invoke this method instead. + /// + /// # Errors + /// + /// This function will return any I/O error reported while formatting. + fn write_fmt(&mut self, fmt: fmt::Arguments) -> IoResult<()> { + // Create a shim which translates a Writer to a FormatWriter and saves + // off I/O errors. instead of discarding them + struct Adaptor<'a, T:'a> { + inner: &'a mut T, + error: IoResult<()>, + } + + impl<'a, T: Writer> fmt::FormatWriter for Adaptor<'a, T> { + fn write(&mut self, bytes: &[u8]) -> fmt::Result { + match self.inner.write(bytes) { + Ok(()) => Ok(()), + Err(e) => { + self.error = Err(e); + Err(fmt::Error) + } + } + } + } + + let mut output = Adaptor { inner: self, error: Ok(()) }; + match fmt::write(&mut output, fmt) { + Ok(()) => Ok(()), + Err(..) => output.error + } + } + + + // NOTE(stage0): Remove method after a snapshot + #[cfg(stage0)] /// Writes a formatted string into this writer, returning any error /// encountered. /// diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index b7da57fed27..6bd721599f3 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -378,12 +378,32 @@ pub fn println(s: &str) { }) } +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] +/// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible +/// with the `format_args!` macro. +pub fn print_args(fmt: fmt::Arguments) { + with_task_stdout(|io| write!(io, "{}", fmt)) +} + +// NOTE(stage0): Remove function after a snapshot +#[cfg(stage0)] /// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible /// with the `format_args!` macro. pub fn print_args(fmt: &fmt::Arguments) { with_task_stdout(|io| write!(io, "{}", fmt)) } +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] +/// Similar to `println`, but takes a `fmt::Arguments` structure to be +/// compatible with the `format_args!` macro. +pub fn println_args(fmt: fmt::Arguments) { + with_task_stdout(|io| writeln!(io, "{}", fmt)) +} + +// NOTE(stage0): Remove function after a snapshot +#[cfg(stage0)] /// Similar to `println`, but takes a `fmt::Arguments` structure to be /// compatible with the `format_args!` macro. pub fn println_args(fmt: &fmt::Arguments) { diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index d90a47ea4ea..edb6218c5cc 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -17,6 +17,50 @@ #![experimental] #![macro_escape] +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] +/// The entry point for panic of Rust tasks. +/// +/// This macro is used to inject panic into a Rust task, causing the task to +/// unwind and panic entirely. Each task's panic can be reaped as the +/// `Box<Any>` type, and the single-argument form of the `panic!` macro will be +/// the value which is transmitted. +/// +/// The multi-argument form of this macro panics with a string and has the +/// `format!` syntax for building a string. +/// +/// # Example +/// +/// ```should_fail +/// # #![allow(unreachable_code)] +/// panic!(); +/// panic!("this is a terrible mistake!"); +/// panic!(4i); // panic with the value of 4 to be collected elsewhere +/// panic!("this is a {} {message}", "fancy", message = "message"); +/// ``` +#[macro_export] +macro_rules! panic { + () => ({ + panic!("explicit panic") + }); + ($msg:expr) => ({ + // static requires less code at runtime, more constant data + static _FILE_LINE: (&'static str, uint) = (file!(), line!()); + ::std::rt::begin_unwind($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!()); + ::std::rt::begin_unwind_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE) + + }); +} + +// NOTE(stage0): Remove macro after a snapshot +#[cfg(stage0)] /// The entry point for panic of Rust tasks. /// /// This macro is used to inject panic into a Rust task, causing the task to @@ -245,6 +289,26 @@ macro_rules! unimplemented { () => (panic!("not yet implemented")) } +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] +/// Use the syntax described in `std::fmt` to create a value of type `String`. +/// See `std::fmt` for more information. +/// +/// # Example +/// +/// ``` +/// format!("test"); +/// format!("hello {}", "world!"); +/// format!("x = {}, y = {y}", 10i, y = 30i); +/// ``` +#[macro_export] +#[stable] +macro_rules! format { + ($($arg:tt)*) => (::std::fmt::format(format_args!($($arg)*))) +} + +// NOTE(stage0): Remove macro after a snapshot +#[cfg(stage0)] /// Use the syntax described in `std::fmt` to create a value of type `String`. /// See `std::fmt` for more information. /// @@ -263,6 +327,28 @@ macro_rules! format { ) } +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] +/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. +/// See `std::fmt` for more information. +/// +/// # Example +/// +/// ``` +/// # #![allow(unused_must_use)] +/// +/// let mut w = Vec::new(); +/// write!(&mut w, "test"); +/// write!(&mut w, "formatted {}", "arguments"); +/// ``` +#[macro_export] +#[stable] +macro_rules! write { + ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*))) +} + +// NOTE(stage0): Remove macro after a snapshot +#[cfg(stage0)] /// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. /// See `std::fmt` for more information. /// @@ -294,6 +380,18 @@ macro_rules! writeln { ) } +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] +/// Equivalent to the `println!` macro except that a newline is not printed at +/// the end of the message. +#[macro_export] +#[stable] +macro_rules! print { + ($($arg:tt)*) => (::std::io::stdio::print_args(format_args!($($arg)*))) +} + +// NOTE(stage0): Remove macro after a snapshot +#[cfg(stage0)] /// Equivalent to the `println!` macro except that a newline is not printed at /// the end of the message. #[macro_export] @@ -302,6 +400,28 @@ macro_rules! print { ($($arg:tt)*) => (format_args!(::std::io::stdio::print_args, $($arg)*)) } +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] +/// Macro for printing to a task's stdout handle. +/// +/// Each task can override its stdout handle via `std::io::stdio::set_stdout`. +/// The syntax of this macro is the same as that used for `format!`. For more +/// information, see `std::fmt` and `std::io::stdio`. +/// +/// # Example +/// +/// ``` +/// println!("hello there!"); +/// println!("format {} arguments", "some"); +/// ``` +#[macro_export] +#[stable] +macro_rules! println { + ($($arg:tt)*) => (::std::io::stdio::println_args(format_args!($($arg)*))) +} + +// NOTE(stage0): Remove macro after a snapshot +#[cfg(stage0)] /// Macro for printing to a task's stdout handle. /// /// Each task can override its stdout handle via `std::io::stdio::set_stdout`. @@ -411,11 +531,10 @@ macro_rules! log { pub mod builtin { /// The core macro for formatted string creation & output. /// - /// This macro takes as its first argument a callable expression which will - /// receive as its first argument a value of type `&fmt::Arguments`. This - /// value can be passed to the functions in `std::fmt` for performing useful - /// functions. All other formatting macros (`format!`, `write!`, - /// `println!`, etc) are proxied through this one. + /// This macro produces a value of type `fmt::Arguments`. This value can be + /// passed to the functions in `std::fmt` for performing useful functions. + /// All other formatting macros (`format!`, `write!`, `println!`, etc) are + /// proxied through this one. /// /// For more information, see the documentation in `std::fmt`. /// @@ -424,15 +543,12 @@ pub mod builtin { /// ```rust /// use std::fmt; /// - /// let s = format_args!(fmt::format, "hello {}", "world"); + /// let s = fmt::format(format_args!("hello {}", "world")); /// assert_eq!(s, format!("hello {}", "world")); /// - /// format_args!(|args| { - /// // pass `args` to another function, etc. - /// }, "hello {}", "world"); /// ``` #[macro_export] - macro_rules! format_args { ($closure:expr, $fmt:expr $($args:tt)*) => ({ + macro_rules! format_args { ($fmt:expr $($args:tt)*) => ({ /* compiler built-in */ }) } diff --git a/src/libstd/rt/macros.rs b/src/libstd/rt/macros.rs index bee8b5b82f4..095a27203f9 100644 --- a/src/libstd/rt/macros.rs +++ b/src/libstd/rt/macros.rs @@ -15,6 +15,16 @@ #![macro_escape] +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] +macro_rules! rterrln { + ($fmt:expr $($arg:tt)*) => ( { + ::rt::util::dumb_print(format_args!(concat!($fmt, "\n") $($arg)*)) + } ) +} + +// NOTE(stage0): Remove macro after a snapshot +#[cfg(stage0)] macro_rules! rterrln { ($fmt:expr $($arg:tt)*) => ( { format_args!(::rt::util::dumb_print, concat!($fmt, "\n") $($arg)*) @@ -40,6 +50,14 @@ macro_rules! rtassert { } ) } +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] +macro_rules! rtabort { + ($($arg:tt)*) => (::rt::util::abort(format_args!($($arg)*))) +} + +// NOTE(stage0): Remove macro after a snapshot +#[cfg(stage0)] macro_rules! rtabort { ($($arg:tt)*) => (format_args!(::rt::util::abort, $($arg)*)) } diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index eb15a7ba378..261a8335173 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -477,14 +477,61 @@ pub mod eabi { } } -// Entry point of panic from the libcore crate +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] #[cfg(not(test))] +/// Entry point of panic from the libcore crate. +#[lang = "panic_fmt"] +pub extern fn rust_begin_unwind(msg: fmt::Arguments, + file: &'static str, line: uint) -> ! { + begin_unwind_fmt(msg, &(file, line)) +} + +// NOTE(stage0): Remove function after a snapshot +#[cfg(stage0)] +#[cfg(not(test))] +/// Entry point of panic from the libcore crate. #[lang = "panic_fmt"] pub extern fn rust_begin_unwind(msg: &fmt::Arguments, file: &'static str, line: uint) -> ! { begin_unwind_fmt(msg, &(file, line)) } +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] +/// The entry point for unwinding with a formatted message. +/// +/// This is designed to reduce the amount of code required at the call +/// site as much as possible (so that `panic!()` has as low an impact +/// on (e.g.) the inlining of other functions as possible), by moving +/// the actual formatting into this shared place. +#[inline(never)] #[cold] +pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, uint)) -> ! { + use fmt::FormatWriter; + + // We do two allocations here, unfortunately. But (a) they're + // required with the current scheme, and (b) we don't handle + // panic + OOM properly anyway (see comment in begin_unwind + // below). + + struct VecWriter<'a> { v: &'a mut Vec<u8> } + + impl<'a> fmt::FormatWriter for VecWriter<'a> { + fn write(&mut self, buf: &[u8]) -> fmt::Result { + self.v.push_all(buf); + Ok(()) + } + } + + let mut v = Vec::new(); + let _ = write!(&mut VecWriter { v: &mut v }, "{}", msg); + + let msg = box String::from_utf8_lossy(v.as_slice()).into_owned(); + begin_unwind_inner(msg, file_line) +} + +// NOTE(stage0): Remove function after a snapshot +#[cfg(stage0)] /// The entry point for unwinding with a formatted message. /// /// This is designed to reduce the amount of code required at the call diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index d8cd8455deb..26dadfd9fb1 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -112,12 +112,25 @@ impl fmt::FormatWriter for Stdio { } } +// NOTE(stage0): Remove cfg after a snapshot +#[cfg(not(stage0))] +pub fn dumb_print(args: fmt::Arguments) { + let _ = Stderr.write_fmt(args); +} + +// NOTE(stage0): Remove function after a snapshot +#[cfg(stage0)] pub fn dumb_print(args: &fmt::Arguments) { let mut w = Stderr; let _ = write!(&mut w, "{}", args); } -pub fn abort(args: &fmt::Arguments) -> ! { +// NOTE(stage0): Remove wrappers after a snapshot +#[cfg(not(stage0))] pub fn abort(args: fmt::Arguments) -> ! { abort_(&args) } +#[cfg(stage0)] pub fn abort(args: &fmt::Arguments) -> ! { abort_(args) } + +// NOTE(stage0): Change to `pub fn abort(args: fmt::Arguments) -> !` after a snapshot +fn abort_(args: &fmt::Arguments) -> ! { use fmt::FormatWriter; struct BufWriter<'a> { |
