Skip to content

feat(rust): Remove unnecessary Mutex overhead for resource references#823

Open
LucaButBoring wants to merge 1 commit intosmithy-lang:main-1.xfrom
LucaButBoring:lucalc/no-lock
Open

feat(rust): Remove unnecessary Mutex overhead for resource references#823
LucaButBoring wants to merge 1 commit intosmithy-lang:main-1.xfrom
LucaButBoring:lucalc/no-lock

Conversation

@LucaButBoring
Copy link

Removed unnecessary locking overhead for resource references in generated Rust code.

Problem:
Generated resource types used Rc<RefCell<dyn T>>, which becomes Arc<Mutex<dyn T>> with the sync feature. Since resource traits already require Send + Sync, the implementations must be internally thread-safe, making the outer Mutex redundant, and therefore making every invocation pay the locking overhead for no benefit.

Solution:
We replace Rc<RefCell<dyn T>> with Rc<T> directly. To maintain backwards-compatibility with existing code that calls .lock().unwrap() on resource references, we introduce new ResourceInner<T> and ResourceGuard<T> types that provide a no-op .lock() method. This can be simplified if we decide this is a rare/invalid use case.

There is still one minor breaking change, however: lock() now returns Result<ResourceGuard, Infallible> instead of Result<MutexGuard, PoisonError>. Code that calls PoisonError-specific methods (e.g., .into_inner()) will fail to compile - code that simply uses .unwrap(), .expect() (typical use case), or pattern matches without using the error value will continue to work. If we decide this is a problem, we can introduce a new error type that matches the same API, instead.


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@LucaButBoring LucaButBoring requested a review from a team as a code owner January 8, 2026 23:31
Replace Rc<RefCell<dyn T>> with Rc<T> for resource references in generated
Rust code. Since resource traits already require Send + Sync, the inner
Mutex (which RefCell becomes with the sync feature) was redundant.

To maintain backwards compatibility with existing code that uses
.lock().unwrap() on resource references, introduce ResourceInner<T> and
ResourceGuard<T> types that provide a no-op .lock() method. This allows
existing code to continue working while eliminating the locking overhead.

The lock() method now returns Result<ResourceGuard, Infallible> instead of
Result<MutexGuard, PoisonError>. Code that explicitly handles PoisonError
will need to be updated, though most code uses .unwrap() or .expect() and
will continue to work unchanged.

Changes:
- types/resource.rs: Add ResourceInner<T> wrapper around Rc<T> with no-op
  lock() method, and ResourceGuard<T> for the returned guard type
- conversions/resource.rs: Use ResourceInner::new() instead of
  Rc::new(RefCell::new())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant