RFC 1184: stabilize-no_std

libs (no_std)

Summary

Tweak the #![no_std] attribute, add a new #![no_core] attribute, and pave the way for stabilizing the libcore library.

Motivation

Currently all stable Rust programs must link to the standard library (libstd), and it is impossible to opt out of this. The standard library is not appropriate for use cases such as kernels, embedded development, or some various niche cases in userspace. For these applications Rust itself is appropriate, but the compiler does not provide a stable interface compiling in this mode.

The standard distribution provides a library, libcore, which is "the essence of Rust" as it provides many language features such as iterators, slice methods, string methods, etc. The defining feature of libcore is that it has 0 dependencies, unlike the standard library which depends on many I/O APIs, for example. The purpose of this RFC is to provide a stable method to access libcore.

Applications which do not want to use libstd still want to use libcore 99% of the time, but unfortunately the current #![no_std] attribute does not do a great job in facilitating this. When moving into the realm of not using the standard library, the compiler should make the use case as ergonomic as possible, so this RFC proposes different behavior than today's #![no_std].

Finally, the standard library defines a number of language items which must be defined when libstd is not used. These language items are:

To be able to usefully leverage #![no_std] in stable Rust these lang items must be available in a stable fashion.

Detailed Design

This RFC proposes a nuber of changes:

no_std

The #![no_std] attribute currently provides two pieces of functionality:

This RFC proposes adding the following behavior to the #![no_std] attribute:

Most uses of #![no_std] already want behavior along these lines as they want to use libcore, just not the standard library.

no_core

A new attribute will be added to the compiler, #![no_core], which serves two purposes:

Users of #![no_std] today who do not use libcore would migrate to moving this attribute instead of #![no_std].

Stabilization of libcore

This RFC does not yet propose a stabilization path for the contents of libcore, but it proposes readying to stabilize the name core for libcore, paving the way for the rest of the library to be stabilized. The exact method of stabilizing its contents will be determined with a future RFC or pull requests.

Stabilizing lang items

As mentioned above, there are three separate lang items which are required by the libcore library to link correctly. These items are:

This RFC does not attempt to stabilize these lang items for a number of reasons:

Stabilization of these lang items (in any form) will be considered in a future RFC.

Drawbacks

The current distribution provides precisely one library, the standard library, for general consumption of Rust programs. Adding a new one (libcore) is adding more surface area to the distribution (in addition to adding a new #![no_core] attribute). This surface area is greatly desired, however.

When using #![no_std] the experience of Rust programs isn't always the best as there are some pitfalls that can be run into easily. For example, macros and plugins sometimes hardcode ::std paths, but most ones in the standard distribution have been updated to use ::core in the case that #![no_std] is present. Another example is that common utilities like vectors, pointers, and owned strings are not available without liballoc, which will remain an unstable library. This means that users of #![no_std] will have to reimplement all of this functionality themselves.

This RFC does not yet pave a way forward for using #![no_std] and producing an executable because the #[start] item is required, but remains feature gated. This RFC just enables creation of Rust static or dynamic libraries which don't depend on the standard library in addition to Rust libraries (rlibs) which do not depend on the standard library.

In stabilizing the #![no_std] attribute it's likely that a whole ecosystem of crates will arise which work with #![no_std], but in theory all of these crates should also interoperate with the rest of the ecosystem using std. Unfortunately, however, there are known cases where this is not possible. For example if a macro is exported from a #![no_std] crate which references items from core it won't work by default with a std library.

Alternatives

Most of the strategies taken in this RFC have some minor variations on what can happen:

Unresolved Questions