|
| 1 | +- Feature Name: (fill me in with a unique ident, `reexport-stdlib-macros`) |
| 2 | +- Start Date: (fill me in with today's date, 2022-01-04) |
| 3 | +- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) |
| 4 | +- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) |
| 5 | + |
| 6 | +# Summary |
| 7 | +[summary]: #summary |
| 8 | + |
| 9 | +This RFC proposed we start re-exporting macros currently exposed in `core::*` |
| 10 | +from submodules. We define a mapping of which macros to re-export from which |
| 11 | +submodules, though in some cases it makes most sense to keep the macros exported |
| 12 | +from `core`. |
| 13 | + |
| 14 | +This RFC does not yet propose we deprecate or migrate any code, |
| 15 | +that is left up to future RFCs. |
| 16 | + |
| 17 | +# Motivation |
| 18 | +[motivation]: #motivation |
| 19 | + |
| 20 | +Right now the Rust stdlib exports over 70 macros, most of which exist only in |
| 21 | +the crate root - despite providing a wide range of functionality. This has |
| 22 | +negative consequences for the stdlib's root: not only are there countless |
| 23 | +submodules, there are also an overwhelming number of macros doing an assortment |
| 24 | +of things. But it also has negative consequences for the individual submodules: |
| 25 | +they will often only tell part of a story, and often leave out crucial |
| 26 | +information on how they should actually be used. |
| 27 | + |
| 28 | +Take for example the [`std::panic` |
| 29 | +submodule](https://doc.rust-lang.org/std/panic/index.html). It includes various |
| 30 | +methods to inspect, catch, and even modify panic behavior. But it includes no |
| 31 | +facilities to actually trigger panics. Experienced rustaceans will know that |
| 32 | +this can be done using `panic!`, `todo!`, `unimplemented!` and the like. But for |
| 33 | +someone new to Rust, this information is not made readily available. |
| 34 | + |
| 35 | +When macros are available from submodules we can begin to paint a more complete |
| 36 | +picture of how those submodules are intended to be used. Up until recently it |
| 37 | +wasn't possible to expose macros from submodules, but now that it is we should |
| 38 | +take the opportunity to start making use of it. |
| 39 | + |
| 40 | +# Mapping re-exports |
| 41 | + |
| 42 | +The following table covers which macro we're talking about, which sub-module it |
| 43 | +should be made available from, whether that's a new sub-module, and whether the |
| 44 | +macro is unstable. Macros which are unstable can be _moved_ rather than just |
| 45 | +re-exported. |
| 46 | + |
| 47 | +| __Macro name__ | __Proposed mod__ | __New exports?__ | __Unstable?__ | |
| 48 | +|----------------------------------------|--------------------|------------------|---------------| |
| 49 | +| `assert` | `core::panic` | ✅ | ❌ | |
| 50 | +| `assert_eq` | `core::panic` | ✅ | ❌ | |
| 51 | +| `assert_matches::assert_matches` | `core::panic` | ✅ | ✅ | |
| 52 | +| `assert_matches::debug_assert_matches` | `core::panic` | ✅ | ✅ | |
| 53 | +| `assert_ne` | `core::panic` | ✅ | ❌ | |
| 54 | +| `cfg` | `core` | ❌ | ❌ | |
| 55 | +| `clone::Clone` | `core::clone` | ❌ | ❌ | |
| 56 | +| `cmp::Eq` | `core::cmp` | ❌ | ❌ | |
| 57 | +| `cmp::Ord` | `core::cmp` | ❌ | ❌ | |
| 58 | +| `cmp::PartialEq` | `core::cmp` | ❌ | ❌ | |
| 59 | +| `cmp::PartialOrd` | `core::cmp` | ❌ | ❌ | |
| 60 | +| `column` | `core` | ❌ | ❌ | |
| 61 | +| `compile_error` | `core` | ❌ | ❌ | |
| 62 | +| `concat` | `core` | ❌ | ❌ | |
| 63 | +| `concat_bytes` | `core` | ❌ | ✅ | |
| 64 | +| `concat_idents` | `core` | ❌ | ✅ | |
| 65 | +| `const_format_args` | `core::fmt` | ✅ | ✅ | |
| 66 | +| `dbg` | `core::io` | ✅ | ❌ | |
| 67 | +| `debug_assert` | `core::panic` | ✅ | ❌ | |
| 68 | +| `debug_assert_eq` | `core::panic` | ✅ | ❌ | |
| 69 | +| `debug_assert_ne` | `core::panic` | ✅ | ❌ | |
| 70 | +| `default::Default` | `core::default` | ❌ | ❌ | |
| 71 | +| `env` | `core` | ❌ | ❌ | |
| 72 | +| `eprint` | `core::io` | ✅ | ❌ | |
| 73 | +| `eprintln` | `core::io` | ✅ | ❌ | |
| 74 | +| `file` | `core` | ❌ | ❌ | |
| 75 | +| `fmt::Debug` | `core::fmt` | ❌ | ❌ | |
| 76 | +| `format` | `core::fmt` | ✅ | ❌ | |
| 77 | +| `format_args` | `core::fmt` | ✅ | ❌ | |
| 78 | +| `format_args_nl` | `core::fmt` | ✅ | ✅ | |
| 79 | +| `future::join` | `core` | ❌ | ✅ | |
| 80 | +| `hash::Hash` | `core::hash::Hash` | ❌ | ❌ | |
| 81 | +| `include` | `core` | ❌ | ❌ | |
| 82 | +| `include_bytes` | `core` | ❌ | ❌ | |
| 83 | +| `include_str` | `core` | ❌ | ❌ | |
| 84 | +| `is_aarch64_feature_detected` | `core::arch` | ✅ | ✅ | |
| 85 | +| `is_arm_feature_detected` | `core::arch` | ✅ | ✅ | |
| 86 | +| `is_mips64_feature_detected` | `core::arch` | ✅ | ✅ | |
| 87 | +| `is_mips_feature_detected` | `core::arch` | ✅ | ✅ | |
| 88 | +| `is_powerpc64_feature_detected` | `core::arch` | ✅ | ✅ | |
| 89 | +| `is_powerpc_feature_detected` | `core::arch` | ✅ | ✅ | |
| 90 | +| `is_riscv_feature_detected` | `core::arch` | ✅ | ✅ | |
| 91 | +| `is_x86_feature_detected` | `core::arch` | ✅ | ✅ | |
| 92 | +| `line` | `core` | ❌ | ❌ | |
| 93 | +| `llvm_asm` | `core` | ❌ | ✅ | |
| 94 | +| `log_syntax` | `core` | ❌ | ✅ | |
| 95 | +| `marker::Copy` | `core::marker` | ❌ | ❌ | |
| 96 | +| `matches` | `core` | ❌ | ❌ | |
| 97 | +| `module_path` | `core` | ❌ | ❌ | |
| 98 | +| `option_env` | `core` | ❌ | ❌ | |
| 99 | +| `panic` | `core::panic` | ✅ | ❌ | |
| 100 | +| `prelude::v1::bench` | `core::prelude::v1` | ❌ | ✅ | |
| 101 | +| `prelude::v1::cfg_accessible` | `core::prelude::v1` | ❌ | ❌ | |
| 102 | +| `prelude::v1::cfg_eval` | `core::prelude::v1` | ❌ | ✅ | |
| 103 | +| `prelude::v1::derive` | `core::prelude::v1` | ❌ | ❌ | |
| 104 | +| `prelude::v1::global_allocator` | `core::prelude::v1` | ❌ | ❌ | |
| 105 | +| `prelude::v1::test` | `core::prelude::v1` | ❌ | ❌ | |
| 106 | +| `prelude::v1::test_case` | `core::prelude::v1` | ❌ | ✅ | |
| 107 | +| `print` | `core::io` | ✅ | ❌ | |
| 108 | +| `println` | `core::io` | ✅ | ❌ | |
| 109 | +| `ptr::addr_of` | `core::ptr` | ❌ | ❌ | |
| 110 | +| `ptr::addr_of_mut` | `core::ptr` | ❌ | ❌ | |
| 111 | +| `simd::simd_swizzle` | `core::simd` | ❌ | ✅ | |
| 112 | +| `stringify` | `core` | ❌ | ❌ | |
| 113 | +| `task::ready` | `core::task` | ❌ | ❌ | |
| 114 | +| `thread_local` | `core::thread` | ✅ | ❌ | |
| 115 | +| `todo` | `core::panic` | ✅ | ❌ | |
| 116 | +| `trace_macros` | `core` | ❌ | ✅ | |
| 117 | +| `try` | `core` | ❌ | ❌ | |
| 118 | +| `unimplemented` | `core::panic` | ✅ | ❌ | |
| 119 | +| `unreachable` | `core::panic` | ✅ | ❌ | |
| 120 | +| `vec` | `core::vec` | ✅ | ❌ | |
| 121 | +| `write` | `core` | ❌ | ❌ | |
| 122 | +| `writeln` | `core` | ❌ | ❌ | |
| 123 | + |
| 124 | +# Reference-level explanation |
| 125 | +[reference-level-explanation]: #reference-level-explanation |
| 126 | + |
| 127 | +The implementation of this RFC should be no more than adding a re-export from |
| 128 | +the submodule to the existing macro found in the crate root. Say we're re-exporting |
| 129 | +`core::assert` from `core::panic::assert`, we could imagine it being done along |
| 130 | +these lines: |
| 131 | + |
| 132 | +```rust |
| 133 | +pub mod core { |
| 134 | + /// Panics the current thread. |
| 135 | + #[macro_export] |
| 136 | + macro_rules! panic { ... } |
| 137 | + |
| 138 | + pub mod panic { |
| 139 | + pub use crate::panic; |
| 140 | + } |
| 141 | +} |
| 142 | +``` |
| 143 | + |
| 144 | +Some of these macros such as `panic!` will be built-ins, meaning that changing |
| 145 | +their implementations might have implications for the compiler. Because this RFC |
| 146 | +only proposes we re-export macros and not _migrate_ macros (see "future |
| 147 | +possibilities"), simply creating an alias for the macro from the submodule is enough. |
| 148 | + |
| 149 | +# Prior art |
| 150 | +[prior-art]: #prior-art |
| 151 | + |
| 152 | +It was only up to recently that it wasn't possible to export macros from |
| 153 | +submodules. New macros being added to the stdlib are already available from |
| 154 | +submodules (e.g. `std::ptr::addr_of`, `std::task::ready`). And derive-macros |
| 155 | +have always been available from submodules (e.g. `std::clone::Clone`, |
| 156 | +`std::hash::Hash`). |
| 157 | + |
| 158 | +Now that the technical restriction has been lifted, we can finally look |
| 159 | +at the existing macros and start to re-export them from their logical |
| 160 | +submodules. |
| 161 | + |
| 162 | +# Unresolved questions |
| 163 | +[unresolved-questions]: #unresolved-questions |
| 164 | + |
| 165 | +## `write/writeln` |
| 166 | + |
| 167 | +Both the `write` and `writeln` macros call a method named `write` on a type, as |
| 168 | +exists in the stdlib as |
| 169 | +[`std::fmt::Write`](https://doc.rust-lang.org/std/fmt/trait.Write.html) and |
| 170 | +[`std::io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html). |
| 171 | + |
| 172 | +Because `write/writeln` both need to be available from `core`, they would need |
| 173 | +to _at least_ be available from `core::fmt` - there is no `core::io`. But when |
| 174 | +considering the `std` docs it might make sense to expose them from both. One |
| 175 | +point in favor of doing it from both locations is that it would enable both the |
| 176 | +`fmt` and `io` docs to be more self-contained. But it's unclear what the best |
| 177 | +option would be. What should we do here? |
| 178 | + |
| 179 | +# Future possibilities |
| 180 | +[future-possibilities]: #future-possibilities |
| 181 | + |
| 182 | +## Deprecate macros in stdlib root |
| 183 | + |
| 184 | +Once we have the macros re-exported from their respective submodules, we can |
| 185 | +start looking at what to do with the macros currently still in the stdlib's |
| 186 | +root. Should we deprecate them over an edition? Should we change the way they're |
| 187 | +shown in the docs? Because having 50 or so deprecated items in the crate root |
| 188 | +seems like a lot. |
| 189 | + |
| 190 | +It's likely we'll want to do _something_ here, but it's unclear what exactly. |
| 191 | +Therefor we're leaving this as an open question which should be explored in the |
| 192 | +future, but for now is out of the scope of this RFC. |
| 193 | + |
| 194 | +## API Guidlines |
| 195 | + |
| 196 | +It might be helpful for the stdlib's API guidelines to include a section |
| 197 | +explaining when to export macros from existing submodules, when to export them |
| 198 | +from newly created submodules, and when to export them from the crate root. |
0 commit comments