From 99c380f872ae8c50b393c8b6c4fc786f762ef9ad Mon Sep 17 00:00:00 2001 From: Wedson Almeida Filho Date: Wed, 30 Jun 2021 23:04:51 +0100 Subject: [PATCH] rust: add support for trait objects in `Ref`s. This allows, for example, the automatic coercion from `Ref` to `Ref` when `U` is a trait implemented by `T`. It also allows `Ref` 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 --- rust/kernel/lib.rs | 3 +++ rust/kernel/sync/arc.rs | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 745cc19b217fc5..c3e0ac9c65b38a 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -22,6 +22,9 @@ const_unreachable_unchecked, doc_cfg, receiver_trait, + coerce_unsized, + dispatch_from_dyn, + unsize, try_reserve )] diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index ddecb9e371a45c..898e9b2dd10a87 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -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, }; @@ -50,6 +55,13 @@ struct RefInner { // This is to allow [`Ref`] (and variants) to be used as the type of `self`. impl core::ops::Receiver for Ref {} +// This is to allow coercion from `Ref` to `Ref` if `T` can be converted to the +// dynamically-sized type (DST) `U`. +impl, U: ?Sized> core::ops::CoerceUnsized> for Ref {} + +// This is to allow `Ref` to be dispatched on when `Ref` can be coerced into `Ref`. +impl, U: ?Sized> core::ops::DispatchFromDyn> for Ref {} + // SAFETY: It is safe to send `Ref` 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` may ultimately access `T` directly, for