Skip to content

docs(gc): add precise-tracing API redesign plan#55

Open
Flamki wants to merge 5 commits intoboa-dev:mainfrom
Flamki:docs/precise-tracing-api-invariants
Open

docs(gc): add precise-tracing API redesign plan#55
Flamki wants to merge 5 commits intoboa-dev:mainfrom
Flamki:docs/precise-tracing-api-invariants

Conversation

@Flamki
Copy link
Copy Markdown
Contributor

@Flamki Flamki commented Mar 19, 2026

This PR adds a focused planning note for the GC redesign direction after removing the gc_allocator experiment path.

What this adds

  • notes/precise_tracing_api_plan.md
    • precise-tracing API direction without root/reference-count dependence
    • explicit invariants (rooting, weak/ephemeron, finalization/resurrection, teardown)
    • phased execution plan (contract + prototype + gated integration)
    • validation and risk controls aligned with current tracker issues
  • README link for discoverability

Why

Recent maintainer guidance points toward API-focused GC redesign and staged integration, while #54 removes the Collector: Allocator experiment. This note captures a practical plan that matches that direction and keeps scope clear.

Scope

  • docs only
  • no runtime/API behavior changes

Validation

  • cargo fmt --all -- --check
  • cargo test --workspace

@jedel1043
Copy link
Copy Markdown
Member

I don't think we want a plan to "redesign an API", we want an API redesign proposal. That's much better than just proposing to do it "somehow", since that doesn't prove its feasibility. Having at least a proposed API would open discussion on how to improve it or change it to better fit Boa's needs.

@Flamki
Copy link
Copy Markdown
Contributor Author

Flamki commented Mar 27, 2026

Thanks for the clarification — agreed.

I updated this PR to be an API redesign proposal (not just a plan). The latest commit adds a concrete draft API surface and feasibility path:

  • proposed core types/surface (Gc<T>, Root<T>, WeakGc<T>, GcContext, Scope<'gc>)
  • draft method/signature shape for allocation, rooting, casts, weak upgrades, and collection utilities
  • explicit semantic invariants (tracing authority, root-slot model, weak/ephemeron behavior, finalization/teardown safety)
  • compatibility/adoption mapping to the current Boa-facing boa_gc surface
  • open review questions to drive design discussion

If useful, I can split the proposed API into focused follow-up issues (by parity area) after this gets initial review direction.

Comment on lines +43 to +46
pub struct Root<T: Trace + ?Sized> {
ptr: Gc<T>,
slot: RootSlotId,
}
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.

If roots are not tied to the gc context by lifetime, couldn't you cause UB by holding onto a reference to the inner data of a root, then dropping the context and trying to access the hold reference?

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.

Great point, thanks — agreed this needed to be explicit.

I updated the proposal to brand roots with the GC context lifetime:

  • Root<'gc, T> now carries a context lifetime marker
  • Scope::root now returns Root<'gc, T> (tied to the same scope/context lifetime)
  • added a safety note clarifying that safe code cannot keep rooted references after the context/scope is dropped

So the intended model is that roots cannot outlive their owning GC context in safe code.


impl<'gc> Scope<'gc> {
pub fn alloc<T: Trace + 'static>(&mut self, value: T) -> Gc<T>;
pub fn root<T: Trace + 'static>(&'gc mut self, value: &Gc<T>) -> Root<'gc, T>;
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.

Wait, this is extremely limiting since it essentially means you cannot have more than one root at a time

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.

Thanks, that’s a fair concern.

I pushed an update that keeps the lifetime safety guarantee without serializing root creation:

  • changed Scope::root from an exclusive-borrow shape to a shared-borrow shape
  • roots are now scope-branded (Root<'scope, 'gc, T>) so they remain tied to the owning context lifetime
  • documented the expected implementation detail that root-slot registration uses internal mutability, which allows multiple roots to exist at once

So the model now aims for both:

  1. no “single-root-at-a-time” restriction, and
  2. no safe-code path for roots to outlive their owning GC context.

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 still doesn't allow multiple roots, because Scope mutably borrows from GcContext, so the underlying Root also mutably borrows from GcContext.

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.

Good catch. Fixed now:

  • Scope uses shared &GcContext (not mutable borrow)
  • root stays lifetime-branded (Root<'scope, 'gc, T>)
  • model now allows multiple roots + keeps context-lifetime safety

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.

2 participants