feat(data_structures): introduce NonNullConst and NonNullMut pointer types (#21425)

Most of our low-level data structures e.g. `Arena`, `Vec`, `Box`, and `Stack` types use `NonNull` pointers.

`NonNull` is fundamentally dangerous. A `NonNull` can be created from a `&T`, and so only has read permissions. Yet you can call `as_mut()` on such a pointer to gain a `&mut T`, and that's instant undefined behavior. The onus is on the author to manually track how pointers were created and so whether they have write permissions or not, to avoid this hazard.

In complex code like the arena allocator, pointers are created in various different places, stored in structs, and passed around, so it is not trivial to track their permissions, and neither the type system nor Clippy gives you any help.

In comparison, raw pointers `*const T` and `*mut T` *do* make such a distinction between read-only and write-enabled pointers, but they have other shortcomings - they lack the non-null guarantee of `NonNull` (which can improve perf in some cases), and `*mut T` is not covariant, so it is unsuitable for use in types like `Vec`.

This PR intoduces 2 new pointer types `NonNullConst` and `NonNullMut`. Both are just wrappers around `NonNull` and are equivalent to `NonNull` at runtime. What they add is type system-level guarantees of the read/write permissions that these pointers have. i.e. they bring together the const/mut distinction of raw `*const` / `*mut` pointers, and the advantages of `NonNull`.

This PR only introduces these new pointer types, but does not use them in the codebase yet. It is my intention to migrate `Arena` allocator over to these new pointer types, to make it harder to blunder into causing UB while reworking the implementation. Other types like `Vec`, `Box`, `Stack`, and lexer's `Source` could also be migrated over later on.
This commit is contained in:
overlookmotel committed 2026-04-14 13:42:18 +00:00
1 parent 091e88ef36
commit 24b03ded48
4 files changed
+1714

No files matched your search

+2
View File
@@ -32,6 +32,7 @@ all = [
"code_buffer",
"fieldless_enum",
"inline_string",
"non_null",
"rope",
"slice_iter",
"stack",
@@ -41,6 +42,7 @@ box_macros = []
code_buffer = ["assert_unchecked"]
fieldless_enum = []
inline_string = ["assert_unchecked"]
non_null = []
rope = ["dep:ropey"]
slice_iter = ["assert_unchecked"]
stack = []
+1
View File
@@ -15,6 +15,7 @@ This crate provides specialized data structures and utilities that are used thro
- **Rope data structure**: Efficient text manipulation for large documents
- **Box macros**: Macros for creating boxed arrays / slices (similar to `vec!` macro)
- **Fieldless enums macro**: Macro for creating enums with a `VARIANTS` constant listing all variants
- **Non-null pointers**: `NonNullConst<T>` and `NonNullMut<T>` - non-null pointer types with explicit const/mut permissions
## Architecture
+3
View File
@@ -15,6 +15,9 @@ pub mod fieldless_enum;
#[cfg(feature = "inline_string")]
pub mod inline_string;
#[cfg(feature = "non_null")]
pub mod non_null;
#[cfg(feature = "rope")]
pub mod rope;
File diff suppressed because it is too large. Load diff