Skip to content

Make Lock<T> work when T is pinned. #1181

@dwlsalmeida

Description

@dwlsalmeida

It's currently impossible to have a pinned struct within the Lock<T> type. This is problematic, because drivers might want to do this for various reasons, specially as they grow in complexity.

A trivial example is:

#[pin_data] 
struct Foo {
  #[pin]
  bar: Mutex<Bar>,
  #[pin]
  p: PhantomPinned,
}

#[pin_data]
struct Bar {
  #[pin]
  baz: Mutex<Baz>,
  #[pin]
  p: PhantomPinned,
}

Note that Bar is pinned, so having it in a Mutex makes it impossible to instantiate a Foo that pins the Bar in bar. This is specially undesirable, since Foo is already pinned, and thus, it could trivially enforce that its bar field is pinned as well.

This can be trivially solved by using Pin<KBox<Bar>> instead of structurally pinning, at the cost of an extra (completely unneeded) allocation and ugly syntax. Furthermore, there is no support for pinned projections, so the following won't work:

    let mut data: MutexGuard<'_, Data> = mutex.lock();
    let mut data: Pin<&mut Data> = data.as_mut();
    let a = &mut data.a; // <- won't compile

This task covers the work to make it possible to instantiate a Foo that pins its bar field.

We will start with the following changes, initially:

Changes needed for pinning the T in Mutex<T>:

  • in fn new() use impl PinInit<T> instead of T
  • the guard needs to only implement DerefMut if T: Unpin
  • the guard needs to have fn as_mut(&mut self) -> Pin<&mut T>

Here is a link to the relevant discussion on Zulip is.

Metadata

Metadata

Assignees

Labels

• libRelated to the `rust/` library.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions