Skip to content

feat(thread_aware_core): add the stable core crate for thread-aware state - #643

Open
martintmk wants to merge 58 commits into
mainfrom
user/martintomka/20260806-stabilize-thread-aware
Open

feat(thread_aware_core): add the stable core crate for thread-aware state#643
martintmk wants to merge 58 commits into
mainfrom
user/martintomka/20260806-stabilize-thread-aware

Conversation

@martintmk

@martintmk martintmk commented Aug 6, 2026

Copy link
Copy Markdown
Member

Summary

Adds thread_aware_core, the stable vocabulary that thread-aware libraries share. Nothing
else in the workspace changes.

  • ThreadAware notifies a value that it has moved, via
    relocate(source: Option<&Thread>, destination: &Thread). The call is advisory: a value
    must remain correct if it is never called, called twice, or called with a Thread it has
    never seen. That single property is what lets the method be infallible and lets a runtime
    call it opportunistically.
  • Thread records where a value runs — Owner (which runtime owns it), a
    std::thread::ThreadId, and NumaNode (the memory closest to that thread). Fields are
    private and read through accessors.
  • Owner identity is assigned, not supplied: every new owner is unique, so two runtimes
    alive at once cannot collide. It also reports min_threads, the smallest number of threads
    its runtime runs, so a value can pre-size per-thread state before it has seen any of them.
  • NumaNode is an opaque u32 newtype built with an inherent const fn new(u32).
  • Nothing reaches a consumer's dependency graph; the only manifest entry is a test-only
    dev-dependency. The std feature is on by default and adds implementations for HashMap,
    Path and PathBuf. With default-features = false the crate needs only alloc and
    pointer-width atomics; Thread then loses its thread id and cannot be constructed, leaving
    Owner and NumaNode readable so a no_std library can still implement the trait.
  • docs/DESIGN.md records why the crate is split out, and the rules that let Thread gain
    coordinates later without breaking callers or changing behaviour.
    docs/STABILIZATION.md records the stable boundary.

Why Owner assigns its own identity

Callers used to choose the number, and the documentation warned at length that a collision
was "worse than a slowdown" and that keeping owners distinct was the embedding application's
problem. Taking the identity from a process-wide counter removes the hazard outright rather
than documenting it. Equality and hashing use identity alone.

min_threads is a floor, not an estimate. 0 means the runtime promises none and spawns on
demand, which falls through HashMap::with_capacity as a no-op, so both cases share one
expression at the call site. It was named threads_hint first; in std, _hint already means
a bound — size_hint returns a lower bound plus an optional upper, and overshooting is a bug
— so "hint" would have contradicted the suffix while leaving 0 a magic value.

Why the ids take new rather than From<u16>

A From<integer> impl on a permanently stable type is a one-shot commitment. Every way of
evolving one is breaking, verified against rustc:

Later change Result
Replace From<u16> with From<u32> breaks every caller passing a typed u16 (E0277)
Add From<u32> beside From<u16> breaks unsuffixed literals: from(1) falls back to i32 (E0277)
Add From<i32> no error at all — silently re-resolves from(1) to the new impl

cargo semver-checks 0.48 reports "no semver update required" for all three, so none of them
would be caught in review. NumaNode is therefore u32-backed with an inherent new. The
accepted width already exceeds any node count real hardware reaches — Windows' own topology
APIs report NUMA nodes as USHORT — and a wider or fallible constructor can still be added
later under a different name without touching existing callers.

Provided implementations

Containers forward to what they hold; primitives and other types with nothing tied to a
thread get an empty implementation. Three cases are deliberately absent:

  • References (&str, &Path) — relocating through one would adapt something the value
    only borrows, and whoever owns it is relocated on its own account.
  • Cow — relocating a borrowed one has to clone it into owned storage first, which is
    too much work to hide behind an advisory call. It can return later if a caller wants it.
  • Arc and sets — whether a shared allocation should split per thread depends on what it
    holds, and mutating a set element could change its hash and corrupt the container.

Naming

thread_aware_core::Thread shares a name with std::thread::Thread but is a different kind
of thing: an immutable coordinate that owns no OS resource. Importing both unqualified is
E0252, and both expose an identical id(&self) -> ThreadId. This is called out in the crate
docs and in a # Relation to std::thread::Thread section on the type. Raised deliberately
here in case reviewers would prefer a different name.

Scope

thread_aware is unchanged and still ships its own Affinity-based API. Nothing depends
on thread_aware_core yet; adoption is left for a later change. The diff against main is
the new crate plus its workspace wiring (Cargo.toml, Cargo.lock, CHANGELOG.md,
README.md) and nothing more.

Validation

  • 25 unit tests and 14 doctests with --all-features; 25 unit tests and 12 doctests with
    --no-default-features. One doctest is ignored: it demonstrates
    #[derive(ThreadAware)], which lives in thread_aware, and compiling it here would
    require the dependency the example exists to argue against.
  • Clippy in both feature configurations, rustdoc with -D warnings --cfg docsrs, formatting,
    spelling, and the generated README all pass.
  • Static assertions pin the auto traits (Send, Sync, Unpin, UnwindSafe,
    RefUnwindSafe) on all three public types, and assert_obj_safe! pins dyn-compatibility of
    ThreadAware. Both guard silent regressions: a coordinate added later that is not Sync
    would strip that property with no signature change, and a defaulted-but-generic trait method
    would keep every impl compiling while breaking every Box<dyn ThreadAware>.
  • Documentation and API shape went through repeated independent model-backed reviews. Those
    found real defects rather than wording nits: a counter width that would wrap and reissue a
    live identity, a claim that ThreadId is the operating-system thread id (it explicitly is
    not), an equality claim that was false under no_std, and an Eq/Hash test that passed
    vacuously because it compared a value with its own copy.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 3a761577-6422-4fd1-a0f7-88807d7f6134
@martintmk martintmk added the agency-rocket Touched by a rocket skill label Aug 6, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 3a761577-6422-4fd1-a0f7-88807d7f6134
@martintmk martintmk changed the title docs(thread_aware): add stabilization notes feat(stabilization)!: stabilize thread_aware 1.0 Aug 6, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 3a761577-6422-4fd1-a0f7-88807d7f6134
@martintmk martintmk changed the title feat(stabilization)!: stabilize thread_aware 1.0 feat(stabilization)!: thread_aware 1.0 Aug 6, 2026
@codecov

codecov Bot commented Aug 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.0%. Comparing base (edae40d) to head (197bd04).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #643   +/-   ##
=======================================
  Coverage   100.0%   100.0%           
=======================================
  Files         560      562    +2     
  Lines       60859    60945   +86     
=======================================
+ Hits        60859    60945   +86     
Flag Coverage Δ
linux 100.0% <100.0%> (?)
linux-arm 100.0% <100.0%> (?)
windows 100.0% <100.0%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 392f99fd-c9b0-40c7-aad7-3e87a132b16e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 392f99fd-c9b0-40c7-aad7-3e87a132b16e
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

✅ Version increments look sufficient

cargo semver-checks compared the 1 crate(s) this PR publishes against their previous version-bump commit in git history. Every version increment is sufficient for the detected API changes.

Crate Baseline Baseline commit This PR Minimum required Status
thread_aware_core new crate 0.1.0 0.1.0 ✅ ok

This check is informational and does not block the merge.

View the check run

Comment thread crates/thread_aware_core/Cargo.toml
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 392f99fd-c9b0-40c7-aad7-3e87a132b16e
Make the stable core crate dependency- and feature-free, and remove external-type implementations and their benchmarks.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 392f99fd-c9b0-40c7-aad7-3e87a132b16e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 392f99fd-c9b0-40c7-aad7-3e87a132b16e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 392f99fd-c9b0-40c7-aad7-3e87a132b16e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 392f99fd-c9b0-40c7-aad7-3e87a132b16e
Comment thread crates/thread_aware_core/src/impls.rs
Keep the core crate dependency-free while providing Path, PathBuf, and HashMap implementations behind an opt-in std feature.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 392f99fd-c9b0-40c7-aad7-3e87a132b16e
Comment thread crates/seatbelt/Cargo.toml Outdated
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 392f99fd-c9b0-40c7-aad7-3e87a132b16e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 392f99fd-c9b0-40c7-aad7-3e87a132b16e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 392f99fd-c9b0-40c7-aad7-3e87a132b16e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 392f99fd-c9b0-40c7-aad7-3e87a132b16e
Comment thread crates/thread_aware/src/__private.rs Outdated
Comment thread crates/thread_aware/src/affinity.rs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8f9c8e6e-73c6-47c0-830e-2f674656eceb
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8f9c8e6e-73c6-47c0-830e-2f674656eceb
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8f9c8e6e-73c6-47c0-830e-2f674656eceb
Comment thread crates/anyspawn/src/spawner.rs Outdated
Comment thread crates/tick/Cargo.toml Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated no new comments.

Suppressed comments (2)

Previously missed (1) — in code that hasn't changed since the last review.

crates/thread_aware_core/src/lib.rs:18

  • The PR description talks about Place/Origin and u16 newtypes, but the actual API added here is Thread + Owner/NumaNode with u32 storage. Please align the PR description (or, if the intent really is Place/Origin, align the code/docs) so reviewers and future readers don’t have two conflicting vocabularies for the same change.
//! This crate contains the small API shared by thread-aware libraries:
//!
//! - [`ThreadAware`] notifies a value that it has moved.
//! - [`Thread`] records where it now runs: which runtime, which OS thread, and which memory is
//!   closest to it.

crates/thread_aware_core/src/thread_aware.rs:164

  • Unit-test modules in this repo are typically annotated with #[cfg_attr(coverage_nightly, coverage(off))] so the test-only lines don’t count against the coverage gate. This file adds a #[cfg(test)] mod tests without that attribute, which is inconsistent with the established pattern (e.g., crates/tick/src/error.rs:103-105).
#[cfg(test)]
mod tests {

Drop the `impl Encoder` block. The surrounding prose already carries the
boundary point, and the example is about deriving the trait.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e215e3bc-7b6e-4743-afb4-55779bebd24b
Copilot AI review requested due to automatic review settings August 26, 2026 14:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated no new comments.

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

crates/thread_aware_core/src/lib.rs:62

  • In this doc example, “build dependency” is easy to misread as Cargo [build-dependencies]. Since thread_aware would be a normal/proc-macro dependency used at compile time, consider wording that more precisely communicates “implementation-only dependency” / “not part of the public API”.
//! // A build dependency, not part of what this library promises.

crates/thread_aware_core/src/thread_aware.rs:164

  • The test module here is missing the #[cfg_attr(coverage_nightly, coverage(off))] attribute that other modules in this crate use (e.g. src/thread.rs and src/impls.rs). Without it, these tests can count against the coverage gate in coverage runs.
#[cfg(test)]
mod tests {

crates/thread_aware_core/src/thread.rs:33

  • The PR description says the runtime/node ids are u16 newtypes (and refers to Origin/Place), but the stable API implemented here uses Owner(u32) (and Thread). Please align the PR description (or the code/docs) so reviewers/users aren’t left with conflicting API details.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Owner(u32);

…features

References to the companion crate were bare code spans. This crate
depends on nothing, so intra-doc links cannot reach it; use explicit
docs.rs URLs instead. Three targets, each verified to resolve: the crate
root, the `#[derive(ThreadAware)]` macro page, and the per-core `Arc`.

Restructure the features section to match `tick`: a `# Features`
heading, a lead-in sentence, and `- **`name`** *(default)* - ...`
bullets. The `no_std` story now says which items survive with default
features off, rather than only that the build works.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e215e3bc-7b6e-4743-afb4-55779bebd24b
Copilot AI review requested due to automatic review settings August 26, 2026 15:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@martintmk martintmk changed the title feat(thread_aware_core): add stand-alone crate for thread-aware state feat(thread_aware_core): add the stable core crate for thread-aware state Aug 26, 2026
"The two roles" was lopsided: the implementor role carried four
paragraphs and an example while the runtime role got one sentence,
placed after the implementor's example. Split it into two peer sections
named for their audience, each self-contained with its own example:

    # Library authors: implementing the trait
    # Runtime authors: driving relocation

Merge the duplicated forwarding explanation, which said the same thing
either side of the derive example, and repoint the trait's cross
reference from the removed `#the-two-roles` anchor.

Cut the features section to its single bullet. `tick`'s lead-in and
trailing paragraph earn their place across five features; across one
they restated what the crate intro and `Thread`'s own "Without `std`"
section already say.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e215e3bc-7b6e-4743-afb4-55779bebd24b
Copilot AI review requested due to automatic review settings August 27, 2026 06:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

crates/thread_aware_core/src/thread_aware.rs:165

  • mod tests here is missing #[cfg_attr(coverage_nightly, coverage(off))]. Other test modules in this crate already apply it (e.g. src/thread.rs and src/impls.rs) to avoid test-only lines counting against the 100% coverage gate; this module should do the same for consistency.
#[cfg(test)]
mod tests {

Comment thread crates/thread_aware_core/docs/STABILIZATION.md

@martintmk martintmk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

[AI AGENT]: I reviewed this as a crate publication, so I treated the entire reachable surface as new: ThreadAware (supertrait, required method, dyn-compatibility, downstream implementability), Thread / Owner / NumaNode (visibility, constructors, derives, accessors, auto traits), the std feature boundary and what it removes, the ~90 ThreadAware impls in impls.rs read as a coherence lattice, the manifest and packaged contents, and DESIGN.md / STABILIZATION.md as the stabilization argument.

I relied on this PR's own CI for lint, format and the full suite (green at 604e252, with fuzz-testing still pending and mutation-testing skipped) rather than re-running it, and used narrow local probes only to prove specific claims: an E0119 probe for the reference impls, two failing Cow tests, an E0277 probe for BTreeMap<NumaNode, _> under --no-default-features, cargo package --list for the packaged set, and cargo build / cargo test -p thread_aware_core --lib in both feature configurations to check each proposed fix.

Two findings I would act on before this ships. The concrete &str and &Path impls permanently foreclose the general impl<T: Sync + ?Sized> ThreadAware for &T — verified as a hard E0119 conflict — and that is the one thing in this PR the additive escape hatches in DESIGN.md cannot recover. And Cow::relocate clones borrowed data into a fresh allocation on the first relocation, including when source == destination, which contradicts three of the trait's own documented requirements and is precisely the allocation a Cow<'static, str> field exists to avoid.

Three non-blocking notes, inline: Owner and NumaNode are not Ord, so a no_std consumer cannot key the BTreeMap the crate docs tell them to use; DESIGN.md's "every coordinate has a default variant" rule is not applied to the two coordinates shipping now, leaving no way to express "unknown node"; and my answer to the naming question you raised is on thread.rs.

The rest of the public-contract pass came out clean, and that is worth stating rather than omitting. The Send supertrait plus the assert_obj_safe! / assert_impl_all! pins are the right guards for the two silent-regression classes you identified; private fields with accessors do make Thread extensible without #[non_exhaustive]; the inherent new over From<integer> analysis holds and I could not find a fourth evolution path it misses; and nothing reaches a consumer's graph — the only manifest entry is a dev-dependency, and cargo package --list confirms the LFS-tracked logo.png and favicon.ico stay out of the packaged set (12 files, all src/, docs/**/*.md, examples/, README.md, Cargo.toml), referenced by absolute URL as the packaging guidelines require. I skipped the 0.1.0-versus-1.0 wording in STABILIZATION.md and the missing coverage(off) on thread_aware.rs's test module, since copilot-pull-request-reviewer already has open threads on both.

Comment thread crates/thread_aware_core/src/impls.rs Outdated
Comment thread crates/thread_aware_core/src/impls.rs Outdated
Comment thread crates/thread_aware_core/src/thread.rs
Comment thread crates/thread_aware_core/docs/DESIGN.md
Comment thread crates/thread_aware_core/src/thread.rs
…eads`

`Owner` no longer takes a caller-supplied number. Every new owner is
unique, which removes the collision hazard the docs previously warned
about at length and made the embedding application's problem.

It also reports `min_threads`: the smallest number of threads its runtime
runs, so a value can pre-size per-thread state before it has seen any of
them. `0` means the runtime promises none and spawns on demand, which
falls through `HashMap::with_capacity` as a no-op, so both cases share
one expression at the call site.

Named `min_threads` rather than `threads_hint` on review. In std, `_hint`
already means a bound -- `size_hint` returns a lower bound plus an
optional upper, and overshooting is a bug -- so "hint" would have
contradicted the suffix while leaving `0` a magic value. A floor is also
what pre-sizing wants: `Vec::from_iter` sizes from `size_hint().0`, and
`with_capacity` means "at least".

Equality and hashing use identity alone; the count takes no part.

Also drop three implementations. References (`&str`, `&Path`) would adapt
something the value only borrows, whose owner is relocated on its own
account. `Cow` needed to clone a borrowed value into owned storage before
relocating it, which is too much work to hide behind an advisory call; it
can return later if a caller wants it.

Review of the reshaped type found four defects, all fixed here:

* An `AtomicU32` counter wraps after 2^32 constructions, silently handing
  out a live identity twice -- exactly the collision the change claims to
  remove. Now `AtomicUsize`, which also moves the documented requirement
  from 32-bit to pointer-width atomics.
* Two sentences still told callers to keep owner ids distinct.
* `DESIGN.md` never mentioned the atomics requirement at all.
* The new tests passed for the wrong reason: the `Eq`/`Hash` consistency
  test compared a value with its own copy, so a `Hash` including the
  count would still have passed. It now builds two owners sharing an
  identity, and fails under exactly that mutation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e215e3bc-7b6e-4743-afb4-55779bebd24b
Copilot AI review requested due to automatic review settings August 27, 2026 10:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

crates/thread_aware_core/src/thread_aware.rs:165

  • This crate follows the pattern of excluding #[cfg(test)] mod tests from the coverage gate via #[cfg_attr(coverage_nightly, coverage(off))] (as in thread.rs and impls.rs), but this tests module is missing that attribute. Add it here for consistency and to avoid test-only lines counting toward coverage.
#[cfg(test)]
mod tests {

Comment thread crates/thread_aware_core/src/thread.rs
`cargo mutants` replaced `<impl Hash for Owner>::hash` with `()` and no
test noticed: the only hash assertion checked that two owners sharing an
identity hash *equally*, which a no-op hash satisfies trivially.

Assert the converse as well -- two distinct owners with the same thread
count must hash apart -- which fails under exactly that mutation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e215e3bc-7b6e-4743-afb4-55779bebd24b
Copilot AI review requested due to automatic review settings August 27, 2026 10:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

Previously missed (1) — in code that hasn't changed since the last review.

crates/thread_aware_core/src/thread.rs:89

  • Owner::new uses AtomicUsize::fetch_add, which wraps on overflow. That would violate the documented guarantee that every new Owner is unique by potentially reissuing an identity once the counter wraps (especially on 32-bit targets). Consider using fetch_update with checked_add to fail fast on exhaustion without mutating the counter into a wrapped state.
    pub fn new(min_threads: usize) -> Self {
        Self {
            id: NEXT_OWNER.fetch_add(1, Ordering::Relaxed),
            min_threads,
        }

crates/thread_aware_core/src/thread_aware.rs:165

  • This crate consistently marks #[cfg(test)] mod tests with #[cfg_attr(coverage_nightly, coverage(off))] to keep test-only lines from counting against the 100% coverage gate (e.g. crates/tick/src/error.rs). This test module is missing that attribute.
#[cfg(test)]
mod tests {

Comment thread crates/thread_aware_core/src/impls.rs
Resolved a conflict in the workspace Cargo.toml: main cascaded
thread_aware, thread_aware_macros and thread_aware_macros_impl to
0.11.0, while this branch adds thread_aware_core. Kept main's version
bumps and retained the new thread_aware_core = 0.1.0 entry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 698f459b-8a21-45d8-a46f-1b39e71df42a
Copilot AI review requested due to automatic review settings August 27, 2026 15:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated no new comments.

Suppressed comments (1)

crates/thread_aware_core/src/thread_aware.rs:165

  • Tests modules in this repo are consistently annotated with #[cfg_attr(coverage_nightly, coverage(off))] so unit-test-only lines don’t count against the coverage gate. This mod tests is missing that attribute (unlike thread.rs / impls.rs in the same crate).
#[cfg(test)]
mod tests {

Review flagged the single-element case of `impl_transfer_tuple!` as
broken. It is not: the arm emits a literal comma after the head, so the
1-tuple expands to `let (A,) = self` and `impl<A,> ThreadAware for (A,)`,
both of which are correct (a trailing comma is legal in a generic
parameter list).

The existing coverage could not show this, though. `test_tuples` uses
`(42,)`, and `i32::relocate` is a no-op, so the assertion holds whether
or not the element was ever visited. Add a test built on `Tracker`,
whose `relocate` flips an observable flag, covering the 1-tuple, the
2-tuple and the 12-element maximum.

Verified the test is load-bearing: reproducing the reported defect, by
dropping that literal comma, makes the 1-tuple bind the whole tuple and
call its own impl again, overflowing the stack.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 698f459b-8a21-45d8-a46f-1b39e71df42a
Copilot AI review requested due to automatic review settings August 27, 2026 15:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated no new comments.

Suppressed comments (1)

crates/thread_aware_core/src/thread_aware.rs:165

  • The unit-test module here is missing #[cfg_attr(coverage_nightly, coverage(off))]. Other test modules in this new crate already apply it (e.g., thread.rs and impls.rs), and omitting it can cause test-only lines to count against the coverage gate.
#[cfg(test)]
mod tests {

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

Labels

agency-rocket Touched by a rocket skill

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants