- Start Date: 2014-10-13
- RFC PR: [rust-lang/rfcs#379](https://github.com/rust-lang/rfcs/pull/379)
- Rust Issue: [rust-lang/rust#18046](https://github.com/rust-lang/rust/issues/18046)

# Summary

* Remove reflection from the compiler
* Remove `libdebug`
* Remove the `Poly` format trait as well as the `:?` format specifier

# Motivation

In ancient Rust, one of the primary methods of printing a value was via the `%?`
format specifier. This would use reflection at runtime to determine how to print
a type. Metadata generated by the compiler (a `TyDesc`) would be generated to
guide the runtime in how to print a type. One of the great parts about
reflection was that it was quite easy to print any type. No extra burden was
required from the programmer to print something.

There are, however, a number of cons to this approach:

* Generating extra metadata for many many types by the compiler can lead to
  noticeable increases in compile time and binary size.
* This form of formatting is inherently not speedy. Widespread usage of `%?` led
  to misleading benchmarks about formatting in Rust.
* Depending on how metadata is handled, this scheme makes it very difficult to
  allow recompiling a library without recompiling downstream dependants.

Over time, usage off the `?` formatting has fallen out of fashion for the
following reasons:

* The `deriving`-based infrastructure was improved greatly and has started
  seeing much more widespread use, especially for traits like `Clone`.
* The formatting language implementation and syntax has changed. The most common
  formatter is now `{}` (an implementation of `Show`), and it is quite common to
  see an implementation of `Show` on nearly all types (frequently via
  `deriving`). This form of customizable-per-typformatting largely provides the
  gap that the original formatting language did not provide, which was limited
  to only primitives and `%?`.
* Compiler built-ins, such as `~[T]` and `~str` have been removed from the
  language, and runtime reflection on `Vec<T>` and `String` are far less useful
  (they just print pointers, not contents).

As a result, the `:?` formatting specifier is quite rarely used today, and
when it *is* used it's largely for historical purposes and the output is not of
very high quality any more.

The drawbacks and today's current state of affairs motivate this RFC to
recommend removing this infrastructure entirely. It's possible to add it back in
the future with a more modern design reflecting today's design principles of
Rust and the many language changes since the infrastructure was created.

# Detailed design

* Remove all reflection infrastructure from the compiler. I am not personally
  super familiar with what exists, but at least these concrete actions will be
  taken.
  * Remove the `visit_glue` function from `TyDesc`.
  * Remove any form of `visit_glue` generation.
  * (maybe?) Remove the `name` field of `TyDesc`.
* Remove `core::intrinsics::TyVisitor`
* Remove `core::intrinsics::visit_tydesc`
* Remove `libdebug`
* Remove `std::fmt::Poly`
* Remove the `:?` format specifier in the formatting language syntax.

# Drawbacks

The current infrastructure for reflection, although outdated, represents a
significant investment of work in the past which could be a shame to lose. While
present in the git history, this infrastructure has been updated over time, and
it will no longer receive this attention.

Additionally, given an arbitrary type `T`, it would now be impossible to print
it in literally any situation. Type parameters will now require some bound, such
as `Show`, to allow printing a type.

These two drawbacks are currently not seen as large enough to outweigh the gains
from reducing the surface area of the `std::fmt` API and reduction in
maintenance load on the compiler.

# Alternatives

The primary alternative to outright removing this infrastructure is to preserve
it, but flag it all as `#[experimental]` or feature-gated. The compiler could
require the `fmt_poly` feature gate to be enabled to enable formatting via `:?`
in a crate. This would mean that any backwards-incompatible changes could
continue to be made, and any arbitrary type `T` could still be printed.

# Unresolved questions

* Can `core::intrinsics::TyDesc` be removed entirely?
