From 62273575139a80c2b208a3a27e0c2392b1425be6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 13 Jan 2015 15:42:53 -0800 Subject: [PATCH] std: Stabilize the std::fmt module This commit performs a final stabilization pass over the std::fmt module, marking all necessary APIs as stable. One of the more interesting aspects of this module is that it exposes a good deal of its runtime representation to the outside world in order for `format_args!` to be able to construct the format strings. Instead of hacking the compiler to assume that these items are stable, this commit instead lays out a story for the stabilization and evolution of these APIs. There are three primary details used by the `format_args!` macro: 1. `Arguments` - an opaque package of a "compiled format string". This structure is passed around and the `write` function is the source of truth for transforming a compiled format string into a string at runtime. This must be able to be constructed in stable code. 2. `Argument` - an opaque structure representing an argument to a format string. This is *almost* a trait object as it's just a pointer/function pair, but due to the function originating from one of many traits, it's not actually a trait object. Like `Arguments`, this must be constructed from stable code. 3. `fmt::rt` - this module contains the runtime type definitions primarily for the `rt::Argument` structure. Whenever an argument is formatted with nonstandard flags, a corresponding `rt::Argument` is generated describing how the argument is being formatted. This can be used to construct an `Arguments`. The primary interface to `std::fmt` is the `Arguments` structure, and as such this type name is stabilize as-is today. It is expected for libraries to pass around an `Arguments` structure to represent a pending formatted computation. The remaining portions are largely "cruft" which would rather not be stabilized, but due to the stability checks they must be. As a result, almost all pieces have been renamed to represent that they are "version 1" of the formatting representation. The theory is that at a later date if we change the representation of these types we can add new definitions called "version 2" and corresponding constructors for `Arguments`. One of the other remaining large questions about the fmt module were how the pending I/O reform would affect the signatures of methods in the module. Due to [RFC 526][rfc], however, the writers of fmt are now incompatible with the writers of io, so this question has largely been solved. As a result the interfaces are largely stabilized as-is today. [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0526-fmt-text-writer.md Specifically, the following changes were made: * The contents of `fmt::rt` were all moved under `fmt::rt::v1` * `fmt::rt` is stable * `fmt::rt::v1` is stable * `Error` is stable * `Writer` is stable * `Writer::write_str` is stable * `Writer::write_fmt` is stable * `Formatter` is stable * `Argument` has been renamed to `ArgumentV1` and is stable * `ArgumentV1::new` is stable * `ArgumentV1::from_uint` is stable * `Arguments::new_v1` is stable (renamed from `new`) * `Arguments::new_v1_formatted` is stable (renamed from `with_placeholders`) * All formatting traits are now stable, as well as the `fmt` method. * `fmt::write` is stable * `fmt::format` is stable * `Formatter::pad_integral` is stable * `Formatter::pad` is stable * `Formatter::write_str` is stable * `Formatter::write_fmt` is stable * Some assorted top level items which were only used by `format_args!` were removed in favor of static functions on `ArgumentV1` as well. * The formatting-flag-accessing methods remain unstable Within the contents of the `fmt::rt::v1` module, the following actions were taken: * Reexports of all enum variants were removed * All prefixes on enum variants were removed * A few miscellaneous enum variants were renamed * Otherwise all structs, fields, and variants were marked stable. In addition to these actions in the `std::fmt` module, many implementations of `Show` and `String` were stabilized as well. In some other modules: * `ToString` is now stable * `ToString::to_string` is now stable * `Vec` no longer implements `fmt::Writer` (this has moved to `String`) This is a breaking change due to all of the changes to the `fmt::rt` module, but this likely will not have much impact on existing programs. Closes #20661 [breaking-change] --- src/liballoc/arc.rs | 29 +- src/libcollections/bit.rs | 1 + src/libcollections/enum_set.rs | 1 + src/libcollections/string.rs | 4 + src/libcollections/vec.rs | 7 - src/libcore/fmt/mod.rs | 252 ++++++++++-------- src/libcore/fmt/rt.rs | 86 ------ src/libcore/fmt/rt/v1.rs | 94 +++++++ src/libcore/result.rs | 6 +- src/libgraphviz/lib.rs | 16 +- src/librustc/middle/cfg/graphviz.rs | 4 +- .../middle/infer/region_inference/graphviz.rs | 4 +- src/libserialize/json.rs | 4 +- src/libstd/ffi/c_str.rs | 2 +- src/libstd/fmt.rs | 7 +- src/libstd/old_io/process.rs | 5 +- src/libstd/sync/mpsc/mod.rs | 6 +- src/libsyntax/ext/format.rs | 136 +++++----- src/test/compile-fail/lint-dead-code-4.rs | 1 - src/test/compile-fail/missing_debug_impls.rs | 1 - src/test/pretty/issue-4264.pp | 62 +++-- 21 files changed, 379 insertions(+), 349 deletions(-) delete mode 100644 src/libcore/fmt/rt.rs create mode 100644 src/libcore/fmt/rt/v1.rs diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index f9f6de2df5876..32fe2bb0a3201 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -12,20 +12,22 @@ //! Threadsafe reference-counted boxes (the `Arc` type). //! -//! The `Arc` type provides shared ownership of an immutable value. Destruction is -//! deterministic, and will occur as soon as the last owner is gone. It is marked as `Send` because -//! it uses atomic reference counting. +//! The `Arc` type provides shared ownership of an immutable value. +//! Destruction is deterministic, and will occur as soon as the last owner is +//! gone. It is marked as `Send` because it uses atomic reference counting. //! -//! If you do not need thread-safety, and just need shared ownership, consider the [`Rc` -//! type](../rc/struct.Rc.html). It is the same as `Arc`, but does not use atomics, making it -//! both thread-unsafe as well as significantly faster when updating the reference count. +//! If you do not need thread-safety, and just need shared ownership, consider +//! the [`Rc` type](../rc/struct.Rc.html). It is the same as `Arc`, but +//! does not use atomics, making it both thread-unsafe as well as significantly +//! faster when updating the reference count. //! -//! The `downgrade` method can be used to create a non-owning `Weak` pointer to the box. A -//! `Weak` pointer can be upgraded to an `Arc` pointer, but will return `None` if the value -//! has already been dropped. +//! The `downgrade` method can be used to create a non-owning `Weak` pointer +//! to the box. A `Weak` pointer can be upgraded to an `Arc` pointer, but +//! will return `None` if the value has already been dropped. //! -//! For example, a tree with parent pointers can be represented by putting the nodes behind strong -//! `Arc` pointers, and then storing the parent pointers as `Weak` pointers. +//! For example, a tree with parent pointers can be represented by putting the +//! nodes behind strong `Arc` pointers, and then storing the parent pointers +//! as `Weak` pointers. //! //! # Examples //! @@ -87,8 +89,9 @@ use heap::deallocate; /// /// # Example /// -/// In this example, a large vector of floats is shared between several tasks. With simple pipes, -/// without `Arc`, a copy would have to be made for each task. +/// In this example, a large vector of floats is shared between several tasks. +/// With simple pipes, without `Arc`, a copy would have to be made for each +/// task. /// /// ```rust /// use std::sync::Arc; diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index c627574057969..99f650db44969 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -1730,6 +1730,7 @@ impl BitvSet { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for BitvSet { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { try!(write!(fmt, "BitvSet {{")); diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index b542259eba0dd..c70794262c967 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -31,6 +31,7 @@ pub struct EnumSet { impl Copy for EnumSet {} +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for EnumSet { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { try!(write!(fmt, "EnumSet {{")); diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 8f7920fe1c44b..ae52eff0111b1 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -938,11 +938,14 @@ impl FromStr for String { } /// A generic trait for converting a value to a string +#[stable(feature = "rust1", since = "1.0.0")] pub trait ToString { /// Converts the value of `self` to an owned string + #[stable(feature = "rust1", since = "1.0.0")] fn to_string(&self) -> String; } +#[stable(feature = "rust1", since = "1.0.0")] impl ToString for T { #[inline] fn to_string(&self) -> String { @@ -979,6 +982,7 @@ impl<'a> Str for CowString<'a> { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Writer for String { #[inline] fn write_str(&mut self, s: &str) -> fmt::Result { diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 336a3d7521a19..f57bffa190078 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1546,13 +1546,6 @@ impl fmt::Debug for Vec { } } -impl<'a> fmt::Writer for Vec { - fn write_str(&mut self, s: &str) -> fmt::Result { - self.push_all(s.as_bytes()); - Ok(()) - } -} - //////////////////////////////////////////////////////////////////////////////// // Clone-on-write //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 8b7a4c677ac75..2ff67ebd550ab 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -10,7 +10,6 @@ //! Utilities for formatting and printing strings -#![allow(unused_variables)] #![stable(feature = "rust1", since = "1.0.0")] use any; @@ -27,6 +26,7 @@ use result; use slice::SliceExt; use slice; use str::{self, StrExt}; +use self::rt::v1::Alignment; pub use self::num::radix; pub use self::num::Radix; @@ -34,10 +34,15 @@ pub use self::num::RadixFmt; mod num; mod float; -pub mod rt; -#[unstable(feature = "core", - reason = "core and I/O reconciliation may alter this definition")] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(hidden)] +pub mod rt { + #[cfg(stage0)] pub use self::v1::*; + pub mod v1; +} + +#[stable(feature = "rust1", since = "1.0.0")] /// The type returned by formatter methods. pub type Result = result::Result<(), Error>; @@ -46,8 +51,7 @@ pub type Result = result::Result<(), Error>; /// This type does not support transmission of an error other than that an error /// occurred. Any extra information must be arranged to be transmitted through /// some other means. -#[unstable(feature = "core", - reason = "core and I/O reconciliation may alter this definition")] +#[stable(feature = "rust1", since = "1.0.0")] #[derive(Copy, Debug)] pub struct Error; @@ -60,8 +64,7 @@ pub struct Error; /// This trait should generally not be implemented by consumers of the standard /// library. The `write!` macro accepts an instance of `io::Writer`, and the /// `io::Writer` trait is favored over implementing this trait. -#[unstable(feature = "core", - reason = "waiting for core and I/O reconciliation")] +#[stable(feature = "rust1", since = "1.0.0")] pub trait Writer { /// Writes a slice of bytes into this writer, returning whether the write /// succeeded. @@ -73,12 +76,14 @@ pub trait Writer { /// # Errors /// /// This function will return an instance of `FormatError` on error. + #[stable(feature = "rust1", since = "1.0.0")] fn write_str(&mut self, s: &str) -> Result; /// 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. + #[stable(feature = "rust1", since = "1.0.0")] fn write_fmt(&mut self, args: Arguments) -> Result { // This Adapter is needed to allow `self` (of type `&mut // Self`) to be cast to a FormatWriter (below) without @@ -104,18 +109,17 @@ pub trait Writer { /// A struct to represent both where to emit formatting strings to and how they /// should be formatted. A mutable version of this is passed to all formatting /// traits. -#[unstable(feature = "core", - reason = "name may change and implemented traits are also unstable")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Formatter<'a> { flags: uint, fill: char, - align: rt::Alignment, + align: rt::v1::Alignment, width: Option, precision: Option, buf: &'a mut (Writer+'a), - curarg: slice::Iter<'a, Argument<'a>>, - args: &'a [Argument<'a>], + curarg: slice::Iter<'a, ArgumentV1<'a>>, + args: &'a [ArgumentV1<'a>], } // NB. Argument is essentially an optimized partially applied formatting function, @@ -127,35 +131,40 @@ enum Void {} /// family of functions. It contains a function to format the given value. At /// compile time it is ensured that the function and the value have the correct /// types, and then this struct is used to canonicalize arguments to one type. -#[unstable(feature = "core", - reason = "implementation detail of the `format_args!` macro")] #[derive(Copy)] -pub struct Argument<'a> { +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(hidden)] +pub struct ArgumentV1<'a> { value: &'a Void, formatter: fn(&Void, &mut Formatter) -> Result, } -impl<'a> Argument<'a> { +impl<'a> ArgumentV1<'a> { #[inline(never)] fn show_uint(x: &uint, f: &mut Formatter) -> Result { Display::fmt(x, f) } - fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter) -> Result) -> Argument<'b> { + #[doc(hidden)] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new<'b, T>(x: &'b T, + f: fn(&T, &mut Formatter) -> Result) -> ArgumentV1<'b> { unsafe { - Argument { + ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } } } - fn from_uint(x: &uint) -> Argument { - Argument::new(x, Argument::show_uint) + #[doc(hidden)] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_uint(x: &uint) -> ArgumentV1 { + ArgumentV1::new(x, ArgumentV1::show_uint) } fn as_uint(&self) -> Option { - if self.formatter as uint == Argument::show_uint as uint { + if self.formatter as uint == ArgumentV1::show_uint as uint { Some(unsafe { *(self.value as *const _ as *const uint) }) } else { None @@ -163,14 +172,32 @@ impl<'a> Argument<'a> { } } +// flags available in the v1 format of format_args +#[derive(Copy)] +#[allow(dead_code)] // SignMinus isn't currently used +enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, } + impl<'a> Arguments<'a> { /// When using the format_args!() macro, this function is used to generate the /// Arguments structure. #[doc(hidden)] #[inline] - #[unstable(feature = "core", - reason = "implementation detail of the `format_args!` macro")] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new_v1(pieces: &'a [&'a str], + args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { + Arguments { + pieces: pieces, + fmt: None, + args: args + } + } + + /// When using the format_args!() macro, this function is used to generate the + /// Arguments structure. + #[doc(hidden)] #[inline] + #[cfg(stage0)] + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(pieces: &'a [&'a str], - args: &'a [Argument<'a>]) -> Arguments<'a> { + args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { Arguments { pieces: pieces, fmt: None, @@ -185,11 +212,28 @@ impl<'a> Arguments<'a> { /// created with `argumentuint`. However, failing to do so doesn't cause /// unsafety, but will ignore invalid . #[doc(hidden)] #[inline] - #[unstable(feature = "core", - reason = "implementation detail of the `format_args!` macro")] + #[cfg(stage0)] + #[stable(feature = "rust1", since = "1.0.0")] pub fn with_placeholders(pieces: &'a [&'a str], - fmt: &'a [rt::Argument], - args: &'a [Argument<'a>]) -> Arguments<'a> { + fmt: &'a [rt::v1::Argument], + args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { + Arguments { + pieces: pieces, + fmt: Some(fmt), + args: args + } + } + /// This function is used to specify nonstandard formatting parameters. + /// The `pieces` array must be at least as long as `fmt` to construct + /// a valid Arguments structure. Also, any `Count` within `fmt` that is + /// `CountIsParam` or `CountIsNextParam` has to point to an argument + /// created with `argumentuint`. However, failing to do so doesn't cause + /// unsafety, but will ignore invalid . + #[doc(hidden)] #[inline] + #[cfg(not(stage0))] + pub fn new_v1_formatted(pieces: &'a [&'a str], + args: &'a [ArgumentV1<'a>], + fmt: &'a [rt::v1::Argument]) -> Arguments<'a> { Arguments { pieces: pieces, fmt: Some(fmt), @@ -214,11 +258,11 @@ pub struct Arguments<'a> { pieces: &'a [&'a str], // Placeholder specs, or `None` if all specs are default (as in "{}{}"). - fmt: Option<&'a [rt::Argument]>, + fmt: Option<&'a [rt::v1::Argument]>, // Dynamic arguments for interpolation, to be interleaved with string // pieces. (Every argument is preceded by a string piece.) - args: &'a [Argument<'a>], + args: &'a [ArgumentV1<'a>], } #[stable(feature = "rust1", since = "1.0.0")] @@ -237,20 +281,20 @@ impl<'a> Display for Arguments<'a> { /// Format trait for the `:?` format. Useful for debugging, all types /// should implement this. -#[unstable(feature = "core", - reason = "I/O and core have yet to be reconciled")] #[deprecated(since = "1.0.0", reason = "renamed to Debug")] +#[unstable(feature = "old_fmt")] pub trait Show { /// Formats the value using the given formatter. + #[stable(feature = "rust1", since = "1.0.0")] fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `:?` format. Useful for debugging, all types /// should implement this. -#[unstable(feature = "core", - reason = "I/O and core have yet to be reconciled")] -#[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is defined in your \ - crate, add `#[derive(Debug)]` or manually implement it"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is \ + defined in your crate, add `#[derive(Debug)]` or \ + manually implement it"] #[lang = "debug_trait"] pub trait Debug { /// Formats the value using the given formatter. @@ -264,19 +308,20 @@ impl Debug for T { /// When a value can be semantically expressed as a String, this trait may be /// used. It corresponds to the default format, `{}`. -#[unstable(feature = "core")] #[deprecated(since = "1.0.0", reason = "renamed to Display")] +#[unstable(feature = "old_fmt")] pub trait String { /// Formats the value using the given formatter. + #[stable(feature = "rust1", since = "1.0.0")] fn fmt(&self, &mut Formatter) -> Result; } /// When a value can be semantically expressed as a String, this trait may be /// used. It corresponds to the default format, `{}`. -#[unstable(feature = "core", - reason = "I/O and core have yet to be reconciled")] -#[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default formatter; try using \ - `:?` instead if you are using a format string"] +#[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default \ + formatter; try using `:?` instead if you are using \ + a format string"] +#[stable(feature = "rust1", since = "1.0.0")] pub trait Display { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; @@ -288,58 +333,58 @@ impl Display for T { } /// Format trait for the `o` character -#[unstable(feature = "core", - reason = "I/O and core have yet to be reconciled")] +#[stable(feature = "rust1", since = "1.0.0")] pub trait Octal { /// Formats the value using the given formatter. + #[stable(feature = "rust1", since = "1.0.0")] fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `b` character -#[unstable(feature = "core", - reason = "I/O and core have yet to be reconciled")] +#[stable(feature = "rust1", since = "1.0.0")] pub trait Binary { /// Formats the value using the given formatter. + #[stable(feature = "rust1", since = "1.0.0")] fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `x` character -#[unstable(feature = "core", - reason = "I/O and core have yet to be reconciled")] +#[stable(feature = "rust1", since = "1.0.0")] pub trait LowerHex { /// Formats the value using the given formatter. + #[stable(feature = "rust1", since = "1.0.0")] fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `X` character -#[unstable(feature = "core", - reason = "I/O and core have yet to be reconciled")] +#[stable(feature = "rust1", since = "1.0.0")] pub trait UpperHex { /// Formats the value using the given formatter. + #[stable(feature = "rust1", since = "1.0.0")] fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `p` character -#[unstable(feature = "core", - reason = "I/O and core have yet to be reconciled")] +#[stable(feature = "rust1", since = "1.0.0")] pub trait Pointer { /// Formats the value using the given formatter. + #[stable(feature = "rust1", since = "1.0.0")] fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `e` character -#[unstable(feature = "core", - reason = "I/O and core have yet to be reconciled")] +#[stable(feature = "rust1", since = "1.0.0")] pub trait LowerExp { /// Formats the value using the given formatter. + #[stable(feature = "rust1", since = "1.0.0")] fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `E` character -#[unstable(feature = "core", - reason = "I/O and core have yet to be reconciled")] +#[stable(feature = "rust1", since = "1.0.0")] pub trait UpperExp { /// Formats the value using the given formatter. + #[stable(feature = "rust1", since = "1.0.0")] fn fmt(&self, &mut Formatter) -> Result; } @@ -351,16 +396,14 @@ pub trait UpperExp { /// /// * output - the buffer to write output to /// * args - the precompiled arguments generated by `format_args!` -#[unstable(feature = "core", - reason = "libcore and I/O have yet to be reconciled, and this is an \ - implementation detail which should not otherwise be exported")] +#[stable(feature = "rust1", since = "1.0.0")] pub fn write(output: &mut Writer, args: Arguments) -> Result { let mut formatter = Formatter { flags: 0, width: None, precision: None, buf: output, - align: rt::AlignUnknown, + align: Alignment::Unknown, fill: ' ', args: args.args, curarg: args.args.iter(), @@ -402,7 +445,7 @@ impl<'a> Formatter<'a> { // First up is the collection of functions used to execute a format string // at runtime. This consumes all of the compile-time statics generated by // the format! syntax extension. - fn run(&mut self, arg: &rt::Argument) -> Result { + fn run(&mut self, arg: &rt::v1::Argument) -> Result { // Fill in the format parameters into the formatter self.fill = arg.format.fill; self.align = arg.format.align; @@ -412,22 +455,22 @@ impl<'a> Formatter<'a> { // Extract the correct argument let value = match arg.position { - rt::ArgumentNext => { *self.curarg.next().unwrap() } - rt::ArgumentIs(i) => self.args[i], + rt::v1::Position::Next => { *self.curarg.next().unwrap() } + rt::v1::Position::At(i) => self.args[i], }; // Then actually do some printing (value.formatter)(value.value, self) } - fn getcount(&mut self, cnt: &rt::Count) -> Option { + fn getcount(&mut self, cnt: &rt::v1::Count) -> Option { match *cnt { - rt::CountIs(n) => Some(n), - rt::CountImplied => None, - rt::CountIsParam(i) => { + rt::v1::Count::Is(n) => Some(n), + rt::v1::Count::Implied => None, + rt::v1::Count::Param(i) => { self.args[i].as_uint() } - rt::CountIsNextParam => { + rt::v1::Count::NextParam => { self.curarg.next().and_then(|arg| arg.as_uint()) } } @@ -437,8 +480,8 @@ impl<'a> Formatter<'a> { // all formatting traits can use. /// Performs the correct padding for an integer which has already been - /// emitted into a byte-array. The byte-array should *not* contain the sign - /// for the integer, that will be added by this method. + /// emitted into a str. The str should *not* contain the sign for the + /// integer, that will be added by this method. /// /// # Arguments /// @@ -449,27 +492,25 @@ impl<'a> Formatter<'a> { /// /// This function will correctly account for the flags provided as well as /// the minimum width. It will not take precision into account. - #[unstable(feature = "core", - reason = "definition may change slightly over time")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn pad_integral(&mut self, is_positive: bool, prefix: &str, buf: &str) -> Result { use char::CharExt; - use fmt::rt::{FlagAlternate, FlagSignPlus, FlagSignAwareZeroPad}; let mut width = buf.len(); let mut sign = None; if !is_positive { sign = Some('-'); width += 1; - } else if self.flags & (1 << (FlagSignPlus as uint)) != 0 { + } else if self.flags & (1 << (FlagV1::SignPlus as uint)) != 0 { sign = Some('+'); width += 1; } let mut prefixed = false; - if self.flags & (1 << (FlagAlternate as uint)) != 0 { + if self.flags & (1 << (FlagV1::Alternate as uint)) != 0 { prefixed = true; width += prefix.char_len(); } @@ -499,16 +540,16 @@ impl<'a> Formatter<'a> { } // The sign and prefix goes before the padding if the fill character // is zero - Some(min) if self.flags & (1 << (FlagSignAwareZeroPad as uint)) != 0 => { + Some(min) if self.flags & (1 << (FlagV1::SignAwareZeroPad as uint)) != 0 => { self.fill = '0'; try!(write_prefix(self)); - self.with_padding(min - width, rt::AlignRight, |f| { + self.with_padding(min - width, Alignment::Right, |f| { f.buf.write_str(buf) }) } // Otherwise, the sign and prefix goes after the padding Some(min) => { - self.with_padding(min - width, rt::AlignRight, |f| { + self.with_padding(min - width, Alignment::Right, |f| { try!(write_prefix(f)); f.buf.write_str(buf) }) } @@ -526,8 +567,7 @@ impl<'a> Formatter<'a> { /// is longer than this length /// /// Notably this function ignored the `flag` parameters - #[unstable(feature = "core", - reason = "definition may change slightly over time")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn pad(&mut self, s: &str) -> Result { // Make sure there's a fast path up front if self.width.is_none() && self.precision.is_none() { @@ -561,7 +601,7 @@ impl<'a> Formatter<'a> { // If we're under both the maximum and the minimum width, then fill // up the minimum width with the specified string + some alignment. Some(width) => { - self.with_padding(width - s.char_len(), rt::AlignLeft, |me| { + self.with_padding(width - s.char_len(), Alignment::Left, |me| { me.buf.write_str(s) }) } @@ -570,19 +610,20 @@ impl<'a> Formatter<'a> { /// Runs a callback, emitting the correct padding either before or /// afterwards depending on whether right or left alignment is requested. - fn with_padding(&mut self, padding: uint, default: rt::Alignment, f: F) -> Result where - F: FnOnce(&mut Formatter) -> Result, + fn with_padding(&mut self, padding: uint, default: Alignment, + f: F) -> Result + where F: FnOnce(&mut Formatter) -> Result, { use char::CharExt; let align = match self.align { - rt::AlignUnknown => default, + Alignment::Unknown => default, _ => self.align }; let (pre_pad, post_pad) = match align { - rt::AlignLeft => (0, padding), - rt::AlignRight | rt::AlignUnknown => (padding, 0), - rt::AlignCenter => (padding / 2, (padding + 1) / 2), + Alignment::Left => (0, padding), + Alignment::Right | Alignment::Unknown => (padding, 0), + Alignment::Center => (padding / 2, (padding + 1) / 2), }; let mut fill = [0u8; 4]; @@ -604,23 +645,20 @@ impl<'a> Formatter<'a> { /// Writes some data to the underlying buffer contained within this /// formatter. - #[unstable(feature = "core", - reason = "reconciling core and I/O may alter this definition")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn write_str(&mut self, data: &str) -> Result { self.buf.write_str(data) } /// Writes some formatted information into this instance - #[unstable(feature = "core", - reason = "reconciling core and I/O may alter this definition")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn write_fmt(&mut self, fmt: Arguments) -> Result { write(self.buf, fmt) } /// Flags for formatting (packed version of rt::Flag) - #[unstable(feature = "core", - reason = "return type may change and method was just created")] - pub fn flags(&self) -> uint { self.flags } + #[stable(feature = "rust1", since = "1.0.0")] + pub fn flags(&self) -> usize { self.flags } /// Character used as 'fill' whenever there is alignment #[unstable(feature = "core", reason = "method was just created")] @@ -628,7 +666,7 @@ impl<'a> Formatter<'a> { /// Flag indicating what form of alignment was requested #[unstable(feature = "core", reason = "method was just created")] - pub fn align(&self) -> rt::Alignment { self.align } + pub fn align(&self) -> Alignment { self.align } /// Optionally specified integer width that the output should be #[unstable(feature = "core", reason = "method was just created")] @@ -649,20 +687,20 @@ impl Display for Error { /// This is a function which calls are emitted to by the compiler itself to /// create the Argument structures that are passed into the `format` function. #[doc(hidden)] #[inline] -#[unstable(feature = "core", - reason = "implementation detail of the `format_args!` macro")] +#[cfg(stage0)] +#[stable(feature = "rust1", since = "1.0.0")] pub fn argument<'a, T>(f: fn(&T, &mut Formatter) -> Result, - t: &'a T) -> Argument<'a> { - Argument::new(t, f) + t: &'a T) -> ArgumentV1<'a> { + ArgumentV1::new(t, f) } /// When the compiler determines that the type of an argument *must* be a uint /// (such as for width and precision), then it invokes this method. #[doc(hidden)] #[inline] -#[unstable(feature = "core", - reason = "implementation detail of the `format_args!` macro")] -pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> { - Argument::from_uint(s) +#[cfg(stage0)] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn argumentuint<'a>(s: &'a uint) -> ArgumentV1<'a> { + ArgumentV1::from_uint(s) } // Implementations of the core formatting traits @@ -741,9 +779,9 @@ impl Display for char { #[stable(feature = "rust1", since = "1.0.0")] impl Pointer for *const T { fn fmt(&self, f: &mut Formatter) -> Result { - f.flags |= 1 << (rt::FlagAlternate as uint); + f.flags |= 1 << (FlagV1::Alternate as uint); let ret = LowerHex::fmt(&(*self as uint), f); - f.flags &= !(1 << (rt::FlagAlternate as uint)); + f.flags &= !(1 << (FlagV1::Alternate as uint)); ret } } @@ -899,7 +937,7 @@ impl<'a> Debug for &'a (any::Any+'a) { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for [T] { fn fmt(&self, f: &mut Formatter) -> Result { - if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 { + if f.flags & (1 << (FlagV1::Alternate as uint)) == 0 { try!(write!(f, "[")); } let mut is_first = true; @@ -911,7 +949,7 @@ impl Debug for [T] { } try!(write!(f, "{:?}", *x)) } - if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 { + if f.flags & (1 << (FlagV1::Alternate as uint)) == 0 { try!(write!(f, "]")); } Ok(()) diff --git a/src/libcore/fmt/rt.rs b/src/libcore/fmt/rt.rs deleted file mode 100644 index 0b2c1efbc5dee..0000000000000 --- a/src/libcore/fmt/rt.rs +++ /dev/null @@ -1,86 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! This is an internal module used by the ifmt! runtime. These structures are -//! emitted to static arrays to precompile format strings ahead of time. -//! -//! These definitions are similar to their `ct` equivalents, but differ in that -//! these can be statically allocated and are slightly optimized for the runtime - -#![unstable(feature = "core", - reason = "implementation detail of the `format_args!` macro")] - -pub use self::Alignment::*; -pub use self::Count::*; -pub use self::Position::*; -pub use self::Flag::*; - -#[doc(hidden)] -#[derive(Copy)] -pub struct Argument { - pub position: Position, - pub format: FormatSpec, -} - -#[doc(hidden)] -#[derive(Copy)] -pub struct FormatSpec { - pub fill: char, - pub align: Alignment, - pub flags: uint, - pub precision: Count, - pub width: Count, -} - -/// Possible alignments that can be requested as part of a formatting directive. -#[derive(Copy, PartialEq)] -pub enum Alignment { - /// Indication that contents should be left-aligned. - AlignLeft, - /// Indication that contents should be right-aligned. - AlignRight, - /// Indication that contents should be center-aligned. - AlignCenter, - /// No alignment was requested. - AlignUnknown, -} - -#[doc(hidden)] -#[derive(Copy)] -pub enum Count { - CountIs(uint), CountIsParam(uint), CountIsNextParam, CountImplied, -} - -#[doc(hidden)] -#[derive(Copy)] -pub enum Position { - ArgumentNext, ArgumentIs(uint) -} - -/// Flags which can be passed to formatting via a directive. -/// -/// These flags are discovered through the `flags` field of the `Formatter` -/// structure. The flag in that structure is a union of these flags into a -/// `uint` where each flag's discriminant is the corresponding bit. -#[derive(Copy)] -pub enum Flag { - /// A flag which enables number formatting to always print the sign of a - /// number. - FlagSignPlus, - /// Currently not a used flag - FlagSignMinus, - /// Indicates that the "alternate formatting" for a type should be used. - /// - /// The meaning of this flag is type-specific. - FlagAlternate, - /// Indicates that padding should be done with a `0` character as well as - /// being aware of the sign to be printed. - FlagSignAwareZeroPad, -} diff --git a/src/libcore/fmt/rt/v1.rs b/src/libcore/fmt/rt/v1.rs new file mode 100644 index 0000000000000..f0c82759b7056 --- /dev/null +++ b/src/libcore/fmt/rt/v1.rs @@ -0,0 +1,94 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! This is an internal module used by the ifmt! runtime. These structures are +//! emitted to static arrays to precompile format strings ahead of time. +//! +//! These definitions are similar to their `ct` equivalents, but differ in that +//! these can be statically allocated and are slightly optimized for the runtime + +#![stable(feature = "rust1", since = "1.0.0")] + +#[cfg(stage0)] pub use self::Position::*; + +#[cfg(stage0)] pub use self::Alignment::Left as AlignLeft; +#[cfg(stage0)] pub use self::Alignment::Right as AlignRight; +#[cfg(stage0)] pub use self::Alignment::Center as AlignCenter; +#[cfg(stage0)] pub use self::Alignment::Unknown as AlignUnknown; +#[cfg(stage0)] pub use self::Count::Is as CountIs; +#[cfg(stage0)] pub use self::Count::Implied as CountImplied; +#[cfg(stage0)] pub use self::Count::Param as CountIsParam; +#[cfg(stage0)] pub use self::Count::NextParam as CountIsNextParam; +#[cfg(stage0)] pub use self::Position::Next as ArgumentNext; +#[cfg(stage0)] pub use self::Position::At as ArgumentIs; + +#[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Argument { + #[stable(feature = "rust1", since = "1.0.0")] + pub position: Position, + #[stable(feature = "rust1", since = "1.0.0")] + pub format: FormatSpec, +} + +#[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct FormatSpec { + #[stable(feature = "rust1", since = "1.0.0")] + pub fill: char, + #[stable(feature = "rust1", since = "1.0.0")] + pub align: Alignment, + #[stable(feature = "rust1", since = "1.0.0")] + pub flags: uint, + #[stable(feature = "rust1", since = "1.0.0")] + pub precision: Count, + #[stable(feature = "rust1", since = "1.0.0")] + pub width: Count, +} + +/// Possible alignments that can be requested as part of a formatting directive. +#[derive(Copy, PartialEq)] +#[stable(feature = "rust1", since = "1.0.0")] +pub enum Alignment { + /// Indication that contents should be left-aligned. + #[stable(feature = "rust1", since = "1.0.0")] + Left, + /// Indication that contents should be right-aligned. + #[stable(feature = "rust1", since = "1.0.0")] + Right, + /// Indication that contents should be center-aligned. + #[stable(feature = "rust1", since = "1.0.0")] + Center, + /// No alignment was requested. + #[stable(feature = "rust1", since = "1.0.0")] + Unknown, +} + +#[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] +pub enum Count { + #[stable(feature = "rust1", since = "1.0.0")] + Is(usize), + #[stable(feature = "rust1", since = "1.0.0")] + Param(usize), + #[stable(feature = "rust1", since = "1.0.0")] + NextParam, + #[stable(feature = "rust1", since = "1.0.0")] + Implied, +} + +#[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] +pub enum Position { + #[stable(feature = "rust1", since = "1.0.0")] + Next, + #[stable(feature = "rust1", since = "1.0.0")] + At(usize) +} diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 92a7465038bb1..fc7d4e868f746 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -229,7 +229,7 @@ use self::Result::{Ok, Err}; use clone::Clone; -use fmt::Debug; +use fmt; use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, ExactSizeIterator}; use ops::{FnMut, FnOnce}; use option::Option::{self, None, Some}; @@ -715,7 +715,7 @@ impl Result { } #[stable(feature = "rust1", since = "1.0.0")] -impl Result { +impl Result { /// Unwraps a result, yielding the content of an `Ok`. /// /// # Panics @@ -746,7 +746,7 @@ impl Result { } #[stable(feature = "rust1", since = "1.0.0")] -impl Result { +impl Result { /// Unwraps a result, yielding the content of an `Err`. /// /// # Panics diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 21d5cd3d516ab..6b14592c23b8c 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -362,19 +362,19 @@ impl<'a> Id<'a> { /// /// Passing an invalid string (containing spaces, brackets, /// quotes, ...) will return an empty `Err` value. - pub fn new>(name: Name) -> Option> { + pub fn new>(name: Name) -> Result, ()> { let name = name.into_cow(); { let mut chars = name.chars(); match chars.next() { Some(c) if is_letter_or_underscore(c) => { ; }, - _ => return None + _ => return Err(()) } if !chars.all(is_constituent) { - return None + return Err(()) } } - return Some(Id{ name: name }); + return Ok(Id{ name: name }); fn is_letter_or_underscore(c: char) -> bool { in_range('a', c, 'z') || in_range('A', c, 'Z') || c == '_' @@ -878,8 +878,8 @@ r#"digraph syntax_tree { fn simple_id_construction() { let id1 = Id::new("hello"); match id1 { - Some(_) => {;}, - None => panic!("'hello' is not a valid value for id anymore") + Ok(_) => {;}, + Err(..) => panic!("'hello' is not a valid value for id anymore") } } @@ -887,8 +887,8 @@ r#"digraph syntax_tree { fn badly_formatted_id() { let id2 = Id::new("Weird { struct : ure } !!!"); match id2 { - Some(_) => panic!("graphviz id suddenly allows spaces, brackets and stuff"), - None => {;} + Ok(_) => panic!("graphviz id suddenly allows spaces, brackets and stuff"), + Err(..) => {;} } } } diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs index 3d8348e8f5a99..1f0fe4f1acaea 100644 --- a/src/librustc/middle/cfg/graphviz.rs +++ b/src/librustc/middle/cfg/graphviz.rs @@ -54,10 +54,10 @@ fn replace_newline_with_backslash_l(s: String) -> String { } impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> { - fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(&self.name[]).unwrap() } + fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(&self.name[]).ok().unwrap() } fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> { - dot::Id::new(format!("N{}", i.node_id())).unwrap() + dot::Id::new(format!("N{}", i.node_id())).ok().unwrap() } fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> { diff --git a/src/librustc/middle/infer/region_inference/graphviz.rs b/src/librustc/middle/infer/region_inference/graphviz.rs index 215c4945ea920..b1ca4e625155d 100644 --- a/src/librustc/middle/infer/region_inference/graphviz.rs +++ b/src/librustc/middle/infer/region_inference/graphviz.rs @@ -157,10 +157,10 @@ impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> { impl<'a, 'tcx> dot::Labeller<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> { fn graph_id(&self) -> dot::Id { - dot::Id::new(self.graph_name.as_slice()).unwrap() + dot::Id::new(self.graph_name.as_slice()).ok().unwrap() } fn node_id(&self, n: &Node) -> dot::Id { - dot::Id::new(format!("node_{}", self.node_ids.get(n).unwrap())).unwrap() + dot::Id::new(format!("node_{}", self.node_ids.get(n).unwrap())).ok().unwrap() } fn node_label(&self, n: &Node) -> dot::LabelText { match *n { diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 2e7a6fd492354..d6eb05a867eca 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -3951,8 +3951,8 @@ mod tests { struct ArbitraryType(uint); let mut hm: HashMap = HashMap::new(); hm.insert(ArbitraryType(1), true); - let mut mem_buf = Vec::new(); - let mut encoder = Encoder::new(&mut mem_buf as &mut fmt::Writer); + let mut mem_buf = string::String::new(); + let mut encoder = Encoder::new(&mut mem_buf); let result = hm.encode(&mut encoder); match result.err().unwrap() { EncoderError::BadHashmapKey => (), diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index fdd7aa216d3c0..2e55c007b551b 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -122,7 +122,7 @@ impl Deref for CString { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for CString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - String::from_utf8_lossy(self.as_bytes()).fmt(f) + fmt::Debug::fmt(&String::from_utf8_lossy(self.as_bytes()), f) } } diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs index 4ab43e875cdff..a1d6d097607bf 100644 --- a/src/libstd/fmt.rs +++ b/src/libstd/fmt.rs @@ -411,9 +411,10 @@ pub use core::fmt::{Display, Debug}; pub use core::fmt::{LowerHex, UpperHex, Pointer}; pub use core::fmt::{LowerExp, UpperExp}; pub use core::fmt::Error; -pub use core::fmt::{Argument, Arguments, write, radix, Radix, RadixFmt}; +pub use core::fmt::{ArgumentV1, Arguments, write, radix, Radix, RadixFmt}; #[doc(hidden)] +#[cfg(stage0)] pub use core::fmt::{argument, argumentuint}; /// The format function takes a precompiled format string and a list of @@ -431,9 +432,7 @@ pub use core::fmt::{argument, argumentuint}; /// let s = fmt::format(format_args!("Hello, {}!", "world")); /// assert_eq!(s, "Hello, world!".to_string()); /// ``` -#[unstable(feature = "std_misc", - reason = "this is an implementation detail of format! and should not \ - be called directly")] +#[stable(feature = "rust1", since = "1.0.0")] pub fn format(args: Arguments) -> string::String { let mut output = string::String::new(); let _ = write!(&mut output, "{}", args); diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index d3e60de2780e9..b47d81ae17364 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -393,14 +393,15 @@ impl Command { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Command { /// Format the program and arguments of a Command for display. Any /// non-utf8 data is lossily converted using the utf8 replacement /// character. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{}", String::from_utf8_lossy(self.program.as_bytes()))); + try!(write!(f, "{:?}", self.program)); for arg in self.args.iter() { - try!(write!(f, " '{}'", String::from_utf8_lossy(arg.as_bytes()))); + try!(write!(f, " '{:?}'", arg)); } Ok(()) } diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 6a43eccbaba4e..f048dc9a84dc1 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -382,8 +382,8 @@ impl !Sync for SyncSender {} /// A `send` operation can only fail if the receiving end of a channel is /// disconnected, implying that the data could never be received. The error /// contains the data being sent as a payload so it can be recovered. -#[derive(PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] +#[derive(PartialEq, Eq, Clone, Copy)] pub struct SendError(pub T); /// An error returned from the `recv` function on a `Receiver`. @@ -396,7 +396,7 @@ pub struct RecvError; /// This enumeration is the list of the possible reasons that try_recv could not /// return data when called. -#[derive(PartialEq, Clone, Copy, Debug)] +#[derive(PartialEq, Eq, Clone, Copy, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub enum TryRecvError { /// This channel is currently empty, but the sender(s) have not yet @@ -412,8 +412,8 @@ pub enum TryRecvError { /// This enumeration is the list of the possible error outcomes for the /// `SyncSender::try_send` method. -#[derive(PartialEq, Clone)] #[stable(feature = "rust1", since = "1.0.0")] +#[derive(PartialEq, Eq, Clone, Copy)] pub enum TrySendError { /// The data could not be sent on the channel because it would require that /// the callee block to send the data. diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 2a0a352f1281a..36dbf11760457 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -17,7 +17,7 @@ use ext::base::*; use ext::base; use ext::build::AstBuilder; use fmt_macros as parse; -use parse::token::{InternedString, special_idents}; +use parse::token::special_idents; use parse::token; use ptr::P; @@ -300,56 +300,35 @@ impl<'a, 'b> Context<'a, 'b> { } } - /// These attributes are applied to all statics that this syntax extension - /// will generate. - fn static_attrs(ecx: &ExtCtxt, fmtsp: Span) -> Vec { - // Flag statics as `inline` so LLVM can merge duplicate globals as much - // as possible (which we're generating a whole lot of). - let unnamed = ecx.meta_word(fmtsp, InternedString::new("inline")); - let unnamed = ecx.attribute(fmtsp, unnamed); - - // Do not warn format string as dead code - let dead_code = ecx.meta_word(fmtsp, InternedString::new("dead_code")); - let allow_dead_code = ecx.meta_list(fmtsp, - InternedString::new("allow"), - vec![dead_code]); - let allow_dead_code = ecx.attribute(fmtsp, allow_dead_code); - vec![unnamed, allow_dead_code] - } - fn rtpath(ecx: &ExtCtxt, s: &str) -> Vec { - vec![ecx.ident_of("std"), ecx.ident_of("fmt"), ecx.ident_of("rt"), ecx.ident_of(s)] + vec![ecx.ident_of("std"), ecx.ident_of("fmt"), ecx.ident_of("rt"), + ecx.ident_of("v1"), ecx.ident_of(s)] } fn trans_count(&self, c: parse::Count) -> P { let sp = self.fmtsp; - match c { - parse::CountIs(i) => { - self.ecx.expr_call_global(sp, Context::rtpath(self.ecx, "CountIs"), - vec!(self.ecx.expr_usize(sp, i))) + let count = |: c, arg| { + let mut path = Context::rtpath(self.ecx, "Count"); + path.push(self.ecx.ident_of(c)); + match arg { + Some(arg) => self.ecx.expr_call_global(sp, path, vec![arg]), + None => self.ecx.expr_path(self.ecx.path_global(sp, path)), } + }; + match c { + parse::CountIs(i) => count("Is", Some(self.ecx.expr_usize(sp, i))), parse::CountIsParam(i) => { - self.ecx.expr_call_global(sp, Context::rtpath(self.ecx, "CountIsParam"), - vec!(self.ecx.expr_usize(sp, i))) - } - parse::CountImplied => { - let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, - "CountImplied")); - self.ecx.expr_path(path) - } - parse::CountIsNextParam => { - let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, - "CountIsNextParam")); - self.ecx.expr_path(path) + count("Param", Some(self.ecx.expr_usize(sp, i))) } + parse::CountImplied => count("Implied", None), + parse::CountIsNextParam => count("NextParam", None), parse::CountIsName(n) => { let i = match self.name_positions.get(n) { Some(&i) => i, None => 0, // error already emitted elsewhere }; let i = i + self.args.len(); - self.ecx.expr_call_global(sp, Context::rtpath(self.ecx, "CountIsParam"), - vec!(self.ecx.expr_usize(sp, i))) + count("Param", Some(self.ecx.expr_usize(sp, i))) } } } @@ -373,27 +352,35 @@ impl<'a, 'b> Context<'a, 'b> { } parse::NextArgument(ref arg) => { // Translate the position - let pos = match arg.position { - // These two have a direct mapping - parse::ArgumentNext => { - let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, - "ArgumentNext")); - self.ecx.expr_path(path) - } - parse::ArgumentIs(i) => { - self.ecx.expr_call_global(sp, Context::rtpath(self.ecx, "ArgumentIs"), - vec!(self.ecx.expr_usize(sp, i))) - } - // Named arguments are converted to positional arguments at - // the end of the list of arguments - parse::ArgumentNamed(n) => { - let i = match self.name_positions.get(n) { - Some(&i) => i, - None => 0, // error already emitted elsewhere - }; - let i = i + self.args.len(); - self.ecx.expr_call_global(sp, Context::rtpath(self.ecx, "ArgumentIs"), - vec!(self.ecx.expr_usize(sp, i))) + let pos = { + let pos = |: c, arg| { + let mut path = Context::rtpath(self.ecx, "Position"); + path.push(self.ecx.ident_of(c)); + match arg { + Some(i) => { + let arg = self.ecx.expr_usize(sp, i); + self.ecx.expr_call_global(sp, path, vec![arg]) + } + None => { + self.ecx.expr_path(self.ecx.path_global(sp, path)) + } + } + }; + match arg.position { + // These two have a direct mapping + parse::ArgumentNext => pos("Next", None), + parse::ArgumentIs(i) => pos("At", Some(i)), + + // Named arguments are converted to positional arguments + // at the end of the list of arguments + parse::ArgumentNamed(n) => { + let i = match self.name_positions.get(n) { + Some(&i) => i, + None => 0, // error already emitted elsewhere + }; + let i = i + self.args.len(); + pos("At", Some(i)) + } } }; @@ -417,19 +404,16 @@ impl<'a, 'b> Context<'a, 'b> { // Translate the format let fill = self.ecx.expr_lit(sp, ast::LitChar(fill)); + let align = |:name| { + let mut p = Context::rtpath(self.ecx, "Alignment"); + p.push(self.ecx.ident_of(name)); + self.ecx.path_global(sp, p) + }; let align = match arg.format.align { - parse::AlignLeft => { - self.ecx.path_global(sp, Context::rtpath(self.ecx, "AlignLeft")) - } - parse::AlignRight => { - self.ecx.path_global(sp, Context::rtpath(self.ecx, "AlignRight")) - } - parse::AlignCenter => { - self.ecx.path_global(sp, Context::rtpath(self.ecx, "AlignCenter")) - } - parse::AlignUnknown => { - self.ecx.path_global(sp, Context::rtpath(self.ecx, "AlignUnknown")) - } + parse::AlignLeft => align("Left"), + parse::AlignRight => align("Right"), + parse::AlignCenter => align("Center"), + parse::AlignUnknown => align("Unknown"), }; let align = self.ecx.expr_path(align); let flags = self.ecx.expr_usize(sp, arg.format.flags); @@ -465,7 +449,7 @@ impl<'a, 'b> Context<'a, 'b> { 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 item = ecx.item(fmtsp, name, vec![], st); let decl = respan(fmtsp, ast::DeclItem(item)); // Wrap the declaration in a block so that it forms a single expression. @@ -575,7 +559,7 @@ impl<'a, 'b> Context<'a, 'b> { // 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]) + ("new_v1", vec![pieces, args_slice]) } else { // Build up the static array which will store our precompiled // nonstandard placeholders, if there are any. @@ -587,7 +571,7 @@ impl<'a, 'b> Context<'a, 'b> { piece_ty, self.pieces); - ("with_placeholders", vec![pieces, fmt, args_slice]) + ("new_v1_formatted", vec![pieces, args_slice, fmt]) }; self.ecx.expr_call_global(self.fmtsp, vec!( @@ -624,7 +608,8 @@ impl<'a, 'b> Context<'a, 'b> { return ecx.expr_call_global(sp, vec![ ecx.ident_of("std"), ecx.ident_of("fmt"), - ecx.ident_of("argumentuint")], vec![arg]) + ecx.ident_of("ArgumentV1"), + ecx.ident_of("from_uint")], vec![arg]) } }; @@ -636,7 +621,8 @@ impl<'a, 'b> Context<'a, 'b> { ecx.expr_call_global(sp, vec![ ecx.ident_of("std"), ecx.ident_of("fmt"), - ecx.ident_of("argument")], vec![ecx.expr_path(format_fn), arg]) + ecx.ident_of("ArgumentV1"), + ecx.ident_of("new")], vec![arg, ecx.expr_path(format_fn)]) } } diff --git a/src/test/compile-fail/lint-dead-code-4.rs b/src/test/compile-fail/lint-dead-code-4.rs index 22570bad61696..449788459dcff 100644 --- a/src/test/compile-fail/lint-dead-code-4.rs +++ b/src/test/compile-fail/lint-dead-code-4.rs @@ -13,7 +13,6 @@ #![deny(dead_code)] #![feature(libc)] #![feature(core)] -#![feature(collections)] extern crate libc; diff --git a/src/test/compile-fail/missing_debug_impls.rs b/src/test/compile-fail/missing_debug_impls.rs index 5b781a40fe548..bc4bfef4d48c4 100644 --- a/src/test/compile-fail/missing_debug_impls.rs +++ b/src/test/compile-fail/missing_debug_impls.rs @@ -11,7 +11,6 @@ // compile-flags: --crate-type lib #![deny(missing_debug_implementations)] #![allow(unused, missing_copy_implementations)] -#![feature(core)] use std::fmt; diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index c18d076c0d318..b1d38f5dc9b16 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -41,41 +41,39 @@ ((::std::fmt::format as - fn(core::fmt::Arguments<'_>) -> collections::string::String {std::fmt::format})(((::std::fmt::Arguments::new + fn(core::fmt::Arguments<'_>) -> collections::string::String {std::fmt::format})(((::std::fmt::Arguments::new_v1 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 + fn(&[&str], &[core::fmt::ArgumentV1<'_>]) -> core::fmt::Arguments<'_> {core::fmt::Arguments<'a>::new_v1})(({ + 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 - &'static [&'static str]) - } - as - &[&str]), - (&(match (() - as - ()) - { - () - => - ([] + &[&str]), + (&(match (() + as + ()) + { + () + => + ([] + as + [core::fmt::ArgumentV1<'_>; 0]), + } as - [core::fmt::Argument<'_>; 0]), - } - as - [core::fmt::Argument<'_>; 0]) - as - &[core::fmt::Argument<'_>; 0])) + [core::fmt::ArgumentV1<'_>; 0]) + as + &[core::fmt::ArgumentV1<'_>; 0])) as core::fmt::Arguments<'_>)) as collections::string::String);