about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-12-28 03:11:48 +0000
committerbors <bors@rust-lang.org>2014-12-28 03:11:48 +0000
commit3e6b29f8ad1ddfcb134d743a66ee5f467e16c350 (patch)
treedfd36279301f37402264995a2d25a5d21eb38464 /src
parent070ab63807dc80fa6a6c5ee80531284761ab42de (diff)
parent647e54d6d154e1a267e84c8ae9f1315e3f9b93fc (diff)
downloadrust-3e6b29f8ad1ddfcb134d743a66ee5f467e16c350.tar.gz
rust-3e6b29f8ad1ddfcb134d743a66ee5f467e16c350.zip
auto merge of #20136 : eddyb/rust/format-args, r=alexcrichton
We have the technology: no longer do you need to write closures to use `format_args!`.
This is a `[breaking-change]`, as it forces you to clean up old hacks - if you had code like this:
```rust
format_args!(fmt::format, "{} {} {}", a, b, c)
format_args!(|args| { w.write_fmt(args) }, "{} {} {}", x, y, z)
```
change it to this: 
```rust
fmt::format(format_args!("{} {} {}", a, b, c))
w.write_fmt(format_args!("{} {} {}", x, y, z))
```
To allow them to be called with `format_args!(...)` directly, several functions were modified to
take `fmt::Arguments` by value instead of by reference. Also, `fmt::Arguments` derives `Copy`
now in order to preserve all usecases that were previously possible.
Diffstat (limited to 'src')
-rw-r--r--src/libcollections/string.rs9
-rw-r--r--src/libcore/fmt/float.rs7
-rw-r--r--src/libcore/fmt/mod.rs86
-rw-r--r--src/libcore/lib.rs2
-rw-r--r--src/libcore/macros.rs34
-rw-r--r--src/libcore/panicking.rs43
-rw-r--r--src/liblog/lib.rs42
-rw-r--r--src/liblog/macros.rs57
-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
-rw-r--r--src/libsyntax/ext/deriving/show.rs10
-rw-r--r--src/libsyntax/ext/format.rs236
-rw-r--r--src/test/compile-fail/dead-code-closure-bang.rs2
-rw-r--r--src/test/compile-fail/ifmt-bad-format-args.rs6
-rw-r--r--src/test/compile-fail/ifmt-bad-format-args2.rs13
-rw-r--r--src/test/pretty/issue-4264.pp64
-rw-r--r--src/test/run-pass/ifmt.rs12
22 files changed, 726 insertions, 238 deletions
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index 6c2659b13f7..9460b9a8966 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -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);
diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs
index 55a87973e0f..47701ab8ffd 100644
--- a/src/libcore/fmt/float.rs
+++ b/src/libcore/fmt/float.rs
@@ -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)
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index fb26450ec75..b050b98de2f 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -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
@@ -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],
@@ -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)
     }
@@ -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.
@@ -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 {
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 9de723f38ee..6d0d6e0817a 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -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.
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 7ce1da7d2d0..2cd9e7c4509 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -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 {
@@ -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 {
diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index fd0526db411..32f09a4c17f 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -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
@@ -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)) -> ! {
@@ -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),
@@ -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)]
diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs
index 97301628a45..1d865868f18 100644
--- a/src/liblog/lib.rs
+++ b/src/liblog/lib.rs
@@ -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
@@ -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() } {
@@ -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)]
@@ -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,
diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs
index 8b2cfcd420a..2e8302cc10f 100644
--- a/src/liblog/macros.rs
+++ b/src/liblog/macros.rs
@@ -12,6 +12,63 @@
 
 #![macro_escape]
 
+// NOTE(stage0): Remove cfg after a snapshot
+#[cfg(not(stage0))]
+/// The standard logging macro
+///
+/// This macro will generically log over a provided level (of type u32) with a
+/// format!-based argument list. See documentation in `std::fmt` for details on
+/// how to use the syntax.
+///
+/// # Example
+///
+/// ```
+/// #![feature(phase)]
+/// #[phase(plugin, link)] extern crate log;
+///
+/// fn main() {
+///     log!(log::WARN, "this is a warning {}", "message");
+///     log!(log::DEBUG, "this is a debug message");
+///     log!(6, "this is a custom logging level: {level}", level=6u);
+/// }
+/// ```
+///
+/// Assumes the binary is `main`:
+///
+/// ```{.bash}
+/// $ RUST_LOG=warn ./main
+/// WARN:main: this is a warning message
+/// ```
+///
+/// ```{.bash}
+/// $ RUST_LOG=debug ./main
+/// DEBUG:main: this is a debug message
+/// WARN:main: this is a warning message
+/// ```
+///
+/// ```{.bash}
+/// $ RUST_LOG=6 ./main
+/// DEBUG:main: this is a debug message
+/// WARN:main: this is a warning message
+/// 6:main: this is a custom logging level: 6
+/// ```
+#[macro_export]
+macro_rules! log {
+    ($lvl:expr, $($arg:tt)+) => ({
+        static LOC: ::log::LogLocation = ::log::LogLocation {
+            line: line!(),
+            file: file!(),
+            module_path: module_path!(),
+        };
+        let lvl = $lvl;
+        if log_enabled!(lvl) {
+            ::log::log(lvl, &LOC, format_args!($($arg)+))
+        }
+    })
+}
+
+// NOTE(stage0): Remove macro after a snapshot
+#[cfg(stage0)]
 /// The standard logging macro
 ///
 /// This macro will generically log over a provided level (of type u32) with a
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> {
diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs
index 19b45a1e610..2788c89676a 100644
--- a/src/libsyntax/ext/deriving/show.rs
+++ b/src/libsyntax/ext/deriving/show.rs
@@ -131,8 +131,10 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
     let format_string = cx.expr_str(span, s);
 
     // phew, not our responsibility any more!
-    format::expand_preparsed_format_args(cx, span,
-                                         format::MethodCall(formatter, meth),
-                                         format_string, exprs, Vec::new(),
-                                         HashMap::new())
+
+    let args = vec![
+        format::expand_preparsed_format_args(cx, span, format_string,
+                                             exprs, vec![], HashMap::new())
+    ];
+    cx.expr_method_call(span, formatter, meth, args)
 }
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index aad4045f00a..6474d92953f 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::Invocation::*;
 use self::ArgumentType::*;
 use self::Position::*;
 
@@ -23,17 +22,16 @@ use parse::token;
 use ptr::P;
 
 use std::collections::HashMap;
-use std::string;
 
 #[deriving(PartialEq)]
 enum ArgumentType {
-    Known(string::String),
+    Known(String),
     Unsigned
 }
 
 enum Position {
     Exact(uint),
-    Named(string::String),
+    Named(String),
 }
 
 struct Context<'a, 'b:'a> {
@@ -48,12 +46,12 @@ struct Context<'a, 'b:'a> {
     /// Note that we keep a side-array of the ordering of the named arguments
     /// found to be sure that we can translate them in the same order that they
     /// were declared in.
-    names: HashMap<string::String, P<ast::Expr>>,
-    name_types: HashMap<string::String, ArgumentType>,
-    name_ordering: Vec<string::String>,
+    names: HashMap<String, P<ast::Expr>>,
+    name_types: HashMap<String, ArgumentType>,
+    name_ordering: Vec<String>,
 
     /// The latest consecutive literal strings, or empty if there weren't any.
-    literal: string::String,
+    literal: String,
 
     /// Collection of the compiled `rt::Argument` structures
     pieces: Vec<P<ast::Expr>>,
@@ -62,62 +60,40 @@ struct Context<'a, 'b:'a> {
     /// Stays `true` if all formatting parameters are default (as in "{}{}").
     all_pieces_simple: bool,
 
-    name_positions: HashMap<string::String, uint>,
-    method_statics: Vec<P<ast::Item>>,
+    name_positions: HashMap<String, uint>,
 
     /// Updated as arguments are consumed or methods are entered
     nest_level: uint,
     next_arg: uint,
 }
 
-pub enum Invocation {
-    Call(P<ast::Expr>),
-    MethodCall(P<ast::Expr>, ast::Ident),
-}
-
 /// Parses the arguments from the given list of tokens, returning None
 /// if there's a parse error so we can continue parsing other format!
 /// expressions.
 ///
-/// If parsing succeeds, the second return value is:
+/// If parsing succeeds, the return value is:
 ///
 ///     Some((fmtstr, unnamed arguments, ordering of named arguments,
 ///           named arguments))
-fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool,
-              tts: &[ast::TokenTree])
-    -> (Invocation, Option<(P<ast::Expr>, Vec<P<ast::Expr>>, Vec<string::String>,
-                            HashMap<string::String, P<ast::Expr>>)>) {
+fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+              -> Option<(P<ast::Expr>, Vec<P<ast::Expr>>, Vec<String>,
+                         HashMap<String, P<ast::Expr>>)> {
     let mut args = Vec::new();
-    let mut names = HashMap::<string::String, P<ast::Expr>>::new();
+    let mut names = HashMap::<String, P<ast::Expr>>::new();
     let mut order = Vec::new();
 
     let mut p = ecx.new_parser_from_tts(tts);
-    // Parse the leading function expression (maybe a block, maybe a path)
-    let invocation = if allow_method {
-        let e = p.parse_expr();
-        if !p.eat(&token::Comma) {
-            ecx.span_err(sp, "expected token: `,`");
-            return (Call(e), None);
-        }
-        MethodCall(e, p.parse_ident())
-    } else {
-        Call(p.parse_expr())
-    };
-    if !p.eat(&token::Comma) {
-        ecx.span_err(sp, "expected token: `,`");
-        return (invocation, None);
-    }
 
     if p.token == token::Eof {
         ecx.span_err(sp, "requires at least a format string argument");
-        return (invocation, None);
+        return None;
     }
     let fmtstr = p.parse_expr();
     let mut named = false;
     while p.token != token::Eof {
         if !p.eat(&token::Comma) {
             ecx.span_err(sp, "expected token: `,`");
-            return (invocation, None);
+            return None;
         }
         if p.token == token::Eof { break } // accept trailing commas
         if named || (p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq)) {
@@ -131,13 +107,13 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool,
                     ecx.span_err(p.span,
                                  "expected ident, positional arguments \
                                  cannot follow named arguments");
-                    return (invocation, None);
+                    return None;
                 }
                 _ => {
                     ecx.span_err(p.span,
                                  format!("expected ident for named argument, found `{}`",
                                          p.this_token_to_string())[]);
-                    return (invocation, None);
+                    return None;
                 }
             };
             let interned_name = token::get_ident(ident);
@@ -160,7 +136,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool,
             args.push(p.parse_expr());
         }
     }
-    return (invocation, Some((fmtstr, args, order, names)));
+    Some((fmtstr, args, order, names))
 }
 
 impl<'a, 'b> Context<'a, 'b> {
@@ -225,7 +201,7 @@ impl<'a, 'b> Context<'a, 'b> {
         }
     }
 
