Skip to content

Rust: Provide a trait method to (optionally) control resource allocation#1625

Open
cpetig wants to merge 2 commits into
bytecodealliance:mainfrom
cpetig:resource_arena
Open

Rust: Provide a trait method to (optionally) control resource allocation#1625
cpetig wants to merge 2 commits into
bytecodealliance:mainfrom
cpetig:resource_arena

Conversation

@cpetig

@cpetig cpetig commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

This enables resource allocation from a user provided arena instead of the heap.

Arena implementation in test case generated by genAI.

@cpetig cpetig added gen-rust Related to bindings for Rust-compiled-to-WebAssembly resources Issues with component resources and using them labels Jun 6, 2026

@alexcrichton alexcrichton left a comment

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 like the idea, thanks! I've got some comments below, but let me know if you'd prefer to not handle anything in particular.

Comment on lines +245 to +262
r#"#[doc(hidden)]
/// Place the value on the heap or in an arena, return the raw pointer.
/// Override for custom resource allocators.
fn _resource_into_raw(val: Option<Self>) -> *mut Option<Self> where Self: Sized
{{
{box_path}::into_raw({box_path}::new(val))
}}

#[doc(hidden)]
/// Consumes the value from the handle, handle is invalid afterwards.
///
/// # Safety
///
/// See Box::from_raw
unsafe fn _resource_from_raw(handle: *mut Option<Self>) -> Option<Self> where Self: Sized
{{
*unsafe {{ {box_path}::from_raw(handle) }}
}}

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.

There's a few aspects of this I'd like to bikeshed if that's ok with you as well. One is that I'd rather not open-code the Option<Self> implementation if possible. Given how everything's moving to a trait-based definition, do you think it'd be possible to have, for example, a default associated type or something like that which represents the container here? Something like type RawContainer: SomeOtherTrait = Option<Self>; or something like that, where Option<T> by default implements SomeOtherTrait. That wouldn't be directly related to the allocation here, and would involve abstracting the preexisting .as_mut().unwrap() operations in a few places, but it'd be in the same trend as this.

Orthogonally I'd bikeshed these exact shapes/docs a bit. The _-prefixed methods are probably overkill at this point. It might make sense to rename them to maybe a _-suffix rather than a _ prefix (which typically means "yes I know this is unused ignore that" which isn't the case here). The implementations would stay the same, however. The documentation, though, I think will want to be expanded to explain a bit more about the allocation lifecycle and what's expected of the pointer (e.g. it lives for the entire duration of the resource). I think resource_into_raw will need to be unsafe as well because one of the contractual invariants of resource_from_raw will be that it only consumes values previously produced by resource_into_raw. Finally, the where Self: Sized I think is fine to move to the trait definition (make Sized a supertrait) and avoid the syntactic overhead here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I agree with hiding the Option<T> implementation detail by an associated type or similar (I think there exists an FooImp type or similar already for this). I am not sure about creating another trait here (feels overkill to me for now).

I also agree on the _ suffix and the better documentation and Sized in a different place.

But .. I consider the argumentation about into_raw better be unsafe not compelling. There is no invariant on into_raw, only from_raw has invariants (only called once and only on a result from into_raw). Similarly only one of these member functions is unsafe on Box as well.

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.

That sounds reasonable to me, yeah, and good points!

/// This is safe in single-threaded contexts. In multi-threaded contexts,
/// the caller must ensure exclusive access.
#[inline]
pub fn get_mut(&self) -> &mut Arena<T, SIZE> {

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.

FWIW this is fundamentally unsafe and more-or-less UB. This'll want to be protected by some sort of lock or similar.

For this test though I think it's ok to avoid being fancy and just manually call Box maybe with a slightly different wrapper just to showcase that it can be done (e.g. wrap it up in Box<Thing<T>> instead of Box<T> or something like that)

@cpetig cpetig Jun 8, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I agree. Turning & into &mut is instant UB - unless there is some sort of internal mutability involved (which probably needs an UnsafeCell to protect against compiler optimizations).

I didn't look that closely into this third re-implementation of the arena, my goal was to create a minimalist wasm component without any reference to malloc - which involves avoiding panic and libc, but can be achieved by wat-patching.

I guess I should look a bit more closely into how to make the arena throwaway example code opsem safe and not an evil example buried in a high-quality code base.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Such a thing (&self to &mut T) exists ... https://doc.rust-lang.org/core/cell/struct.UnsafeCell.html#method.as_mut_unchecked but I agree that the unsafety should become better capsuled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gen-rust Related to bindings for Rust-compiled-to-WebAssembly resources Issues with component resources and using them

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants