Byte-Naut opened PR #14384 from Byte-Naut:issue-7793 to bytecodealliance:main:
Closes #7793.
Motivation
Converting a
Resource::<T>::new_borrow(rep)(orResourceDynamic::new_borrow) into aResourceAnyeagerly inserted a borrow into the host resource table. That operation requires an active component call scope, so performing the conversion outside of a call reachedbail_bug!("no current scope"), which panics in debug builds and returns aWasmtimeBugerror in release builds. @rvolosatovs reported this in #7793 with a minimal reproducer, and @alexcrichton pointed out that borrow lowering has to be deferred until a call is actually in progress, the wayResource<T>already does it. The reproducer has been sitting commented out incan_use_own_for_borrowsince then.Changes
ResourceAnynow carries an internalResourceAnyIndexthat is either a host table index (unchanged behavior for every existingResourceAny) or the rawrepof a synthetic borrow.HostResource::try_into_resource_anyreturns the synthetic variant fornew_borrowresources instead of touching the host table. Owned and table-backed resources are handled exactly as before.try_into_resource/try_into_resource_dynamic,resource_drop, and theown/borrowlowering paths handle the new variant;liftis unchanged and still produces table-backed values.- Update the
ResourceAnydocs to state which values requireresource_drop, and add a release note.- Tests: enable the previously disabled part of
can_use_own_for_borrowand extend it with the typed round-trip, a type mismatch, the own-lowering error, and the forgotten-drop trap;resource_dynamicgains the same paths forResourceDynamic.Design
The synthetic variant has no host table slot, so conversion, the typed round-trip, and
resource_dropno longer need a call scope;resource_dropon such a value is a documented no-op. When the value is lowered into a guestborrowparameter,lower_to_indexpasses therepstraight toguest_resource_lower_borrow, which runs during the call and keeps guest-side borrow accounting intact: a guest that fails to drop the handle still traps with "borrow handles still remain at the end of the call". Lowering a synthetic borrow asownkeeps producing the existing "cannot lower aborrowresource into anown" error, and resource type checks run before either lowering path. Borrows lifted from a guest remain table-backed and keep their drop obligation, so nothing changes for embedders who never callnew_borrow.One behavior change worth calling out for review: previously, converting a
new_borrowresource while a call was already active would create a table-backed borrow that had to be dropped before that call returned. That obligation no longer exists, which matches howResource<T>borrows behave when passed directly. Happy to adjust if a different policy is preferred.Testing
cargo test --test all component_model::resourcesLocally: fmt, clippy, and the full
component_modeltest suite pass. The baseline reproduces theBUG: no current scopepanic onmain.Thanks to @rvolosatovs for the clear reproducer and root-cause analysis, and to @alexcrichton for pointing at the deferred-lowering approach. In line with the Bytecode Alliance AI tool policy: Claude was used to assist with analysis and drafting; I have reviewed and tested every change here and am accountable for it.
Byte-Naut requested dicej for a review on PR #14384.
Byte-Naut requested wasmtime-core-reviewers for a review on PR #14384.
Byte-Naut requested fitzgen for a review on PR #14384.
Byte-Naut requested wasmtime-default-reviewers for a review on PR #14384.
github-actions[bot] added the label wasmtime:api on PR #14384.
github-actions[bot] added the label wasmtime:docs on PR #14384.
fitzgen unassigned fitzgen from PR #14384 component: fix ResourceAny conversion of synthetic borrowed host resources.
fitzgen commented on PR #14384:
Not particularly familiar with this area of code; gonna let @dicej handle this review.
:thumbs_up: dicej submitted PR review:
Thanks, @Byte-Naut!
dicej added PR #14384 component: fix ResourceAny conversion of synthetic borrowed host resources to the merge queue.
:check: dicej merged PR #14384.
dicej removed PR #14384 component: fix ResourceAny conversion of synthetic borrowed host resources from the merge queue.
Last updated: Oct 11 2026 at 02:20 UTC