Skip to content

Provide Rust wrapper for memory resouces - #406

Merged
4og merged 2 commits into
eclipse-score:mainfrom
eclipse-impl:swp-271166
Aug 11, 2026
Merged

Provide Rust wrapper for memory resouces#406
4og merged 2 commits into
eclipse-score:mainfrom
eclipse-impl:swp-271166

Conversation

@eclipse-impl

Copy link
Copy Markdown
Contributor

This allows Rust applications that interface with C++ to obtain memory resources to pass back to C++, such that the C++ code will allocate from them, allowing for controlling the memory allocation between the languages.

@github-actions

Copy link
Copy Markdown
Contributor

The created documentation from the pull request is available at: docu-html

@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval July 28, 2026 15:20 — with GitHub Actions Inactive
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval July 28, 2026 15:20 — with GitHub Actions Inactive
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval July 29, 2026 09:17 — with GitHub Actions Inactive
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval July 29, 2026 09:17 — with GitHub Actions Inactive
@pawelrutkaq

Copy link
Copy Markdown
Contributor

@arkjedrz have a look please

@eclipse-impl
eclipse-impl marked this pull request as ready for review July 30, 2026 09:29
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval August 3, 2026 13:03 — with GitHub Actions Inactive
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval August 3, 2026 13:03 — with GitHub Actions Inactive
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval August 3, 2026 13:03 — with GitHub Actions Inactive
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval August 3, 2026 13:03 — with GitHub Actions Inactive
@4og
4og requested a review from Copilot August 3, 2026 15:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new score/language/rust/memres Rust crate and accompanying C++ FFI layer to let Rust code create/own score::cpp::pmr::memory_resource instances and pass them back into C++ so allocations can be controlled across the language boundary (including a “hermetic” no-heap-fallback mode).

Changes:

  • Add a C++ handle hierarchy (MemResHandle + concrete implementations) and extern "C" API for creating/destroying PMR resources and retrieving the underlying memory_resource*.
  • Add a safe Rust wrapper API (MemoryResource, ResourceKind, PoolOptions) plus unit tests and an example demonstrating hermetic monotonic behavior.
  • Integrate the crate into Bazel + Cargo workspace, and bump the Rust toolchains Bazel dep version.

Reviewed changes

Copilot reviewed 18 out of 20 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
score/language/rust/memres/test/memres_test.cpp Adds C++ gtest coverage for handle creation, monotonic hermetic abort, and non-hermetic fallback.
score/language/rust/memres/test/memres_rust_test.rs Adds Rust unit tests exercising the Rust API and end-to-end FFI path.
score/language/rust/memres/src/lib.rs Implements the Rust API wrapper, FFI bindings, and lifetime-bound pointer wrapper.
score/language/rust/memres/README.md Documents design, safety/lifetime invariants, hermetic behavior, and Bazel targets.
score/language/rust/memres/example/main.rs Example binary demonstrating hermetic monotonic behavior and abort-on-overflow.
score/language/rust/memres/example/example_helpers.h Declares C ABI helpers used by the example and Rust tests.
score/language/rust/memres/example/example_helpers.cpp Implements the C ABI helpers for allocating/filling a PMR-backed C++ vector.
score/language/rust/memres/example/BUILD Adds Bazel targets for the example and helper library.
score/language/rust/memres/cpp/memory_resource_handle.h Declares the handle class hierarchy owning PMR resources and upstream guard.
score/language/rust/memres/cpp/memory_resource_handle.cpp Implements handle constructors and resource accessors.
score/language/rust/memres/cpp/guarded_upstream.h Declares the upstream memory_resource enforcing hermetic/heap-fallback policy.
score/language/rust/memres/cpp/guarded_upstream.cpp Implements guarded upstream allocate/deallocate and logging/abort behavior.
score/language/rust/memres/cpp/ffi.h Declares the plain-C API consumed by Rust and C++ tests.
score/language/rust/memres/cpp/ffi.cpp Implements the C API and bridges to the handle classes.
score/language/rust/memres/Cargo.toml Adds the new Rust crate manifest.
score/language/rust/memres/BUILD Adds Bazel cc/rust targets for the library and unit tests.
MODULE.bazel.lock Updates lockfile due to Rust toolchain dep bump (and related module resolution changes).
MODULE.bazel Bumps score_toolchains_rust dev dependency version.
Cargo.toml Adds memres to workspace members/default-members and workspace dependency map.
Cargo.lock Records the new workspace crate and updates some transitive crate versions.
Suppressed comments (1)