-    fn describe_num_args(&self) -> string::String {
+    fn describe_num_args(&self) -> String {
         match self.args.len() {
             0 => "no arguments given".to_string(),
             1 => "there is 1 argument".to_string(),
@@ -474,70 +450,50 @@ impl<'a, 'b> Context<'a, 'b> {
         }
     }
 
-    fn item_static_array(ecx: &mut ExtCtxt,
-                         name: ast::Ident,
-                         piece_ty: P<ast::Ty>,
-                         pieces: Vec<P<ast::Expr>>)
-                         -> P<ast::Stmt> {
+    fn static_array(ecx: &mut ExtCtxt,
+                    name: &str,
+                    piece_ty: P<ast::Ty>,
+                    pieces: Vec<P<ast::Expr>>)
+                    -> P<ast::Expr> {
         let fmtsp = piece_ty.span;
-        let fmt = ecx.expr_vec(fmtsp, pieces);
-        let fmt = ecx.expr_addr_of(fmtsp, fmt);
-        let ty = ast::TyVec(piece_ty);
-        let ty = ast::TyRptr(Some(ecx.lifetime(fmtsp, special_idents::static_lifetime.name)),
-                             ast::MutTy{ mutbl: ast::MutImmutable, ty: ecx.ty(fmtsp, ty) });
-        let ty = ecx.ty(fmtsp, ty);
-        let st = ast::ItemStatic(ty, ast::MutImmutable, fmt);
+        let ty = ecx.ty_rptr(fmtsp,
+            ecx.ty(fmtsp, ast::TyVec(piece_ty)),
+            Some(ecx.lifetime(fmtsp, special_idents::static_lifetime.name)),
+            ast::MutImmutable);
+        let slice = ecx.expr_vec_slice(fmtsp, pieces);
+        let st = ast::ItemStatic(ty, ast::MutImmutable, slice);
+
+        let name = ecx.ident_of(name);
         let item = ecx.item(fmtsp, name, Context::static_attrs(ecx, fmtsp), st);
         let decl = respan(fmtsp, ast::DeclItem(item));
-        P(respan(fmtsp, ast::StmtDecl(P(decl), ast::DUMMY_NODE_ID)))
+
+        // Wrap the declaration in a block so that it forms a single expression.
+        ecx.expr_block(ecx.block(fmtsp,
+            vec![P(respan(fmtsp, ast::StmtDecl(P(decl), ast::DUMMY_NODE_ID)))],
+            Some(ecx.expr_ident(fmtsp, name))))
     }
 
     /// Actually builds the expression which the iformat! block will be expanded
     /// to
-    fn to_expr(mut self, invocation: Invocation) -> P<ast::Expr> {
-        let mut lets = Vec::new();
+    fn into_expr(mut self) -> P<ast::Expr> {
         let mut locals = Vec::new();
         let mut names = Vec::from_fn(self.name_positions.len(), |_| None);
         let mut pats = Vec::new();
         let mut heads = Vec::new();
 
-        // First, declare all of our methods that are statics
-        for method in self.method_statics.into_iter() {
-            let decl = respan(self.fmtsp, ast::DeclItem(method));
-            lets.push(P(respan(self.fmtsp,
-                               ast::StmtDecl(P(decl), ast::DUMMY_NODE_ID))));
-        }
-
-        // Next, build up the static array which will become our precompiled
+        // First, build up the static array which will become our precompiled
         // format "string"
-        let static_str_name = self.ecx.ident_of("__STATIC_FMTSTR");
-        let static_lifetime = self.ecx.lifetime(self.fmtsp, self.ecx.ident_of("'static").name);
+        let static_lifetime = self.ecx.lifetime(self.fmtsp, special_idents::static_lifetime.name);
         let piece_ty = self.ecx.ty_rptr(
                 self.fmtsp,
                 self.ecx.ty_ident(self.fmtsp, self.ecx.ident_of("str")),
                 Some(static_lifetime),
                 ast::MutImmutable);
-        lets.push(Context::item_static_array(self.ecx,
-                                             static_str_name,
-                                             piece_ty,
-                                             self.str_pieces));
-
-        // Then, build up the static array which will store our precompiled
-        // nonstandard placeholders, if there are any.
-        let static_args_name = self.ecx.ident_of("__STATIC_FMTARGS");
-        if !self.all_pieces_simple {
-            let piece_ty = self.ecx.ty_path(self.ecx.path_all(
-                    self.fmtsp,
-                    true, Context::rtpath(self.ecx, "Argument"),
-                    vec![static_lifetime],
-                    vec![],
-                    vec![]
-                ));
-            lets.push(Context::item_static_array(self.ecx,
-                                                 static_args_name,
-                                                 piece_ty,
-                                                 self.pieces));
-        }
+        let pieces = Context::static_array(self.ecx,
+                                           "__STATIC_FMTSTR",
+                                           piece_ty,
+                                           self.str_pieces);
+
 
         // Right now there is a bug such that for the expression:
         //      foo(bar(&1))
@@ -580,71 +536,68 @@ impl<'a, 'b> Context<'a, 'b> {
         // Now create a vector containing all the arguments
         let args = locals.into_iter().chain(names.into_iter().map(|a| a.unwrap()));
 
-        // Now create the fmt::Arguments struct with all our locals we created.
-        let pieces = self.ecx.expr_ident(self.fmtsp, static_str_name);
-        let args_slice = self.ecx.expr_vec_slice(self.fmtsp, args.collect());
-
-        let (fn_name, fn_args) = if self.all_pieces_simple {
-            ("new", vec![pieces, args_slice])
-        } else {
-            let fmt = self.ecx.expr_ident(self.fmtsp, static_args_name);
-            ("with_placeholders", vec![pieces, fmt, args_slice])
-        };
-
-        let result = self.ecx.expr_call_global(self.fmtsp, vec!(
-                self.ecx.ident_of("std"),
-                self.ecx.ident_of("fmt"),
-                self.ecx.ident_of("Arguments"),
-                self.ecx.ident_of(fn_name)), fn_args);
-
-        let result = match invocation {
-            Call(e) => {
-                let span = e.span;
-                self.ecx.expr_call(span, e, vec![
-                    self.ecx.expr_addr_of(span, result)
-                ])
-            }
-            MethodCall(e, m) => {
-                let span = e.span;
-                self.ecx.expr_method_call(span, e, m, vec![
-                    self.ecx.expr_addr_of(span, result)
-                ])
-            }
-        };
-        let body = self.ecx.expr_block(self.ecx.block(self.fmtsp, lets,
-                                                      Some(result)));
+        let args_array = self.ecx.expr_vec(self.fmtsp, args.collect());
 
         // Constructs an AST equivalent to:
         //
         //      match (&arg0, &arg1) {
-        //          (tmp0, tmp1) => body
+        //          (tmp0, tmp1) => args_array
         //      }
         //
         // It was:
         //
         //      let tmp0 = &arg0;
         //      let tmp1 = &arg1;
-        //      body
+        //      args_array
         //
         // Because of #11585 the new temporary lifetime rule, the enclosing
         // statements for these temporaries become the let's themselves.
         // If one or more of them are RefCell's, RefCell borrow() will also
-        // end there; they don't last long enough for body to use them. The
-        // match expression solves the scope problem.
+        // end there; they don't last long enough for args_array to use them.
+        // The match expression solves the scope problem.
         //
         // Note, it may also very well be transformed to:
         //
         //      match arg0 {
         //          ref tmp0 => {
         //              match arg1 => {
-        //                  ref tmp1 => body } } }
+        //                  ref tmp1 => args_array } } }
         //
         // But the nested match expression is proved to perform not as well
         // as series of let's; the first approach does.
         let pat = self.ecx.pat_tuple(self.fmtsp, pats);
-        let arm = self.ecx.arm(self.fmtsp, vec!(pat), body);
+        let arm = self.ecx.arm(self.fmtsp, vec!(pat), args_array);
         let head = self.ecx.expr(self.fmtsp, ast::ExprTup(heads));
-        self.ecx.expr_match(self.fmtsp, head, vec!(arm))
+        let result = self.ecx.expr_match(self.fmtsp, head, vec!(arm));
+
+        let args_slice = self.ecx.expr_addr_of(self.fmtsp, result);
+
+        // Now create the fmt::Arguments struct with all our locals we created.
+        let (fn_name, fn_args) = if self.all_pieces_simple {
+            ("new", vec![pieces, args_slice])
+        } else {
+            // Build up the static array which will store our precompiled
+            // nonstandard placeholders, if there are any.
+            let piece_ty = self.ecx.ty_path(self.ecx.path_all(
+                    self.fmtsp,
+                    true, Context::rtpath(self.ecx, "Argument"),
+                    vec![static_lifetime],
+                    vec![],
+                    vec![]
+                ));
+            let fmt = Context::static_array(self.ecx,
+                                            "__STATIC_FMTARGS",
+                                            piece_ty,
+                                            self.pieces);
+
+            ("with_placeholders", vec![pieces, fmt, args_slice])
+        };
+
+        self.ecx.expr_call_global(self.fmtsp, vec!(
+                self.ecx.ident_of("std"),
+                self.ecx.ident_of("fmt"),
+                self.ecx.ident_of("Arguments"),
+                self.ecx.ident_of(fn_name)), fn_args)
     }
 
     fn format_arg(ecx: &ExtCtxt, sp: Span,
@@ -694,24 +647,22 @@ pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt, sp: Span,
                                tts: &[ast::TokenTree])
                                -> Box<base::MacResult+'cx> {
 
-    match parse_args(ecx, sp, false, tts) {
-        (invocation, Some((efmt, args, order, names))) => {
-            MacExpr::new(expand_preparsed_format_args(ecx, sp, invocation, efmt,
+    match parse_args(ecx, sp, tts) {
+        Some((efmt, args, order, names)) => {
+            MacExpr::new(expand_preparsed_format_args(ecx, sp, efmt,
                                                       args, order, names))
         }
-        (_, None) => MacExpr::new(ecx.expr_uint(sp, 2))
+        None => DummyResult::expr(sp)
     }
 }
 
-/// Take the various parts of `format_args!(extra, efmt, args...,
-/// name=names...)` and construct the appropriate formatting
-/// expression.
+/// Take the various parts of `format_args!(efmt, args..., name=names...)`
+/// and construct the appropriate formatting expression.
 pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
-                                    invocation: Invocation,
                                     efmt: P<ast::Expr>,
                                     args: Vec<P<ast::Expr>>,
-                                    name_ordering: Vec<string::String>,
-                                    names: HashMap<string::String, P<ast::Expr>>)
+                                    name_ordering: Vec<String>,
+                                    names: HashMap<String, P<ast::Expr>>)
                                     -> P<ast::Expr> {
     let arg_types = Vec::from_fn(args.len(), |_| None);
     let mut cx = Context {
@@ -724,17 +675,16 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
         name_ordering: name_ordering,
         nest_level: 0,
         next_arg: 0,
-        literal: string::String::new(),
+        literal: String::new(),
         pieces: Vec::new(),
         str_pieces: Vec::new(),
         all_pieces_simple: true,
-        method_statics: Vec::new(),
         fmtsp: sp,
     };
     cx.fmtsp = efmt.span;
     let fmt = match expr_to_string(cx.ecx,
-                                efmt,
-                                "format argument must be a string literal.") {
+                                   efmt,
+                                   "format argument must be a string literal.") {
         Some((fmt, _)) => fmt,
         None => return DummyResult::raw_expr(sp)
     };
@@ -782,5 +732,5 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
         }
     }
 
-    cx.to_expr(invocation)
+    cx.into_expr()
 }
diff --git a/src/test/compile-fail/dead-code-closure-bang.rs b/src/test/compile-fail/dead-code-closure-bang.rs
index 3179b181560..0aa3c40fa5f 100644
--- a/src/test/compile-fail/dead-code-closure-bang.rs
+++ b/src/test/compile-fail/dead-code-closure-bang.rs
@@ -13,5 +13,5 @@
 fn main() {
     let x: || -> ! = || panic!();
     x();
-    println!("Foo bar"); //~ ERROR: unreachable statement
+    std::io::println("Foo bar"); //~ ERROR: unreachable statement
 }
diff --git a/src/test/compile-fail/ifmt-bad-format-args.rs b/src/test/compile-fail/ifmt-bad-format-args.rs
index d2a3fe2a9b1..8bd3cb0f60b 100644
--- a/src/test/compile-fail/ifmt-bad-format-args.rs
+++ b/src/test/compile-fail/ifmt-bad-format-args.rs
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 fn main() {
-    format_args!("test"); //~ ERROR: expected token
-    format_args!("", || {}); //~ ERROR: must be a string literal
+    format_args!(); //~ ERROR: requires at least a format string argument
+    format_args!(|| {}); //~ ERROR: must be a string literal
 }
diff --git a/src/test/compile-fail/ifmt-bad-format-args2.rs b/src/test/compile-fail/ifmt-bad-format-args2.rs
deleted file mode 100644
index 7bb8365bc12..00000000000
--- a/src/test/compile-fail/ifmt-bad-format-args2.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    format_args!("{}", ""); //~ ERROR: expected function
-}
diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp
index e4389cd69dd..c2ebd764ad6 100644
--- a/src/test/pretty/issue-4264.pp
+++ b/src/test/pretty/issue-4264.pp
@@ -34,13 +34,6 @@ pub fn bar() {
                 [int; 3]) as &[int; 3]) as *const _ as *const [int; 3]) as
             *const [int; (3u as uint)] as *const [int; 3]);
 
-    (match (() as ()) {
-         () => {
-             #[inline]
-             #[allow(dead_code)]
-             static __STATIC_FMTSTR: &'static [&'static str] =
-                 (&([("test" as &'static str)] as [&'static str; 1]) as
-                     &'static [&'static str; 1]);
 
 
 
@@ -49,24 +42,45 @@ pub fn bar() {
 
 
 
-             ((::std::fmt::format as
-                  fn(&core::fmt::Arguments<'_>) -> collections::string::String {std::fmt::format})((&((::std::fmt::Arguments::new
-                                                                                                          as
-                                                                                                          fn(&[&str], &[core::fmt::Argument<'_>]) -> core::fmt::Arguments<'_> {core::fmt::Arguments<'a>::new})((__STATIC_FMTSTR
-                                                                                                                                                                                                                   as
-                                                                                                                                                                                                                   &'static [&'static str]),
-                                                                                                                                                                                                               (&([]
-                                                                                                                                                                                                                     as
-                                                                                                                                                                                                                     [core::fmt::Argument<'_>; 0])
-                                                                                                                                                                                                                   as
-                                                                                                                                                                                                                   &[core::fmt::Argument<'_>; 0]))
-                                                                                                         as
-                                                                                                         core::fmt::Arguments<'_>)
-                                                                                                       as
-                                                                                                       &core::fmt::Arguments<'_>))
-                 as collections::string::String)
-         }
-     } as collections::string::String);
+    ((::std::fmt::format as
+         fn(core::fmt::Arguments<'_>) -> collections::string::String {std::fmt::format})(((::std::fmt::Arguments::new
+                                                                                              as
+                                                                                              fn(&[&str], &[core::fmt::Argument<'_>]) -> core::fmt::Arguments<'_> {core::fmt::Arguments<'a>::new})(({
+                                                                                                                                                                                                        #[inline]
+                                                                                                                                                                                                        #[allow(dead_code)]
+                                                                                                                                                                                                        static __STATIC_FMTSTR:
+                                                                                                                                                                                                               &'static [&'static str]
+                                                                                                                                                                                                               =
+                                                                                                                                                                                                            (&([("test"
+                                                                                                                                                                                                                    as
+                                                                                                                                                                                                                    &'static str)]
+                                                                                                                                                                                                                  as
+                                                                                                                                                                                                                  [&'static str; 1])
+                                                                                                                                                                                                                as
+                                                                                                                                                                                                                &'static [&'static str; 1]);
+                                                                                                                                                                                                        (__STATIC_FMTSTR
+                                                                                                                                                                                                            as
+                                                                                                                                                                                                            &'static [&'static str])
+                                                                                                                                                                                                    }
+                                                                                                                                                                                                       as
+                                                                                                                                                                                                       &[&str]),
+                                                                                                                                                                                                   (&(match (()
+                                                                                                                                                                                                                as
+                                                                                                                                                                                                                ())
+                                                                                                                                                                                                          {
+                                                                                                                                                                                                          ()
+                                                                                                                                                                                                          =>
+                                                                                                                                                                                                          ([]
+                                                                                                                                                                                                              as
+                                                                                                                                                                                                              [core::fmt::Argument<'_>; 0]),
+                                                                                                                                                                                                      }
+                                                                                                                                                                                                         as
+                                                                                                                                                                                                         [core::fmt::Argument<'_>; 0])
+                                                                                                                                                                                                       as
+                                                                                                                                                                                                       &[core::fmt::Argument<'_>; 0]))
+                                                                                             as
+                                                                                             core::fmt::Arguments<'_>))
+        as collections::string::String);
 }
 pub type Foo = [int; (3u as uint)];
 pub struct Bar {
diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs
index f3e15562b6d..fa62699a303 100644
--- a/src/test/run-pass/ifmt.rs
+++ b/src/test/run-pass/ifmt.rs
@@ -190,18 +190,16 @@ fn test_format_args() {
     let mut buf = Vec::new();
     {
         let w = &mut buf as &mut io::Writer;
-        format_args!(|args| { write!(w, "{}", args); }, "{}", 1i);
-        format_args!(|args| { write!(w, "{}", args); }, "test");
-        format_args!(|args| { write!(w, "{}", args); }, "{test}", test=3i);
+        write!(w, "{}", format_args!("{}", 1i));
+        write!(w, "{}", format_args!("test"));
+        write!(w, "{}", format_args!("{test}", test=3i));
     }
     let s = String::from_utf8(buf).unwrap();
     t!(s, "1test3");
 
-    let s = format_args!(fmt::format, "hello {}", "world");
+    let s = fmt::format(format_args!("hello {}", "world"));
     t!(s, "hello world");
-    let s = format_args!(|args| {
-        format!("{}: {}", "args were", args)
-    }, "hello {}", "world");
+    let s = format!("{}: {}", "args were", format_args!("hello {}", "world"));
     t!(s, "args were: hello world");
 }