Skip to content

Commit eca6b28

Browse files
committed
RFC: Stabilize the alloc crate
1 parent 74d4623 commit eca6b28

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed

text/0000-liballoc.md

+196
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
- Feature Name: `liballoc`
2+
- Start Date: 2018-06-14
3+
- RFC PR:
4+
- Rust Issue: [rust-lang/rust#27783](https://github.com/rust-lang/rust/issues/27783)
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
Stabilize the `alloc` crate, with a module structure matching `std`.
10+
11+
This crate provides the subset of the standard library’s functionality that requires
12+
a global allocator (unlike the `core` crate) but not other operating system
13+
capabilities (unlike the `std` crate).
14+
15+
16+
# Motivation
17+
[motivation]: #motivation
18+
19+
## Background: `no_std`
20+
21+
In some environments the `std` crate is not available:
22+
micro-controllers that don’t have an operating system at all, kernel-space code, etc.
23+
The `#![no_std]` attribute allows a crate to not link to `std` implicitly,
24+
using `core` instead with only the subset of functionality that doesn’t have a runtime dependency.
25+
26+
## Use case 1: pushing `no_std` programs toward stable Rust
27+
28+
Programs (or `staticlib`s) that do not link `std` at all may still want to use `Vec<T>`
29+
or other functionality that requires a memory allocator.
30+
Blockers for doing so on stable Rust are diminishing:
31+
32+
* [The `#[global_allocator]` attribute][global_allocator] to specify an allocator
33+
and remove the need for an operating-system-provided one is stable since Rust 1.28.
34+
* [PR #51607] adds a fallback handling for OOM (allocation failure) conditions
35+
for when `std` is not available,
36+
removing the need for programs to define an unstable `oom` lang item themselves.
37+
38+
With this, the only allocation-related blocker is being able to import `Vec` in the first place.
39+
This RFC proposes stabilizing the current unstable way to do it: `extern crate alloc;`
40+
41+
[global_allocator]: https://doc.rust-lang.org/nightly/std/alloc/#the-global_allocator-attribute
42+
[PR #51607]: https://github.com/rust-lang/rust/pull/51607
43+
44+
## Use case 2: making stable libraries `no_std`
45+
46+
Even if a `no_std` program might still require other features that are still unstable,
47+
it is very common to use libraries from crates.io that have other users.
48+
Such a library might support stable Rust and use `Vec<T>`
49+
(or something else that requires a memory allocator)
50+
but not other operating-sytem functionality.
51+
52+
Today, making such a library possible to use without `std` without breaking stable users
53+
requires a compile-time flag:
54+
55+
```rust
56+
#![no_std]
57+
58+
#[cfg(feature = "no_std")] extern crate alloc;
59+
#[cfg(not(feature = "no_std"))] extern crate std as alloc;
60+
61+
use alloc::vec::Vec;
62+
```
63+
64+
With this RFC, this can be simplified to:
65+
66+
```rust
67+
#![no_std]
68+
69+
extern crate alloc;
70+
71+
use alloc::vec::Vec;
72+
```
73+
74+
# Guide-level explanation
75+
[guide-level-explanation]: #guide-level-explanation
76+
77+
When using `#![no_std]` in a crate, that crate does not implicitly depend on `std`
78+
but depends on `core` instead. For example:
79+
80+
```diff
81+
-use std::cell::RefCell;
82+
+use core::cell::RefCell;
83+
```
84+
85+
APIs that require a memory allocator are not available in `core`.
86+
In order to use them, `no_std` Rust code must explicitly depend on the `alloc` crate:
87+
88+
```rust
89+
extern crate alloc;
90+
91+
use core::cell::RefCell;
92+
use alloc::rc::Rc;
93+
```
94+
95+
Like `std` and `core`, this dependency does not need to be declared in `Cargo.toml`
96+
since `alloc` is part of the standard library and distributed with Rust.
97+
98+
The `alloc` crate does not have a prelude (items that are implicitly in scope).
99+
So its items that are in the `std` prelude must be imported explicitly
100+
to be used in `no_std` crates:
101+
102+
```rust
103+
use alloc::vec::Vec;
104+
```
105+
106+
107+
# Reference-level explanation
108+
[reference-level-explanation]: #reference-level-explanation
109+
110+
The `alloc` crate already exists (marked unstable),
111+
and every public API in it is already available in `std`.
112+
113+
[PR #51569] moves them around so that the module structure matches that of `std`,
114+
and the public APIs become a subset:
115+
any path that starts with `alloc::` should still be valid and point to the same item
116+
after replacing that prefix with `std::` (assuming both crates are available).
117+
118+
All that remains is stabilizing the `alloc` crate itself and tweaking its doc-comment.
119+
(In particular, removing the “not intended for general usage” sentence
120+
and mention `no_std` instead.)
121+
Since it is the only remaining unstable crate tracked by [tracking issue #27783],
122+
that issue can be closed after this RFC is implemented.
123+
124+
The structure of the standard library is therefore:
125+
126+
* `core`: has (almost) no runtime dependency, every Rust crate is expected to depend on this.
127+
* `alloc`: requires a global memory allocator,
128+
either specified through the `#[global_allocator]` attribute
129+
or provided by the `std` crate.
130+
* `std`: re-exports the contents of `core` and `alloc`
131+
so that non-`no_std` crate do not need care about what’s in what crate between these three.
132+
Depends on various operating system features such as files, threads, etc.
133+
* `proc-macro`: depends on parts of the compiler, typically only used at build-time
134+
(in procedural macro crates or Cargo build scripts).
135+
136+
[PR #51569]: https://github.com/rust-lang/rust/pull/51569
137+
[tracking issue #27783]: https://github.com/rust-lang/rust/issues/27783
138+
139+
140+
# Drawbacks
141+
[drawbacks]: #drawbacks
142+
143+
[Tracking issue #27783] is the tracking issue for the `alloc` crate and, historically, some other crates.
144+
Although I could not find much discussion of that, I believe it has been kept unstable so far
145+
because of uncertainty of uncertainty of what is the eventual desired crate structure
146+
for the standard library, given infinite time and resources.
147+
148+
In particular, could we have a single crate with some mechanism for selectively disabling
149+
or enabling some of the crate’s components, depending on which runtime dependencies
150+
are available in targetted environments?
151+
In that world, the `no_std` attribute and standard library crates other than `std`
152+
would be unecessary.
153+
154+
By stabilizing the `alloc` crate, we commit to having it − and its public API − exist “forever”.
155+
156+
157+
# Rationale and alternatives
158+
[alternatives]: #alternatives
159+
160+
The `core` and the `no_std` attribute are already stable,
161+
so in a sense it’s already too late for the “pure” version of the vision described above
162+
where `std` really is the only standard library crate that exists.
163+
164+
It may still be [desirable] to regroup the standard library into one crate,
165+
and it is proably still possible.
166+
The `core` crate could be replaced with a set of `pub use` reexport
167+
to maintained compatibility with existing users.
168+
Whatever the eventual status is for `core` is,
169+
we can do the same for `alloc`.
170+
[PR #51569] mentioned above also hopes to make this easier.
171+
172+
While we want to leave the possibility open for it,
173+
at the time of this writing there are no concrete plans
174+
for implementing such a standard library crates unification any time soon.
175+
So the only alternative to this RFC seems to be
176+
leaving heap allocation for `no_std` in unstable limbo for the forseeable future.
177+
178+
[desirable]: https://aturon.github.io/2018/02/06/portability-vision/#the-vision
179+
180+
181+
# Prior art
182+
[prior-art]: #prior-art
183+
184+
I am not aware of a mechanism similar to `no_std` in another programming language.
185+
186+
[Newlib] is a C library for “embedded” systems that typically don’t have an operating system.
187+
It does provide a memory allocator through `malloc` and related functions, unconditionally.
188+
189+
[Newlib]: https://sourceware.org/newlib/
190+
191+
192+
# Unresolved questions
193+
[unresolved]: #unresolved-questions
194+
195+
Did I miss something in [PR #51569] that makes `alloc` not a subset of `std`?
196+
A double-check from someone else would be appreciated.

0 commit comments

Comments
 (0)