Skip to content

Commit cd50556

Browse files
authored
Rollup merge of rust-lang#113715 - kadiwa4:lang_items_doc, r=JohnTitor
Unstable Book: update `lang_items` page and split it [`lang_items` rendered](https://github.com/kadiwa4/rust/blob/lang_items_doc/src/doc/unstable-book/src/language-features/lang-items.md), [`start` rendered](https://github.com/kadiwa4/rust/blob/lang_items_doc/src/doc/unstable-book/src/language-features/start.md) Closes rust-lang#110274 Rustonomicon PR: rust-lang/nomicon#413, Rust Book PR: rust-lang/book#3705 A lot of information doesn't belong on the `lang_items` page. I added a separate page for the `start` feature and moved some text into the Rustonomicon because the `lang_items` page should not be a tutorial on how to build a `#![no_std]` executable. The list of existing lang items is too long/unstable, so I removed it. The doctests still don't work. :(
2 parents 0768872 + 0d99f1d commit cd50556

File tree

4 files changed

+121
-255
lines changed

4 files changed

+121
-255
lines changed

compiler/rustc_error_codes/src/error_codes/E0132.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ It is not possible to declare type parameters on a function that has the `start`
1313
attribute. Such a function must have the following type signature (for more
1414
information, view [the unstable book][1]):
1515

16-
[1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib
16+
[1]: https://doc.rust-lang.org/unstable-book/language-features/start.html
1717

1818
```
1919
# let _:

compiler/rustc_error_codes/src/error_codes/E0152.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ attributes:
2020
#![no_std]
2121
```
2222

23-
See also the [unstable book][1].
23+
See also [this section of the Rustonomicon][beneath std].
2424

25-
[1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib
25+
[beneath std]: https://doc.rust-lang.org/nomicon/beneath-std.html

src/doc/unstable-book/src/language-features/lang-items.md

+59-252
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,60 @@ functionality that isn't hard-coded into the language, but is
99
implemented in libraries, with a special marker to tell the compiler
1010
it exists. The marker is the attribute `#[lang = "..."]` and there are
1111
various different values of `...`, i.e. various different 'lang
12-
items'.
12+
items'. Most of them can only be defined once.
1313

14-
For example, `Box` pointers require a lang item for allocation.
15-
A freestanding program that uses the `Box`
16-
sugar for dynamic allocations via `malloc` and `free`:
14+
Lang items are loaded lazily by the compiler; e.g. if one never uses `Box`
15+
then there is no need to define a function for `exchange_malloc`.
16+
`rustc` will emit an error when an item is needed but not found in the current
17+
crate or any that it depends on.
18+
19+
Some features provided by lang items:
20+
21+
- overloadable operators via traits: the traits corresponding to the
22+
`==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all
23+
marked with lang items; those specific four are `eq`, `partial_ord`,
24+
`deref`/`deref_mut`, and `add` respectively.
25+
- panicking: the `panic` and `panic_impl` lang items, among others.
26+
- stack unwinding: the lang item `eh_personality` is a function used by the
27+
failure mechanisms of the compiler. This is often mapped to GCC's personality
28+
function (see the [`std` implementation][personality] for more information),
29+
but programs which don't trigger a panic can be assured that this function is
30+
never called. Additionally, a `eh_catch_typeinfo` static is needed for certain
31+
targets which implement Rust panics on top of C++ exceptions.
32+
- the traits in `core::marker` used to indicate types of
33+
various kinds; e.g. lang items `sized`, `sync` and `copy`.
34+
- memory allocation, see below.
35+
36+
Most lang items are defined by `core`, but if you're trying to build
37+
an executable without the `std` crate, you might run into the need
38+
for lang item definitions.
39+
40+
[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/personality/gcc.rs
41+
42+
## Example: Implementing a `Box`
43+
44+
`Box` pointers require two lang items: one for the type itself and one for
45+
allocation. A freestanding program that uses the `Box` sugar for dynamic
46+
allocations via `malloc` and `free`:
1747

1848
```rust,ignore (libc-is-finicky)
19-
#![feature(lang_items, start, libc, core_intrinsics, rustc_private, rustc_attrs)]
49+
#![feature(lang_items, start, core_intrinsics, rustc_private, panic_unwind, rustc_attrs)]
2050
#![allow(internal_features)]
2151
#![no_std]
52+
53+
extern crate libc;
54+
extern crate unwind;
55+
56+
use core::ffi::c_void;
2257
use core::intrinsics;
2358
use core::panic::PanicInfo;
2459
use core::ptr::NonNull;
2560
26-
extern crate libc;
27-
61+
pub struct Global; // the global allocator
2862
struct Unique<T>(NonNull<T>);
2963
3064
#[lang = "owned_box"]
31-
pub struct Box<T>(Unique<T>);
65+
pub struct Box<T, A = Global>(Unique<T>, A);
3266
3367
impl<T> Box<T> {
3468
pub fn new(x: T) -> Self {
@@ -37,272 +71,45 @@ impl<T> Box<T> {
3771
}
3872
}
3973
74+
impl<T, A> Drop for Box<T, A> {
75+
fn drop(&mut self) {
76+
unsafe {
77+
libc::free(self.0.0.as_ptr() as *mut c_void);
78+
}
79+
}
80+
}
81+
4082
#[lang = "exchange_malloc"]
4183
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
42-
let p = libc::malloc(size as libc::size_t) as *mut u8;
84+
let p = libc::malloc(size) as *mut u8;
4385
4486
// Check if `malloc` failed:
45-
if p as usize == 0 {
87+
if p.is_null() {
4688
intrinsics::abort();
4789
}
4890
4991
p
5092
}
5193
52-
impl<T> Drop for Box<T> {
53-
fn drop(&mut self) {
54-
libc::free(self.0.0.0 as *mut libc::c_void)
55-
}
56-
}
57-
5894
#[start]
5995
fn main(_argc: isize, _argv: *const *const u8) -> isize {
6096
let _x = Box::new(1);
6197
6298
0
6399
}
64100
65-
#[lang = "eh_personality"] extern fn rust_eh_personality() {}
66-
#[lang = "panic_impl"] extern fn rust_begin_panic(_info: &PanicInfo) -> ! { intrinsics::abort() }
67-
#[no_mangle] pub extern fn rust_eh_register_frames () {}
68-
#[no_mangle] pub extern fn rust_eh_unregister_frames () {}
69-
```
70-
71-
Note the use of `abort`: the `exchange_malloc` lang item is assumed to
72-
return a valid pointer, and so needs to do the check internally.
73-
74-
Other features provided by lang items include:
75-
76-
- overloadable operators via traits: the traits corresponding to the
77-
`==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all
78-
marked with lang items; those specific four are `eq`, `ord`,
79-
`deref`, and `add` respectively.
80-
- stack unwinding and general failure; the `eh_personality`,
81-
`panic` and `panic_bounds_check` lang items.
82-
- the traits in `std::marker` used to indicate types of
83-
various kinds; lang items `send`, `sync` and `copy`.
84-
- the marker types and variance indicators found in
85-
`std::marker`; lang items `covariant_type`,
86-
`contravariant_lifetime`, etc.
87-
88-
Lang items are loaded lazily by the compiler; e.g. if one never uses
89-
`Box` then there is no need to define a function for `exchange_malloc`.
90-
`rustc` will emit an error when an item is needed
91-
but not found in the current crate or any that it depends on.
92-
93-
Most lang items are defined by `libcore`, but if you're trying to build
94-
an executable without the standard library, you'll run into the need
95-
for lang items. The rest of this page focuses on this use-case, even though
96-
lang items are a bit broader than that.
97-
98-
### Using libc
99-
100-
In order to build a `#[no_std]` executable we will need libc as a dependency.
101-
We can specify this using our `Cargo.toml` file:
102-
103-
```toml
104-
[dependencies]
105-
libc = { version = "0.2.14", default-features = false }
106-
```
107-
108-
Note that the default features have been disabled. This is a critical step -
109-
**the default features of libc include the standard library and so must be
110-
disabled.**
111-
112-
### Writing an executable without stdlib
113-
114-
Controlling the entry point is possible in two ways: the `#[start]` attribute,
115-
or overriding the default shim for the C `main` function with your own.
116-
117-
The function marked `#[start]` is passed the command line parameters
118-
in the same format as C:
119-
120-
```rust,ignore (libc-is-finicky)
121-
#![feature(lang_items, core_intrinsics, rustc_private)]
122-
#![feature(start)]
123-
#![allow(internal_features)]
124-
#![no_std]
125-
use core::intrinsics;
126-
use core::panic::PanicInfo;
127-
128-
// Pull in the system libc library for what crt0.o likely requires.
129-
extern crate libc;
130-
131-
// Entry point for this program.
132-
#[start]
133-
fn start(_argc: isize, _argv: *const *const u8) -> isize {
134-
0
135-
}
136-
137-
// These functions are used by the compiler, but not
138-
// for a bare-bones hello world. These are normally
139-
// provided by libstd.
140-
#[lang = "eh_personality"]
141-
#[no_mangle]
142-
pub extern fn rust_eh_personality() {
143-
}
144-
145-
#[lang = "panic_impl"]
146-
#[no_mangle]
147-
pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
148-
unsafe { intrinsics::abort() }
149-
}
150-
```
151-
152-
To override the compiler-inserted `main` shim, one has to disable it
153-
with `#![no_main]` and then create the appropriate symbol with the
154-
correct ABI and the correct name, which requires overriding the
155-
compiler's name mangling too:
156-
157-
```rust,ignore (libc-is-finicky)
158-
#![feature(lang_items, core_intrinsics, rustc_private)]
159-
#![feature(start)]
160-
#![allow(internal_features)]
161-
#![no_std]
162-
#![no_main]
163-
use core::intrinsics;
164-
use core::panic::PanicInfo;
165-
166-
// Pull in the system libc library for what crt0.o likely requires.
167-
extern crate libc;
168-
169-
// Entry point for this program.
170-
#[no_mangle] // ensure that this symbol is called `main` in the output
171-
pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 {
172-
0
173-
}
174-
175-
// These functions are used by the compiler, but not
176-
// for a bare-bones hello world. These are normally
177-
// provided by libstd.
178101
#[lang = "eh_personality"]
179-
#[no_mangle]
180-
pub extern fn rust_eh_personality() {
181-
}
102+
fn rust_eh_personality() {}
182103
183-
#[lang = "panic_impl"]
184-
#[no_mangle]
185-
pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
186-
unsafe { intrinsics::abort() }
187-
}
104+
#[panic_handler]
105+
fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() }
188106
```
189107

190-
In many cases, you may need to manually link to the `compiler_builtins` crate
191-
when building a `no_std` binary. You may observe this via linker error messages
192-
such as "```undefined reference to `__rust_probestack'```".
193-
194-
## More about the language items
195-
196-
The compiler currently makes a few assumptions about symbols which are
197-
available in the executable to call. Normally these functions are provided by
198-
the standard library, but without it you must define your own. These symbols
199-
are called "language items", and they each have an internal name, and then a
200-
signature that an implementation must conform to.
201-
202-
The first of these functions, `rust_eh_personality`, is used by the failure
203-
mechanisms of the compiler. This is often mapped to GCC's personality function
204-
(see the [libstd implementation][unwind] for more information), but crates
205-
which do not trigger a panic can be assured that this function is never
206-
called. The language item's name is `eh_personality`.
207-
208-
[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs
209-
210-
The second function, `rust_begin_panic`, is also used by the failure mechanisms of the
211-
compiler. When a panic happens, this controls the message that's displayed on
212-
the screen. While the language item's name is `panic_impl`, the symbol name is
213-
`rust_begin_panic`.
214-
215-
Finally, a `eh_catch_typeinfo` static is needed for certain targets which
216-
implement Rust panics on top of C++ exceptions.
108+
Note the use of `abort`: the `exchange_malloc` lang item is assumed to
109+
return a valid pointer, and so needs to do the check internally.
217110

218111
## List of all language items
219112

220-
This is a list of all language items in Rust along with where they are located in
221-
the source code.
113+
An up-to-date list of all language items can be found [here] in the compiler code.
222114

223-
- Primitives
224-
- `i8`: `libcore/num/mod.rs`
225-
- `i16`: `libcore/num/mod.rs`
226-
- `i32`: `libcore/num/mod.rs`
227-
- `i64`: `libcore/num/mod.rs`
228-
- `i128`: `libcore/num/mod.rs`
229-
- `isize`: `libcore/num/mod.rs`
230-
- `u8`: `libcore/num/mod.rs`
231-
- `u16`: `libcore/num/mod.rs`
232-
- `u32`: `libcore/num/mod.rs`
233-
- `u64`: `libcore/num/mod.rs`
234-
- `u128`: `libcore/num/mod.rs`
235-
- `usize`: `libcore/num/mod.rs`
236-
- `f32`: `libstd/f32.rs`
237-
- `f64`: `libstd/f64.rs`
238-
- `char`: `libcore/char.rs`
239-
- `slice`: `liballoc/slice.rs`
240-
- `str`: `liballoc/str.rs`
241-
- `const_ptr`: `libcore/ptr.rs`
242-
- `mut_ptr`: `libcore/ptr.rs`
243-
- `unsafe_cell`: `libcore/cell.rs`
244-
- Runtime
245-
- `start`: `libstd/rt.rs`
246-
- `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC)
247-
- `eh_personality`: `libpanic_unwind/gcc.rs` (GNU)
248-
- `eh_personality`: `libpanic_unwind/seh.rs` (SEH)
249-
- `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC)
250-
- `panic`: `libcore/panicking.rs`
251-
- `panic_bounds_check`: `libcore/panicking.rs`
252-
- `panic_impl`: `libcore/panicking.rs`
253-
- `panic_impl`: `libstd/panicking.rs`
254-
- Allocations
255-
- `owned_box`: `liballoc/boxed.rs`
256-
- `exchange_malloc`: `liballoc/heap.rs`
257-
- Operands
258-
- `not`: `libcore/ops/bit.rs`
259-
- `bitand`: `libcore/ops/bit.rs`
260-
- `bitor`: `libcore/ops/bit.rs`
261-
- `bitxor`: `libcore/ops/bit.rs`
262-
- `shl`: `libcore/ops/bit.rs`
263-
- `shr`: `libcore/ops/bit.rs`
264-
- `bitand_assign`: `libcore/ops/bit.rs`
265-
- `bitor_assign`: `libcore/ops/bit.rs`
266-
- `bitxor_assign`: `libcore/ops/bit.rs`
267-
- `shl_assign`: `libcore/ops/bit.rs`
268-
- `shr_assign`: `libcore/ops/bit.rs`
269-
- `deref`: `libcore/ops/deref.rs`
270-
- `deref_mut`: `libcore/ops/deref.rs`
271-
- `index`: `libcore/ops/index.rs`
272-
- `index_mut`: `libcore/ops/index.rs`
273-
- `add`: `libcore/ops/arith.rs`
274-
- `sub`: `libcore/ops/arith.rs`
275-
- `mul`: `libcore/ops/arith.rs`
276-
- `div`: `libcore/ops/arith.rs`
277-
- `rem`: `libcore/ops/arith.rs`
278-
- `neg`: `libcore/ops/arith.rs`
279-
- `add_assign`: `libcore/ops/arith.rs`
280-
- `sub_assign`: `libcore/ops/arith.rs`
281-
- `mul_assign`: `libcore/ops/arith.rs`
282-
- `div_assign`: `libcore/ops/arith.rs`
283-
- `rem_assign`: `libcore/ops/arith.rs`
284-
- `eq`: `libcore/cmp.rs`
285-
- `ord`: `libcore/cmp.rs`
286-
- Functions
287-
- `fn`: `libcore/ops/function.rs`
288-
- `fn_mut`: `libcore/ops/function.rs`
289-
- `fn_once`: `libcore/ops/function.rs`
290-
- `generator_state`: `libcore/ops/generator.rs`
291-
- `generator`: `libcore/ops/generator.rs`
292-
- Other
293-
- `coerce_unsized`: `libcore/ops/unsize.rs`
294-
- `drop`: `libcore/ops/drop.rs`
295-
- `drop_in_place`: `libcore/ptr.rs`
296-
- `clone`: `libcore/clone.rs`
297-
- `copy`: `libcore/marker.rs`
298-
- `send`: `libcore/marker.rs`
299-
- `sized`: `libcore/marker.rs`
300-
- `unsize`: `libcore/marker.rs`
301-
- `sync`: `libcore/marker.rs`
302-
- `phantom_data`: `libcore/marker.rs`
303-
- `discriminant_kind`: `libcore/marker.rs`
304-
- `freeze`: `libcore/marker.rs`
305-
- `debug_trait`: `libcore/fmt/mod.rs`
306-
- `non_zero`: `libcore/nonzero.rs`
307-
- `arc`: `liballoc/sync.rs`
308-
- `rc`: `liballoc/rc.rs`
115+
[here]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs

0 commit comments

Comments
 (0)