|
| 1 | +- Feature Name: N/A |
| 2 | +- Start Date: 2015-06-26 |
| 3 | +- RFC PR: https://github.com/rust-lang/rfcs/pull/1184 |
| 4 | +- Rust Issue: https://github.com/rust-lang/rust/issues/27394 |
| 5 | + |
| 6 | +# Summary |
| 7 | + |
| 8 | +Tweak the `#![no_std]` attribute, add a new `#![no_core]` attribute, and |
| 9 | +pave the way for stabilizing the libcore library. |
| 10 | + |
| 11 | +# Motivation |
| 12 | + |
| 13 | +Currently all stable Rust programs must link to the standard library (libstd), |
| 14 | +and it is impossible to opt out of this. The standard library is not appropriate |
| 15 | +for use cases such as kernels, embedded development, or some various niche cases |
| 16 | +in userspace. For these applications Rust itself is appropriate, but the |
| 17 | +compiler does not provide a stable interface compiling in this mode. |
| 18 | + |
| 19 | +The standard distribution provides a library, libcore, which is "the essence of |
| 20 | +Rust" as it provides many language features such as iterators, slice methods, |
| 21 | +string methods, etc. The defining feature of libcore is that it has 0 |
| 22 | +dependencies, unlike the standard library which depends on many I/O APIs, for |
| 23 | +example. The purpose of this RFC is to provide a stable method to access |
| 24 | +libcore. |
| 25 | + |
| 26 | +Applications which do not want to use libstd still want to use libcore 99% of |
| 27 | +the time, but unfortunately the current `#![no_std]` attribute does not do a |
| 28 | +great job in facilitating this. When moving into the realm of not using the |
| 29 | +standard library, the compiler should make the use case as ergonomic as |
| 30 | +possible, so this RFC proposes different behavior than today's `#![no_std]`. |
| 31 | + |
| 32 | +Finally, the standard library defines a number of language items which must be |
| 33 | +defined when libstd is not used. These language items are: |
| 34 | + |
| 35 | +* `panic_fmt` |
| 36 | +* `eh_personality` |
| 37 | +* `stack_exhausted` |
| 38 | + |
| 39 | +To be able to usefully leverage `#![no_std]` in stable Rust these lang items |
| 40 | +must be available in a stable fashion. |
| 41 | + |
| 42 | +# Detailed Design |
| 43 | + |
| 44 | +This RFC proposes a nuber of changes: |
| 45 | + |
| 46 | +* Tweak the `#![no_std]` attribute slightly. |
| 47 | +* Introduce a `#![no_core]` attribute. |
| 48 | +* Pave the way to stabilize the `core` module. |
| 49 | + |
| 50 | +## `no_std` |
| 51 | + |
| 52 | +The `#![no_std]` attribute currently provides two pieces of functionality: |
| 53 | + |
| 54 | +* The compiler no longer injects `extern crate std` at the top of a crate. |
| 55 | +* The prelude (`use std::prelude::v1::*`) is no longer injected at the top of |
| 56 | + every module. |
| 57 | + |
| 58 | +This RFC proposes adding the following behavior to the `#![no_std]` attribute: |
| 59 | + |
| 60 | +* The compiler will inject `extern crate core` at the top of a crate. |
| 61 | +* The libcore prelude will be injected at the top of every module. |
| 62 | + |
| 63 | +Most uses of `#![no_std]` already want behavior along these lines as they want |
| 64 | +to use libcore, just not the standard library. |
| 65 | + |
| 66 | +## `no_core` |
| 67 | + |
| 68 | +A new attribute will be added to the compiler, `#![no_core]`, which serves two |
| 69 | +purposes: |
| 70 | + |
| 71 | +* This attribute implies the `#![no_std]` attribute (no std prelude/crate |
| 72 | + injection). |
| 73 | +* This attribute will prevent core prelude/crate injection. |
| 74 | + |
| 75 | +Users of `#![no_std]` today who do *not* use libcore would migrate to moving |
| 76 | +this attribute instead of `#![no_std]`. |
| 77 | + |
| 78 | +## Stabilization of libcore |
| 79 | + |
| 80 | +This RFC does not yet propose a stabilization path for the contents of libcore, |
| 81 | +but it proposes readying to stabilize the name `core` for libcore, paving the |
| 82 | +way for the rest of the library to be stabilized. The exact method of |
| 83 | +stabilizing its contents will be determined with a future RFC or pull requests. |
| 84 | + |
| 85 | +## Stabilizing lang items |
| 86 | + |
| 87 | +As mentioned above, there are three separate lang items which are required by |
| 88 | +the libcore library to link correctly. These items are: |
| 89 | + |
| 90 | +* `panic_fmt` |
| 91 | +* `stack_exhausted` |
| 92 | +* `eh_personality` |
| 93 | + |
| 94 | +This RFC does **not** attempt to stabilize these lang items for a number of |
| 95 | +reasons: |
| 96 | + |
| 97 | +* The exact set of these lang items is somewhat nebulous and may change over |
| 98 | + time. |
| 99 | +* The signatures of each of these lang items can either be platform-specific or |
| 100 | + it's just "too weird" to stabilize. |
| 101 | +* These items are pretty obscure and it's not very widely known what they do or |
| 102 | + how they should be implemented. |
| 103 | + |
| 104 | +Stabilization of these lang items (in any form) will be considered in a future |
| 105 | +RFC. |
| 106 | + |
| 107 | +# Drawbacks |
| 108 | + |
| 109 | +The current distribution provides precisely one library, the standard library, |
| 110 | +for general consumption of Rust programs. Adding a new one (libcore) is adding |
| 111 | +more surface area to the distribution (in addition to adding a new `#![no_core]` |
| 112 | +attribute). This surface area is greatly desired, however. |
| 113 | + |
| 114 | +When using `#![no_std]` the experience of Rust programs isn't always the best as |
| 115 | +there are some pitfalls that can be run into easily. For example, macros and |
| 116 | +plugins sometimes hardcode `::std` paths, but most ones in the standard |
| 117 | +distribution have been updated to use `::core` in the case that `#![no_std]` is |
| 118 | +present. Another example is that common utilities like vectors, pointers, and |
| 119 | +owned strings are not available without liballoc, which will remain an unstable |
| 120 | +library. This means that users of `#![no_std]` will have to reimplement all of |
| 121 | +this functionality themselves. |
| 122 | + |
| 123 | +This RFC does not yet pave a way forward for using `#![no_std]` and producing an |
| 124 | +executable because the `#[start]` item is required, but remains feature gated. |
| 125 | +This RFC just enables creation of Rust static or dynamic libraries which don't |
| 126 | +depend on the standard library in addition to Rust libraries (rlibs) which do |
| 127 | +not depend on the standard library. |
| 128 | + |
| 129 | +In stabilizing the `#![no_std]` attribute it's likely that a whole ecosystem of |
| 130 | +crates will arise which work with `#![no_std]`, but in theory all of these |
| 131 | +crates should also interoperate with the rest of the ecosystem using `std`. |
| 132 | +Unfortunately, however, there are known cases where this is not possible. For |
| 133 | +example if a macro is exported from a `#![no_std]` crate which references items |
| 134 | +from `core` it won't work by default with a `std` library. |
| 135 | + |
| 136 | +# Alternatives |
| 137 | + |
| 138 | +Most of the strategies taken in this RFC have some minor variations on what can |
| 139 | +happen: |
| 140 | + |
| 141 | +* The `#![no_std]` attribute could be stabilized as-is without adding a |
| 142 | + `#![no_core]` attribute, requiring users to write `extern crate core` and |
| 143 | + import the core prelude manually. The burden of adding `#![no_core]` to the |
| 144 | + compiler, however, is seen as not-too-bad compared to the increase in |
| 145 | + ergonomics of using `#![no_std]`. |
| 146 | +* Another stable crate could be provided by the distribution which provides |
| 147 | + definitions of these lang items which are all wired to abort. This has the |
| 148 | + downside of selecting a name for this crate, however, and also inflating the |
| 149 | + crates in our distribution again. |
| 150 | + |
| 151 | +# Unresolved Questions |
| 152 | + |
| 153 | +* How important/common are `#![no_std]` executables? Should this RFC attempt to |
| 154 | + stabilize that as well? |
| 155 | +* When a staticlib is emitted should the compiler *guarantee* that a |
| 156 | + `#![no_std]` one will link by default? This precludes us from ever adding |
| 157 | + future require language items for features like unwinding or stack exhaustion |
| 158 | + by default. For example if a new security feature is added to LLVM and we'd |
| 159 | + like to enable it by default, it may require that a symbol or two is defined |
| 160 | + somewhere in the compilation. |
0 commit comments