Stabilize Unsafe Fields
| Metadata | |
|---|---|
| Point of contact | Jack Wrenn |
| lang champion | Niko Matsakis |
| Status | Proposed |
| Tracking issue | rust-lang/rust-project-goals#273 |
| Zulip channel | https://rust-lang.zulipchat.com/#narrow/channel/213817-t-lang/topic/unsafe.20fields.20RFC |
| Teams | book, clippy, lang, libs, rustdoc, rustfmt, spec, style |
| Task owners | (none) |
Summary
Complete and stabilize field safety tooling (RFC3458).
Motivation
The absence of a mechanism for denoting the presence of library safety invariants increases both the risk of working with unsafe code and the difficulty of evaluating its soundness.
The status quo
Presently, Rust lacks mechanisms for denoting when fields carry library safety invariants, and for enforcing extra care around their use. Consequently, to evaluate the soundness of unsafe code (i.e., code which relies on safety invariants being upheld), it is not enough to check the contents of unsafe blocks — one must check all places (including safe contexts) in which safety invariants might be violated. (See The Scope of Unsafe)
For example, consider this idealized Vec:
#![allow(unused)]
fn main() {
pub struct Vec<T> {
data: Box<[MaybeUninit<T>]>,
len: usize,
}
}
Although len is bound by a safety invariant, it is trivial to violate its invariant in entirely safe code:
#![allow(unused)]
fn main() {
impl Vec<T> {
pub fn evil(&mut self) {
self.len += 2;
}
}
}
Rust cannot enforce that modifications of len require unsafe, because the language does not provide the programmer a way of communicating to the compiler that len carries safety invariants.
After more than a decade of discussion, an RFC for field safety tooling has been accepted and a preliminary implementation is available with #![feature(unsafe_fields)]. Instability and gaps in supporting tooling (i.e., clippy, rustdoc, and rustfmt) prevent this feature from being utilized widely.
The “shiny future” we are working towards
Rust programmers will use the unsafe keyword to denote fields that carry library safety invariants; e.g.:
#![allow(unused)]
fn main() {
struct Vec<T> {
// SAFETY: The elements `data[i]` for
// `i < len` are in a valid state.
unsafe data: Box<[MaybeUninit<T>]>,
unsafe len: usize,
}
}
Rust will require that usages of unsafe fields which could violate their safety invariants must only occur within unsafe contexts.
Work items over the next year
Over the next year, we will complete tooling support, documentation, and stabilization of Unsafe Fields according to the steps documented in Tracking issue for RFC 3458: Unsafe fields:
| Task | Owner(s) | Notes |
|---|---|---|
| Implement clippy support. | Jack Wrenn | |
| Implement rustdoc support. | Jack Wrenn | |
| Implement rustfmt support. | Jack Wrenn | |
| Add Book documentation. | Jack Wrenn | |
| Add Standard Library documentation. | Jack Wrenn | |
| Add Reference documentation. | Jack Wrenn | |
| Add Style Guide documentation. | Jack Wrenn | |
| Write Stabilization Report. | Jack Wrenn | |
| Stabilize | Jack Wrenn |
Team asks
| Team | Support level | Notes |
|---|---|---|
| book | Small | Will need approval for book changes. |
| clippy | Small | Will need approval for clippy support. |
| lang | Small | Will need approval for stabilization. |
| libs | Small | Will need approval for documentation changes. |
| spec | Small | Will need approval for reference changes. |
| style | Small | Will need approval for style guide changes. |
| rustdoc | Small | Will need approval for rustdoc support. |
| rustfmt | Small | Will need approval for rustfmt support. |