Skip to content

Add more safety requirements for Allocator impls#156544

Closed
theemathas wants to merge 1 commit into
rust-lang:mainfrom
theemathas:more-allocator-docs
Closed

Add more safety requirements for Allocator impls#156544
theemathas wants to merge 1 commit into
rust-lang:mainfrom
theemathas:more-allocator-docs

Conversation

@theemathas

Copy link
Copy Markdown
Contributor

An Allocator implementation is now allowed to invalidate its allocations when the allocator is mutated or when a lifetime in the allocator type expires.

Mutation of an Allocator should sensibly be allowed to invalidate its allocations. For example, the bumpalo crates has a Bump::reset method that takes &mut self and invalidates all past allocations. Accesses via & still must not invalidate past allocations since, for example, Box provides & access to the allocator.

The "lifetime expiry" clause closes a hole/ambiguity on when an allocator is considered to be "dropped" if it does not have a destructor. Additionally, this clause matches what is required for Box::into_pin and {Rc, Arc}::pin to be sound. (Those methods have an A: 'static bound to prevent allocating via a &MyAllocator and then running MyAllocator's destructor.)

r? libs-api

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels May 13, 2026

@danielhenrymantilla danielhenrymantilla left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about when an allocator is moved? Iow, is an allocator allowed to lend pointers to its own shallow memory?

View changes since this review

Comment thread library/core/src/alloc/mod.rs Outdated
Comment thread library/core/src/alloc/mod.rs Outdated
@theemathas

theemathas commented May 13, 2026

Copy link
Copy Markdown
Contributor Author

There's text immediately after my edits that address moving the allocator. An allocator must not invalidate its allocations upon moving.

An `Allocator` implementation is now allowed to invalidate its
allocations when the allocator is mutated or when a lifetime in the
allocator type expires.

Mutation of an `Allocator` should sensibly be allowed to invalidate its
allocations. For example, the `bumpalo` crates has a `Bump::reset`
method that takes `&mut self` and invalidates all past allocations.
Accesses via `&` still must not invalidate past allocations since,
for example, `Box` provides `&` access to the allocator.

