Skip to content

Commit 7d9d122

Browse files
authored
Merge pull request #198 from hexcatnl/eii
Add project goal: Externally Implemtable Items (EII)
2 parents b61f222 + 52350b1 commit 7d9d122

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed

src/2025h1/eii.md

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Externally Implementable Items
2+
3+
| Metadata | |
4+
| -------- | -------------------------------------------------------------- |
5+
| Owner(s) | [Jonathan Dönszelmann](@jdonszelmann) and [Mara Bos](@m-ou-se) |
6+
| Teams | [lang], [compiler] |
7+
| Status | Proposed |
8+
9+
## Summary
10+
11+
We intend to implement [Externally Implementable Items](https://github.com/rust-lang/rust/issues/125418) in the compiler.
12+
The plan is to do so in a way that allows us to change the way `#[panic_handler]` and similar attributes are handled,
13+
making these library features instead of compiler built-ins.
14+
We intend to eventually support both statics and functions,
15+
but the priority is at functions right now.
16+
17+
## Motivation
18+
19+
(as per the rfcs[^1][^2][^3] on this):
20+
21+
We have several items in the standard library that are overridable/definable by the user crate.
22+
For example, the (no_std) `panic_handler`, the global allocator for `alloc`, and so on.
23+
24+
Each of those is a special lang item with its own special handling.
25+
Having a general mechanism simplifies the language and makes this functionality available for other crates,
26+
and potentially for more use cases in `core`/`alloc`/`std`.
27+
28+
In general, having externally implementable items be feature of the language instead of magic lang items and linker hacks gives more flexibility.
29+
It creates a standard interface to expose points where libraries can be customized.
30+
31+
Additionally, making externally implementable items a language feature makes it easier to document these points of customization.
32+
They can become part of the public api of a crate.
33+
34+
[^1]: https://github.com/rust-lang/rfcs/pull/3632
35+
[^2]: https://github.com/rust-lang/rfcs/pull/3635
36+
[^3]: https://github.com/rust-lang/rfcs/pull/3645
37+
38+
### The status quo
39+
40+
Today, "externally implementable items" exist in various forms that each have their own implementation.
41+
Examples are the `#[panic_handler]`, the global allocator, the global logger of the `log` crate, and so on.
42+
Some of these are magical lang items, whereas others need to be set at runtime or are done (unsafely) through a global (`#[no_mangle]`) linker symbol.
43+
44+
After [RFC 3632], which proposes a new syntax for externally implementable _functions_,
45+
several alternative ideas were proposed in rapid succession
46+
that focussing on [statics](https://github.com/rust-lang/rfcs/pull/3635), [traits](https://github.com/rust-lang/rfcs/pull/3645), and [impl blocks](https://github.com/rust-lang/rfcs/pull/3632) rather than function definitions.
47+
Each of these having rougly equivalent power, but using a different part of Rust to achieve it.
48+
49+
The lang team agreed that this is a problem worth solving, and accepted it as a _lang experiment_.[^4]
50+
51+
While working on implementing possible solutions,
52+
we concluded that it'd be better to make use of attributes rather than new syntax, at least for now.[^5]
53+
54+
Because this requires support for name resolution in attributes, this led to a big detour:
55+
refactoring how attributes are implemented and handled in rustc.[^6]
56+
The main part of that is now merged[^7], allowing us to finally continue on implementing the externally implementable items experiment itself.
57+
58+
[^4]: https://github.com/rust-lang/rfcs/pull/3632#issuecomment-2125488373
59+
[^5]: https://github.com/rust-lang/rust/issues/125418#issuecomment-2360542039
60+
[^6]: https://github.com/rust-lang/rust/issues/131229
61+
[^7]: https://github.com/rust-lang/rust/pull/131808
62+
63+
### The next 6 months
64+
65+
The goal for the next six months is to finish the implementation of externally implementable items (as an experimental feature).
66+
67+
It is not unthinkable that we run into more obstacles that requires some changes in the compiler,
68+
but we estimate that six months is enough to make the feature available for experimentation.
69+
70+
### The "shiny future" we are working towards
71+
72+
In the longer term, this feature should be able to replace the magic behind the panic handler, global allocator, oom handler, and so on.
73+
At that point, an attribute like `#[panic_handler]` would simply be a regular (externally implementable) item exported by `core`, for example.
74+
75+
After stabilization, other crates in the ecosystem, such as the `log` crate, should be able to make use of this as well.
76+
E.g., they could have a `#[log::global_logger]` item that can be used to provide the global logger.
77+
78+
In the longer term, this could enable more fine grained customization of parts of `core`, `alloc` and `std`, such as panic handling.
79+
For example, right now, all kind of panics, including overflows and out-of-bounds panics, can all only be handled
80+
through the `#[panic_handler]`, which will only get a panic message containing an (english) description of the problem.
81+
Instead, one could imagine having a `#[panic_oob_handler]` that gets the index and size as arguments,
82+
allowing one to customize the default behavior.
83+
84+
## Design axioms
85+
86+
The experimental feature we implement should:
87+
88+
- be able to replace how `#[panic_handler]` and global allocator features are implemented.
89+
- This means the feature should not have a higher (memory, performance, etc.) cost than how those features are currently implemented.
90+
- This also puts some requirements on the supported functionality, to support everything that those features currently support.
91+
(E.g., being able to provide a default implementation that can be overridden later.)
92+
- be ergonomic.
93+
- This means that mistakes should not result in confusing linker errors, but in reasonable diagnostics.
94+
- allow for semver-compatible upgrade paths.
95+
- E.g. if a crate wants to change the signature or kind of an externally implementable item,
96+
it should be possible to have some backwards-compatible path forward.
97+
- be as close to zero-cost as possible.
98+
- E.g. adding the option for more fine grained panic handlers to `core` should not result in a loss of performance.
99+
100+
## Ownership and team asks
101+
102+
**Owner:** [Jonathan Dönszelmann](@jdonszelmann) and [Mara Bos](@m-ou-se)
103+
104+
| Task | Owner(s) or team(s) | Notes |
105+
| ---------------------------------------------- | ----------------------- | ----- |
106+
| Discussion and moral support | [compiler], [lang] | |
107+
| Lang-team experiment | ![Team][] [lang] | Already approved |
108+
| Design experiment (syntax, etc.) | *Jonathan and Mara* | Done |
109+
| Refactor attributes in rustc | *Jonathan* | In progress, refactor merged |
110+
| Implement experiment | *Jonathan and Mara* | |
111+
| Standard reviews | ![Team][] [compiler] | |
112+
| Blog post inviting feedback | *Jonathan and Mara* | |
113+
| Update RFC with new findings | *Jonathan and Mara* | |
114+
115+
## Frequently asked questions
116+
117+
- None yet.

0 commit comments

Comments
 (0)