From c5c7180810e3528f689732d4da874729151fc15f Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Sat, 3 Oct 2026 10:30:31 -0700 Subject: [PATCH] fix(net): keep track::Fetching unwind safe The cached-hit group consumer added to Fetching in #4691 carries an Arc, which is not RefUnwindSafe, so Fetching dropped UnwindSafe and RefUnwindSafe: a semver break that forced moq-net 0.4.0. Require unwind safety on the crate-private Expiry trait and assert it. Co-Authored-By: Claude Opus 5.5 --- rs/moq-net/src/model/group.rs | 5 ++++- rs/moq-net/src/model/track.rs | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/rs/moq-net/src/model/group.rs b/rs/moq-net/src/model/group.rs index e199da5f88..db1e74f5a7 100644 --- a/rs/moq-net/src/model/group.rs +++ b/rs/moq-net/src/model/group.rs @@ -1129,7 +1129,10 @@ pub struct Consumer { } /// Subscriber-specific policy for expiring a group after it was handed out. -pub(crate) trait Expiry: Send + Sync { +/// +/// Unwind safe so the [`Consumer`] holding it is, and so the published +/// [`track::Fetching`] that holds a consumer stays unwind safe too. +pub(crate) trait Expiry: Send + Sync + std::panic::UnwindSafe + std::panic::RefUnwindSafe { /// Return whether the group is stale, registering `waiter` for anything that /// could change the answer while the group remains live. fn is_expired(&self, waiter: &kio::Waiter) -> bool; diff --git a/rs/moq-net/src/model/track.rs b/rs/moq-net/src/model/track.rs index 84edd324f1..6e6daae06e 100644 --- a/rs/moq-net/src/model/track.rs +++ b/rs/moq-net/src/model/track.rs @@ -8080,6 +8080,15 @@ mod test { assert_eq!(retry.await.unwrap().sequence, 5); } + /// Dropping an auto trait from a published type is a semver break, so the group + /// consumer a cached fetch holds must not cost `Fetching` its unwind safety. + #[test] + fn fetching_is_unwind_safe() { + fn assert_unwind_safe() {} + assert_unwind_safe::(); + assert_unwind_safe::(); + } + /// A fetch that hits the cache holds the group until polled, so a handler that aborts /// the group once nobody wants it (an abandoned upstream fetch) leaves it alone. #[tokio::test]