# Meeting 2025-07-23 <!-- Leave your topic starting with ### in the relevant sections below --> ## Critical <!-- bugs, soundness issues, urgent patches/reviews etc. --> ## Status Reports <!-- You want to report on something you are working on/request reviews. Or you want to know the status of something someone else is doing --> * Xiang is still working on the abitrary self type. * Boqun: I'm not able to follow the blocking issue of pin-initializer, please add more details @dingxf. * xiang: Recently we were talking about allowing `T: Init<[T; N]>` to also implicate `T: Init<[T]>`. The technical details of allowing such type judgement are to finalize, especially I need to find a safe way to select a correct `T: Init<[T; N]>`, if any, and rejects ambiguity, if we are in a situation to prove that `T: Init<[T]>`. ## Discussion Questions <!-- Anything that requires lengthy discussion/more general questions also fit here --> ### Kangrejos 2025 * Joel asked for the status about calling functions between Rust modules, and Miguel planned to give a topic about that on Kangrejos. * Daniel suggested to talk about Tyr at Kangrejos. * Boqun suggested to talk about SpinLockIrq at Kangrejos. ### Pinned Data in `Lock<T>` Boqun: I think we should also separate `Mutex` and `Spinlock`, ie get rid of the generic `Lock`. But this is orthogonal Changes needed for data in `Mutex<T>` are: * in the `new` use `impl PinInit<T>` instead `T` * the guard needs to only implement `DerefMut` if `T: Unpin` * the guard needs to have `fn as_mut(&mut self) -> Pin<&mut T>` Alice: We need pin/field projections for this to be useful in practice. ```rust #[pin_data] struct Data { #[pin] a: Devres<A>, #[pin] b: Devres<B>, } fn handle_data(mutex: &Mutex<Data>) { let mut data: MutexGuard<'_, Data> = mutex.lock(); let mut data: Pin<&mut Data> = data.as_mut(); let a = &mut data.a; // <- won't compile // instead can do this now: let a: Pin<&mut Devres<A>> = unsafe { Pin::map_mut_unchecked(data, |data| &mut data.a) }; // what we could also do with macros would be: let a: Pin<&mut Devres<A>> = Data::project_a(data); let a: Pin<&mut Devres<A>> = data.project().a; // field projection prototype let a = proj!(data => a); // <- Boqun: can we just expand this line with the above unsafe code? let a = proj!(unsafe data => a); let a = p!(@mut data->a); // Either reference a generated name let PinProjectedData { a, b } = data.project(); // or let proj = data.project(); let a = proj.a; let a = proj.b; // this would be with field projections: (faar in the future) let a: Pin<&mut Devres<A>> = @mut data.a; } ``` Conclusion: if we want to invest more to make it help field projection proposal, let's try to see if we can get `syn` in as a dependency and have the safe `p!()` macro (i.e. a macro implemenation of field projection). <https://github.com/Rust-for-Linux/field-projection/blob/new/examples/fair_race_future.rs> ```patch diff --git a/rust/pin-init/src/macros.rs b/rust/pin-init/src/macros.rs index 9ced630737b8..94092bd11cda 100644 --- a/rust/pin-init/src/macros.rs +++ b/rust/pin-init/src/macros.rs @@ -988,6 +988,31 @@ fn drop(&mut self) { @pinned($($(#[$($p_attr:tt)*])* $pvis:vis $p_field:ident : $p_type:ty),* $(,)?), @not_pinned($($(#[$($attr:tt)*])* $fvis:vis $field:ident : $type:ty),* $(,)?), ) => { + $crate::macros::paste! { + impl<$($impl_generics)*> $name<$($ty_generics)*> + where $($whr)* + { + $( + $(#[$($p_attr)*])* + $pvis unsafe fn [< project_ $p_field >]( + self: ::core::pin::Pin<&mut Self>, + ) -> ::core::pin::Pin<&mut $p_type> { + // SAFETY: `$p_field` is structurally pinned. + unsafe { ::core::pin::Pin::map_unchecked_mut(self, |inner| &mut inner.$p_field) } + } + )* + $( + $(#[$($attr)*])* + $fvis unsafe fn [< project_ $field >]( + self: ::core::pin::Pin<&mut Self>, + ) -> &mut $type { + // SAFETY: `$field` is not structurally pinned. + unsafe { &mut ::core::pin::Pin::get_unchecked_mut(self).$field } + } + )* + } + } + // For every field, we create a projection function according to its projection type. If a // field is structurally pinned, then it must be initialized via `PinInit`, if it is not // structurally pinned, then it can be initialized via `Init`. ``` ## Miscellaneous <!-- stuff that does not fit into other categories -->