score/language/rust/memres/cpp/guarded_upstream.cpp:35

  • The warning log message concatenates tokens without spaces (e.g. "requested10bytes"), reducing its usefulness for diagnostics.
    score::mw::log::LogWarn("memres") << "Memory resource exhausted: requested" << bytes << "bytes with alignment"
                                      << alignment << ". Falling back to system heap.";

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread score/language/rust/memres/src/lib.rs Outdated
Comment on lines +96 to +98
/// Marker for a single-threaded resource that must not cross thread
/// boundaries.
pub struct Local;

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.

In principle, this would be a false positive for MemoryResource<Local>, which is Local's purpose of usage on this PR, because MemoryResource carries a mutable pointer and is thus not Send + Sync. But it's true that someone could have another type with threading information, and reuse these definitions, say:

struct Borrower<'a, S> {
    _resource: core::marker::PhantomData<&'a S>,
}

In this case, Borrower<'_, Local> would be Send + Sync and therefore the original semantic would not be achieved, as pointed out by the AI. Therefore, I followed its suggestion and updated the code to explicitly state that Local shall never be Send + Sync.

Comment on lines +228 to +252
impl MemoryResource<Shared> {
/// Returns a handle backed by the process-global default memory resource
/// (`score::cpp::pmr::get_default_resource()`).
///
/// The default resource synchronises internally, so the returned handle is
/// `Send + Sync` and may be shared across threads.
///
/// # Panics
///
/// Panics if the C++ side fails to allocate the thin wrapper handle.
pub fn default_resource() -> Self {
// SAFETY: memres_new_default allocates a thin non-owning wrapper around
// the global default resource; ownership of the wrapper is transferred
// to this struct and released via memres_destroy on drop.
let handle = ffi::memres_new_default();
assert!(
!handle.is_null(),
"memres: C++ failed to allocate default resource handle"
);
Self {
handle,
_marker: PhantomData,
}
}
}

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.

This is not the case. The interface allows for Rust programs to interface with C++ code that use the memory resources. As the Rust interface does not export set_default_resource, there's no way for a Rust application to overload the default behavior.

Comment on lines +172 to +177
/// - [`Shared`]: the backing resource performs its own internal
/// synchronisation (currently only the process-global default resource,
/// whose `allocate`/`deallocate` forward to the data-race-free global
/// `operator new`/`operator delete`). `MemoryResource<Shared>` is therefore
/// `Send + Sync`.
/// - [`Local`] (the default): the backing resource is single-threaded

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.

This is not the case. The interface allows for Rust programs to interface with C++ code that use the memory resources. As the Rust interface does not export set_default_resource, there's no way for a Rust application to overload the default behavior.

Comment on lines +30 to +31
score::mw::log::LogFatal("memres") << "Memory resource exhausted in hermetic mode: requested" << bytes
<< "bytes with alignment" << alignment << ". Aborting.";

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.

This is not the case, the elements separator is added by the backend.

4og
4og previously approved these changes Aug 11, 2026
@4og

4og commented Aug 11, 2026

Copy link
Copy Markdown
Member

The "Rust Coverage (Demo)" workflow fails in this PR, and it looks like an issue in the coverage toolchain and not the code.

thread 'rustc' (17424) panicked at ferrocene/tools/symbol-report/src/main.rs:44:41:
called `Option::unwrap()` on a `None` value

We disabled the workflow in baselibs for now. There is ongoing work to improve the coverage tooling, and I hope once it's done, we can reenable the coverage for rust. eclipse-score/tooling#394

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

Labels

bazel Bazel and Starlark build files c++ C++ code rust Rust code

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants