feat(api): add Send + Sync bounds to public traits

Required for T3 rayon-based parallelism. Affected traits:
- Time (+ Send + Sync + 'static)
- Drift<T> (+ Send + Sync)
- Observer<T> (+ Send + Sync)
- Factor (+ Send + Sync)
- Schedule (+ Send + Sync)

All built-in impls (i64, Untimed, ConstantDrift, NullObserver,
EpsilonOrMax, TeamSumFactor, RankDiffFactor, TruncFactor,
BuiltinFactor) naturally satisfy these bounds via auto-derive.

Minor breaking change: downstream custom impls that aren't already
thread-safe will need to add the bounds.

Part of T3 of docs/superpowers/specs/2026-04-23-trueskill-engine-redesign-design.md.
This commit is contained in:
2026-04-24 13:36:39 +02:00
parent 9fe40042da
commit 4f302ed28e
5 changed files with 6 additions and 7 deletions

View File

@@ -6,7 +6,7 @@ use crate::time::Time;
/// ///
/// Generic over `T: Time` so seasonal or calendar-aware drift is expressible /// Generic over `T: Time` so seasonal or calendar-aware drift is expressible
/// without going through `i64`. /// without going through `i64`.
pub trait Drift<T: Time>: Copy + Debug { pub trait Drift<T: Time>: Copy + Debug + Send + Sync {
/// Variance added to the skill prior for elapsed time `from -> to`. /// Variance added to the skill prior for elapsed time `from -> to`.
/// ///
/// Called with `from <= to`; returning zero means no drift accumulates. /// Called with `from <= to`; returning zero means no drift accumulates.

View File

@@ -56,7 +56,7 @@ impl VarStore {
/// Factors hold their own outgoing messages and propagate them by reading /// Factors hold their own outgoing messages and propagate them by reading
/// connected variable marginals from a `VarStore` and writing back updated /// connected variable marginals from a `VarStore` and writing back updated
/// marginals. /// marginals.
pub trait Factor { pub trait Factor: Send + Sync {
/// Update outgoing messages and write back to the var store. /// Update outgoing messages and write back to the var store.
/// ///
/// Returns the max delta `(|Δmu|, |Δsigma|)` across writes this /// Returns the max delta `(|Δmu|, |Δsigma|)` across writes this

View File

@@ -9,9 +9,8 @@ use crate::time::Time;
/// Receives progress callbacks during `History::converge`. /// Receives progress callbacks during `History::converge`.
/// ///
/// All methods have default no-op implementations; implement only what's /// All methods have default no-op implementations; implement only what's
/// interesting. Send/Sync is NOT required in T2 (added in T3 along with /// interesting.
/// Rayon support). pub trait Observer<T: Time>: Send + Sync {
pub trait Observer<T: Time> {
/// Called after each convergence iteration across the whole history. /// Called after each convergence iteration across the whole history.
fn on_iteration_end(&self, _iter: usize, _max_step: (f64, f64)) {} fn on_iteration_end(&self, _iter: usize, _max_step: (f64, f64)) {}

View File

@@ -16,7 +16,7 @@ pub struct ScheduleReport {
} }
/// Drives factor propagation to convergence. /// Drives factor propagation to convergence.
pub trait Schedule { pub trait Schedule: Send + Sync {
fn run(&self, factors: &mut [BuiltinFactor], vars: &mut VarStore) -> ScheduleReport; fn run(&self, factors: &mut [BuiltinFactor], vars: &mut VarStore) -> ScheduleReport;
} }

View File

@@ -8,7 +8,7 @@
/// ///
/// Must be `Ord + Copy` so slices can sort events, and `'static` so /// Must be `Ord + Copy` so slices can sort events, and `'static` so
/// `History` can store it by value without lifetimes. /// `History` can store it by value without lifetimes.
pub trait Time: Copy + Ord + 'static { pub trait Time: Copy + Ord + Send + Sync + 'static {
/// How much time elapsed between `self` and `later`. /// How much time elapsed between `self` and `later`.
/// ///
/// Used by `Drift<T>::variance_delta` to compute skill drift. Returning /// Used by `Drift<T>::variance_delta` to compute skill drift. Returning