Skip to content

Commit

Permalink
rust: add support for trait objects in Refs.
Browse files Browse the repository at this point in the history
This allows, for example, the automatic coercion from `Ref<T>` to
`Ref<dyn U>` when `U` is a trait implemented by `T`. It also allows
`Ref<dyn U>` to be used as the receiver in a trait object.

These traits are also implemented by `Arc`, and this is in preparation
for replacing all usages of `Arc` with `Ref`, which is needed before we
can remove `Arc` from the `alloc` crate.

Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
  • Loading branch information
wedsonaf committed Jul 24, 2021
1 parent 85f97a8 commit 99c380f
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 1 deletion.
3 changes: 3 additions & 0 deletions rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
const_unreachable_unchecked,
doc_cfg,
receiver_trait,
coerce_unsized,
dispatch_from_dyn,
unsize,
try_reserve
)]

Expand Down
14 changes: 13 additions & 1 deletion rust/kernel/sync/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@
use crate::{bindings, Result};
use alloc::boxed::Box;
use core::{
cell::UnsafeCell, convert::AsRef, marker::PhantomData, mem::ManuallyDrop, ops::Deref, pin::Pin,
cell::UnsafeCell,
convert::AsRef,
marker::{PhantomData, Unsize},
mem::ManuallyDrop,
ops::Deref,
pin::Pin,
ptr::NonNull,
};

Expand Down Expand Up @@ -50,6 +55,13 @@ struct RefInner<T: ?Sized> {
// This is to allow [`Ref`] (and variants) to be used as the type of `self`.
impl<T: ?Sized> core::ops::Receiver for Ref<T> {}

// This is to allow coercion from `Ref<T>` to `Ref<U>` if `T` can be converted to the
// dynamically-sized type (DST) `U`.
impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Ref<U>> for Ref<T> {}

// This is to allow `Ref<U>` to be dispatched on when `Ref<T>` can be coerced into `Ref<U>`.
impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Ref<U>> for Ref<T> {}

// SAFETY: It is safe to send `Ref<T>` to another thread when the underlying `T` is `Sync` because
// it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs
// `T` to be `Send` because any thread that has a `Ref<T>` may ultimately access `T` directly, for
Expand Down

0 comments on commit 99c380f

Please sign in to comment.