Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std: Stabilize the std::fmt module #21125

Closed
wants to merge 1 commit into from

Conversation

alexcrichton
Copy link
Member

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, 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.

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)

While stabilize the formatting traits, the following change was also made to the
result module:

  • Result::unwrap now requires String instead of Show
  • Result::unwrap_err now requires String instead of Show

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. It is also a
breaking change due to the usage of String for unwrap() on Result instead
of Show. Error types should implement String for human readable errors and
Show for inspecting their representation.

Closes #20661
[breaking-change]

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`)

While stabilize the formatting traits, the following change was also made to the
`result` module:

* `Result::unwrap` now requires `String` instead of `Show`
* `Result::unwrap_err` now requires `String` instead of `Show`

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. It is also a
breaking change due to the usage of `String` for `unwrap()` on `Result` instead
of `Show`. Error types should implement `String` for human readable errors and
`Show` for inspecting their representation.

Closes rust-lang#20661
[breaking-change]
@alexcrichton
Copy link
Member Author

r? @aturon

@rust-highfive rust-highfive assigned aturon and unassigned nikomatsakis Jan 14, 2015
@rust-highfive
Copy link
Collaborator

r? @nikomatsakis

(rust_highfive has picked a reviewer for you, use r? to override)

@aturon aturon mentioned this pull request Jan 14, 2015
38 tasks
@alexcrichton
Copy link
Member Author

Some open questions I thought of while writing this:

  • All formatting methods are called fmt, so delegation from one to another requires UFCS. This is intended to be pretty rare, however, so I don't think we need to optimize for this.
  • If Show for string::String escapes characters, should Show for CString/Path also have escaped characters? (currently the answer is no). I do think that this is somewhat of a squishy point, so I'm fine tweaking this after this PR.

@sfackler
Copy link
Member

Could we also get some stable way of extracting useful values out of Formatter.flags?

@alexcrichton
Copy link
Member Author

After some discussion on IRC I'm closing this until rust-lang/rfcs#565 has been decided

@alexcrichton alexcrichton deleted the second-pass-fmt branch January 20, 2015 06:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix detection of feature gate use inside of println!
5 participants