镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Rust JSG: bound jsg_traced!(<T> X<T>) by HoldsNoGcReferences - #8401

Open
littledivy wants to merge 1 commit into
mainfrom
littledivy/2026-11-12-rjsg-traced-bound
Open

littledivy wants to merge 1 commit into
mainfrom
littledivy/2026-11-12-rjsg-traced-bound

Conversation

@littledivy

Copy link
Copy Markdown
Member

The generic form of jsg_traced! gave X<T> a no-op trace and HoldsNoGcReferences for any T. IoOwned<T> uses it, and IoContext::add_object takes any Send value. So an IoOwned, or any jsg_traced! wrapper, that holds a TracedGlobal or jsg::Rc was never visited. The handle stayed strong, and a cycle through it was never collected. A resource that holds a Slot<TracedGlobal> pointing back at its own wrapper is never dropped, while the same cycle through a traced field is.

In this patch:

  • The generic form bounds every parameter by HoldsNoGcReferences, so X<T> claims no GC references only where T holds none. Weak<R> holds nothing to trace whatever R is, so it implements both traits by hand.
  • add_object requires T: HoldsNoGcReferences. The values the request owns today (the span wrapper and the memory cache's fallback permit) are marked with jsg_traced!.
  • New compile tests check both bounds. Without the fix they fail because the code compiles. The change is compile-time only.

The generic form of `jsg_traced!` gave `X<T>` a no-op `trace` and
`HoldsNoGcReferences` for any `T`. `IoOwned<T>` uses it, and
`IoContext::add_object` takes any `Send` value, so an `IoOwned` or
`jsg_traced!` wrapper holding a `TracedGlobal` or `jsg::Rc` was never
visited. The handle stayed strong, and a cycle through it was never
collected: a resource holding `Slot<TracedGlobal>` that points at its own
wrapper is never dropped, while the same cycle through a traced field is.

In this patch the generic form bounds every parameter by
`HoldsNoGcReferences`, so `X<T>` claims no GC references only where `T`
holds none, and `add_object` requires `T: HoldsNoGcReferences`.
`Weak<R>`, which holds no reference to trace whatever `R` is, implements
both traits by hand. The values the request owns today (the span wrapper
and the memory cache's fallback permit) are marked with `jsg_traced!`.
Compile tests cover both bounds. This is a compile-time change only.
@littledivy
littledivy requested review from a team as code owners November 12, 2026 16:38

@clanky-the-clanker clanky-the-clanker Bot 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.

✅ Approved — A compile-time-only fix that tightens the GC-reference bounds correctly. Send is still implied through Traced, and no issues were found.

The decision is advisory: this review is a comment and never approves, blocks or requests changes on the pull request.


✅ All checks passed

🔒 Security: ✅ LGTM

The change only tightens compile-time bounds and weakens no boundary.


📖 AGENTS.md: ✅ LGTM

The src/rust/AGENTS.md edit is accurate.


📋 Code Quality: ✅ LGTM

The macro bounds, the Weak<R> impls, the add_object callers and the new compile tests are all consistent. Send is still enforced, because HoldsNoGcReferences is a subtrait of Traced, which requires Send.


⚡ Performance: ✅ LGTM

The change is compile-time only and has no runtime cost.


📝 Documentation: ✅ LGTM

The doc comments and the src/rust/AGENTS.md update match the new bounds.


Reviewed commit: d3ac2b18

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