|
| 1 | +- Start Date: (fill me in with today's date, YYYY-MM-DD) |
| 2 | +- RFC PR: (leave this empty) |
| 3 | +- Rust Issue: (leave this empty) |
| 4 | + |
| 5 | +# Summary |
| 6 | + |
| 7 | +* Remove reflection from the compiler |
| 8 | +* Remove `libdebug` |
| 9 | +* Remove the `Poly` format trait as well as the `:?` format specifier |
| 10 | + |
| 11 | +# Motivation |
| 12 | + |
| 13 | +In ancient Rust, one of the primary methods of printing a value was via the `%?` |
| 14 | +format specifier. This would use reflection at runtime to determine how to print |
| 15 | +a type. Metadata generated by the compiler (a `TyDesc`) would be generated to |
| 16 | +guide the runtime in how to print a type. One of the great parts about |
| 17 | +reflection was that it was quite easy to print any type. No extra burden was |
| 18 | +required from the programmer to print something. |
| 19 | + |
| 20 | +There are, however, a number of cons to this approach: |
| 21 | + |
| 22 | +* Generating extra metadata for many many types by the compiler can lead to |
| 23 | + noticeable increases in compile time and binary size. |
| 24 | +* This form of formatting is inherently not speedy. Widespread usage of `%?` led |
| 25 | + to misleading benchmarks about formatting in Rust. |
| 26 | +* Depending on how metadata is handled, this scheme makes it very difficult to |
| 27 | + allow recompiling a library without recompiling downstream dependants. |
| 28 | + |
| 29 | +Over time, usage off the `?` formatting has fallen out of fashion for the |
| 30 | +following reasons: |
| 31 | + |
| 32 | +* The `deriving`-based infrastructure was improved greatly and has started |
| 33 | + seeing much more widespread use, especially for traits like `Clone`. |
| 34 | +* The formatting language implementation and syntax has changed. The most common |
| 35 | + formatter is now `{}` (an implementation of `Show`), and it is quite common to |
| 36 | + see an implementation of `Show` on nearly all types (frequently via |
| 37 | + `deriving`). This form of customizable-per-typformatting largely provides the |
| 38 | + gap that the original formatting language did not provide, which was limited |
| 39 | + to only primitives and `%?`. |
| 40 | +* Compiler built-ins, such as `~[T]` and `~str` have been removed from the |
| 41 | + language, and runtime reflection on `Vec<T>` and `String` are far less useful |
| 42 | + (they just print pointers, not contents). |
| 43 | + |
| 44 | +As a result, the `:?` formatting specifier is quite rarely used today, and |
| 45 | +when it *is* used it's largely for historical purposes and the output is not of |
| 46 | +very high quality any more. |
| 47 | + |
| 48 | +The drawbacks and today's current state of affairs motivate this RFC to |
| 49 | +recommend removing this infrastructure entirely. It's possible to add it back in |
| 50 | +the future with a more modern design reflecting today's design principles of |
| 51 | +Rust and the many language changes since the infrastructure was created. |
| 52 | + |
| 53 | +# Detailed design |
| 54 | + |
| 55 | +* Remove all reflection infrastructure from the compiler. I am not personally |
| 56 | + super familiar with what exists, but at least these concrete actions will be |
| 57 | + taken. |
| 58 | + * Remove the `visit_glue` function from `TyDesc`. |
| 59 | + * Remove any form of `visit_glue` generation. |
| 60 | + * (maybe?) Remove the `name` field of `TyDesc`. |
| 61 | +* Remove `core::intrinsics::TyVisitor` |
| 62 | +* Remove `core::intrinsics::visit_tydesc` |
| 63 | +* Remove `libdebug` |
| 64 | +* Remove `std::fmt::Poly` |
| 65 | +* Remove the `:?` format specifier in the formatting language syntax. |
| 66 | + |
| 67 | +# Drawbacks |
| 68 | + |
| 69 | +The current infrastructure for reflection, although outdated, represents a |
| 70 | +significant investment of work in the past which could be a shame to lose. While |
| 71 | +present in the git history, this infrastructure has been updated over time, and |
| 72 | +it will no longer receive this attention. |
| 73 | + |
| 74 | +Additionally, given an arbitrary type `T`, it would now be impossible to print |
| 75 | +it in literally any situation. Type parameters will now require some bound, such |
| 76 | +as `Show`, to allow printing a type. |
| 77 | + |
| 78 | +These two drawbacks are currently not seen as large enough to outweigh the gains |
| 79 | +from reducing the surface area of the `std::fmt` API and reduction in |
| 80 | +maintenance load on the compiler. |
| 81 | + |
| 82 | +# Alternatives |
| 83 | + |
| 84 | +The primary alternative to outright removing this infrastructure is to preserve |
| 85 | +it, but flag it all as `#[experimental]` or feature-gated. The compiler could |
| 86 | +require the `fmt_poly` feature gate to be enabled to enable formatting via `:?` |
| 87 | +in a crate. This would mean that any backwards-incompatible changes could |
| 88 | +continue to be made, and any arbitrary type `T` could still be printed. |
| 89 | + |
| 90 | +# Unresolved questions |
| 91 | + |
| 92 | +* Can `core::intrinsics::TyDesc` be removed entirely? |
0 commit comments