The "lifetime expiry" clause closes a hole/ambiguity on when an
allocator is considered to be "dropped" if it does not have a
destructor. Additionally, this clause matches what is required for
`Box::into_pin` and `{Rc, Arc}::pin` to be sound. (Those methods have an
`A: 'static` bound to prevent allocating via a `&MyAllocator` and then
running `MyAllocator`'s destructor.)
@theemathas

Copy link
Copy Markdown
Contributor Author

Given that the stabilization has fallen through, could this PR be merged instead in the meantime? @Amanieu

Comment on lines +95 to +96
/// - the allocator is mutated through public API taking `&mut` access (notably,
/// running the allocator's destructor is such a mutation), or

@Amanieu Amanieu Jun 4, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this needs to be in the Allocator docs: the Allocator trait itself doesn't have any methods that take &mut self, and if you're calling allocator-specific methods then it's up to them to document the effect on allocated objections.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point of this is: Box and other collections aren't allowed to have a safe allocator_mut method that gives out a &mut A. In exchange, allocator implementations are allowed to have a safe &mut self method that invalidates allocations.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a separate paragraph in the safety section:

Safe methods taking &self on types that implement Allocator must not cause the lifetime of an allocation to end early.

And maybe another sentence explaining that this is because collections can expose immutable access to their allocator.

Comment on lines +97 to +99
/// - the allocator's type becomes invalid.
/// (For example, the type `&'a T` becomes invalid when `'a` expires.
/// More generally, a type becomes invalid when any of its lifetime parameters has expired.)

@Amanieu Amanieu Jun 4, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe "type becomes invalid" is a concept that we've previously used elsewhere. Instead this should just explicitly mirror the wording from the docs of the allocate method which lists the 2 conditions which can cause an allocation to become invalid.

View changes since the review

@theemathas

Copy link
Copy Markdown
Contributor Author

This now conflicts with #157428. What should I do?
cc @nia-e

@clarfonthey

Copy link
Copy Markdown
Contributor

I think that it'd be fair to just settle on wording for the safety requirements and then remove that part from nia's PR.

@theemathas

Copy link
Copy Markdown
Contributor Author

I decided to rewrite the safety requirements, and I've submitted it as a separate PR at #157801. Marking this PR as draft, and I will close this PR if people are in favor of that other PR's approach

@theemathas theemathas marked this pull request as draft June 12, 2026 10:29
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 12, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 7, 2026
…e, r=Amanieu

Rewrite safety requirements for `Allocator` impls

This PR supersedes rust-lang#156544.

cc rust-lang#157428, rust-lang#156920

cc @nia-e

r? @Amanieu (reviewer of rust-lang#156544)

I define the concept of "equivalent allocators", in order to be able to talk about cloning allocators, and to give commonsense guarantees about stdlib `Allocator` impls.

I define the concept of "invalidating a memory block" in order to be able to talk about users not being allowed to use a block of allocated memory after its allocator is "gone".

An `Allocator` implementation is now allowed to invalidate its allocations when the allocator is mutated or when a lifetime in the allocator type expires.

Mutation of an `Allocator` should sensibly be allowed to invalidate its allocations. For example, the `bumpalo` crates has a `Bump::reset` method that takes `&mut self` and invalidates all past allocations. Accesses via `&` still must not invalidate past allocations since, for example, `Box` provides `&` access to the allocator.

I still had the "allocator destructor" clause as a separate clause from the `&mut` clause, to avoid questions about whether drop glue of types that don't implement `Drop` but have fields that implement `Drop` counts as creating a `&mut` to the whole thing.

The "lifetime expiry" clause closes a hole/ambiguity on when an allocator is considered to be "dropped" if it does not have a destructor. Additionally, this clause matches what is required for `Box::into_pin` and `{Rc, Arc}::pin` to be sound. (Those methods have an `A: 'static` bound to prevent allocating via a `&MyAllocator` and then running `MyAllocator`'s destructor.)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 7, 2026
…e, r=Amanieu

Rewrite safety requirements for `Allocator` impls

This PR supersedes rust-lang#156544.

cc rust-lang#157428, rust-lang#156920

cc @nia-e

r? @Amanieu (reviewer of rust-lang#156544)

I define the concept of "equivalent allocators", in order to be able to talk about cloning allocators, and to give commonsense guarantees about stdlib `Allocator` impls.

I define the concept of "invalidating a memory block" in order to be able to talk about users not being allowed to use a block of allocated memory after its allocator is "gone".

An `Allocator` implementation is now allowed to invalidate its allocations when the allocator is mutated or when a lifetime in the allocator type expires.

Mutation of an `Allocator` should sensibly be allowed to invalidate its allocations. For example, the `bumpalo` crates has a `Bump::reset` method that takes `&mut self` and invalidates all past allocations. Accesses via `&` still must not invalidate past allocations since, for example, `Box` provides `&` access to the allocator.

I still had the "allocator destructor" clause as a separate clause from the `&mut` clause, to avoid questions about whether drop glue of types that don't implement `Drop` but have fields that implement `Drop` counts as creating a `&mut` to the whole thing.

The "lifetime expiry" clause closes a hole/ambiguity on when an allocator is considered to be "dropped" if it does not have a destructor. Additionally, this clause matches what is required for `Box::into_pin` and `{Rc, Arc}::pin` to be sound. (Those methods have an `A: 'static` bound to prevent allocating via a `&MyAllocator` and then running `MyAllocator`'s destructor.)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 7, 2026
…e, r=Amanieu

Rewrite safety requirements for `Allocator` impls

This PR supersedes rust-lang#156544.

cc rust-lang#157428, rust-lang#156920

cc @nia-e

r? @Amanieu (reviewer of rust-lang#156544)

I define the concept of "equivalent allocators", in order to be able to talk about cloning allocators, and to give commonsense guarantees about stdlib `Allocator` impls.

I define the concept of "invalidating a memory block" in order to be able to talk about users not being allowed to use a block of allocated memory after its allocator is "gone".

An `Allocator` implementation is now allowed to invalidate its allocations when the allocator is mutated or when a lifetime in the allocator type expires.

Mutation of an `Allocator` should sensibly be allowed to invalidate its allocations. For example, the `bumpalo` crates has a `Bump::reset` method that takes `&mut self` and invalidates all past allocations. Accesses via `&` still must not invalidate past allocations since, for example, `Box` provides `&` access to the allocator.

I still had the "allocator destructor" clause as a separate clause from the `&mut` clause, to avoid questions about whether drop glue of types that don't implement `Drop` but have fields that implement `Drop` counts as creating a `&mut` to the whole thing.

The "lifetime expiry" clause closes a hole/ambiguity on when an allocator is considered to be "dropped" if it does not have a destructor. Additionally, this clause matches what is required for `Box::into_pin` and `{Rc, Arc}::pin` to be sound. (Those methods have an `A: 'static` bound to prevent allocating via a `&MyAllocator` and then running `MyAllocator`'s destructor.)
@rust-bors

rust-bors Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

☔ The latest upstream changes (presumably #158924) made this pull request unmergeable. Please resolve the merge conflicts by rebasing.

rust-timer added a commit that referenced this pull request Jul 8, 2026
Rollup merge of #157801 - theemathas:allocator-safety-rewrite, r=Amanieu

Rewrite safety requirements for `Allocator` impls

This PR supersedes #156544.

cc #157428, #156920

cc @nia-e

r? @Amanieu (reviewer of #156544)

I define the concept of "equivalent allocators", in order to be able to talk about cloning allocators, and to give commonsense guarantees about stdlib `Allocator` impls.

I define the concept of "invalidating a memory block" in order to be able to talk about users not being allowed to use a block of allocated memory after its allocator is "gone".

An `Allocator` implementation is now allowed to invalidate its allocations when the allocator is mutated or when a lifetime in the allocator type expires.

Mutation of an `Allocator` should sensibly be allowed to invalidate its allocations. For example, the `bumpalo` crates has a `Bump::reset` method that takes `&mut self` and invalidates all past allocations. Accesses via `&` still must not invalidate past allocations since, for example, `Box` provides `&` access to the allocator.

I still had the "allocator destructor" clause as a separate clause from the `&mut` clause, to avoid questions about whether drop glue of types that don't implement `Drop` but have fields that implement `Drop` counts as creating a `&mut` to the whole thing.

The "lifetime expiry" clause closes a hole/ambiguity on when an allocator is considered to be "dropped" if it does not have a destructor. Additionally, this clause matches what is required for `Box::into_pin` and `{Rc, Arc}::pin` to be sound. (Those methods have an `A: 'static` bound to prevent allocating via a `&MyAllocator` and then running `MyAllocator`'s destructor.)
@theemathas theemathas closed this Jul 8, 2026
@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jul 8, 2026
@theemathas theemathas deleted the more-allocator-docs branch July 8, 2026 00:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants