From 3d0ced0bd110550162db2c2292aaf082d1033648 Mon Sep 17 00:00:00 2001 From: Oleksandr Babak Date: Tue, 28 Oct 2025 13:58:18 +0100 Subject: [PATCH] fix: make mutexes `!Send` Each mutex is generated uniquely for each task, it is unsound to send them between tasks. But they are `Send`. Before, it wasn't an issue, because you couldn't share non-`'static` data between them, but with \#1043 you can make the mutex `'static`. Thus we need to use actual tools that Rust provides and out out from `Send`. Currently, mutexes are simple ZSTs with `PhantomData<&'a ()>`, which is `Send`. We replace it with `PhantomData<(&'a (), *const u8)>`, and return `Sync` back via `unsafe` implementation. It is trivially sound, because mutexes have no method methods that accept `&self`. See https://doc.rust-lang.org/std/sync/struct.Exclusive.html for details. --- rtic-macros/src/codegen/shared_resources.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rtic-macros/src/codegen/shared_resources.rs b/rtic-macros/src/codegen/shared_resources.rs index 5e8ca9ae77c..92657c8fe69 100644 --- a/rtic-macros/src/codegen/shared_resources.rs +++ b/rtic-macros/src/codegen/shared_resources.rs @@ -62,9 +62,14 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { #[allow(non_camel_case_types)] #(#cfgs)* pub struct #shared_name<'a> { - __rtic_internal_p: ::core::marker::PhantomData<&'a ()>, + __rtic_internal_p: ::core::marker::PhantomData<(&'a (), *const u8)>, } + // Opt out from `Send`. + // `#shared_name` is trivially `Sync` because there are no `&self` methods. + // See https://doc.rust-lang.org/std/sync/struct.Exclusive.html . + unsafe impl<'a> Sync for #shared_name<'a> {} + #(#cfgs)* impl<'a> #shared_name<'a> { #[inline(always)]