summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2014-12-27 23:57:43 +0200
committerEduard Burtescu <edy.burt@gmail.com>2014-12-27 23:57:43 +0200
commit647e54d6d154e1a267e84c8ae9f1315e3f9b93fc (patch)
treea25d8f7f938435e2dfcb2056353cbd4c3c3d8a55 /src/libstd
parentfc3f22bf2510dacb1fc4f5422b025a51bfda410e (diff)
downloadrust-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.rs61
-rw-r--r--src/libstd/io/mod.rs42
-rw-r--r--src/libstd/io/stdio.rs20
-rw-r--r--src/libstd/macros.rs136
-rw-r--r--src/libstd/rt/macros.rs18
-rw-r--r--src/libstd/rt/unwind.rs49
-rw-r--r--src/libstd/rt/util.rs15
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> {