[v2,27/28] rust: types: add `Either` type

Message ID 20221202161502.385525-28-ojeda@kernel.org
State New
Headers
Series [v2,01/28] rust: prelude: split re-exports into groups |

Commit Message

Miguel Ojeda Dec. 2, 2022, 4:14 p.m. UTC
  From: Wedson Almeida Filho <wedsonaf@gmail.com>

Introduce the new `types` module of the `kernel` crate with
`Either` as its first type.

`Either<L, R>` is a sum type that always holds either a value
of type `L` (`Left` variant) or `R` (`Right` variant).

For instance:

    struct Executor {
        queue: Either<BoxedQueue, &'static Queue>,
    }

Signed-off-by: Wedson Almeida Filho <wedsonaf@gmail.com>
Reviewed-by: Wei Liu <wei.liu@kernel.org>
[Reworded, adapted for upstream and applied latest changes]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 rust/kernel/lib.rs   |  1 +
 rust/kernel/types.rs | 12 ++++++++++++
 2 files changed, 13 insertions(+)
 create mode 100644 rust/kernel/types.rs
  

Comments

Josh Triplett Dec. 2, 2022, 11:41 p.m. UTC | #1
On Fri, Dec 02, 2022 at 05:14:58PM +0100, ojeda@kernel.org wrote:
> From: Wedson Almeida Filho <wedsonaf@gmail.com>
> 
> Introduce the new `types` module of the `kernel` crate with
> `Either` as its first type.
> 
> `Either<L, R>` is a sum type that always holds either a value
> of type `L` (`Left` variant) or `R` (`Right` variant).
> 
> For instance:
> 
>     struct Executor {
>         queue: Either<BoxedQueue, &'static Queue>,
>     }

This specific example seems like it would be better served by the
existing `Cow` type.
  
Miguel Ojeda Dec. 4, 2022, 12:58 a.m. UTC | #2
On Sat, Dec 3, 2022 at 12:42 AM Josh Triplett <josh@joshtriplett.org> wrote:
>
> This specific example seems like it would be better served by the
> existing `Cow` type.

Yeah, possibly -- it is taken from one of the use cases in the full
repository. Perhaps it was deemed simpler, or providing a way to go to
an owned instance was to be avoided.

Thanks for taking a look!

Cheers,
Miguel
  
Gary Guo Dec. 4, 2022, 10:31 a.m. UTC | #3
On Fri, 2 Dec 2022 15:41:59 -0800
Josh Triplett <josh@joshtriplett.org> wrote:

> On Fri, Dec 02, 2022 at 05:14:58PM +0100, ojeda@kernel.org wrote:
> > From: Wedson Almeida Filho <wedsonaf@gmail.com>
> > 
> > Introduce the new `types` module of the `kernel` crate with
> > `Either` as its first type.
> > 
> > `Either<L, R>` is a sum type that always holds either a value
> > of type `L` (`Left` variant) or `R` (`Right` variant).
> > 
> > For instance:
> > 
> >     struct Executor {
> >         queue: Either<BoxedQueue, &'static Queue>,
> >     }  
> 
> This specific example seems like it would be better served by the
> existing `Cow` type.

We use `no_global_oom_handling`, which gates most `ToOwned`
implementations (e.g. `str` cannot implement `to_owned()` because it
cannot guarantee allocation success).

So the Rust `Cow` is pretty much useless in the kernel.

Best,
Gary
  
Wedson Almeida Filho Dec. 4, 2022, 5:36 p.m. UTC | #4
On Sun, 4 Dec 2022 at 10:31, Gary Guo <gary@garyguo.net> wrote:
>
> On Fri, 2 Dec 2022 15:41:59 -0800
> Josh Triplett <josh@joshtriplett.org> wrote:
>
> > On Fri, Dec 02, 2022 at 05:14:58PM +0100, ojeda@kernel.org wrote:
> > > From: Wedson Almeida Filho <wedsonaf@gmail.com>
> > >
> > > Introduce the new `types` module of the `kernel` crate with
> > > `Either` as its first type.
> > >
> > > `Either<L, R>` is a sum type that always holds either a value
> > > of type `L` (`Left` variant) or `R` (`Right` variant).
> > >
> > > For instance:
> > >
> > >     struct Executor {
> > >         queue: Either<BoxedQueue, &'static Queue>,
> > >     }
> >
> > This specific example seems like it would be better served by the
> > existing `Cow` type.
>
> We use `no_global_oom_handling`, which gates most `ToOwned`
> implementations (e.g. `str` cannot implement `to_owned()` because it
> cannot guarantee allocation success).
>
> So the Rust `Cow` is pretty much useless in the kernel.

It's also implemented in `std`, which the kernel doesn't include.
(Which is actually good for us, since we can't really use it.)

Josh, how do you feel about adding a `TryToOwned` trait to
`core::borrow`? This would be similar to the precedent of `TryFrom` in
addition to `From` for the fallible case, and would be usable by the
kernel.
  
Miguel Ojeda Dec. 5, 2022, 1:53 p.m. UTC | #5
On Sun, Dec 4, 2022 at 6:36 PM Wedson Almeida Filho <wedsonaf@gmail.com> wrote:
>
> It's also implemented in `std`, which the kernel doesn't include.
> (Which is actually good for us, since we can't really use it.)

We have it around in the kernel (the `std` one is a re-export), so one
"could" replace the `Either` with `Cow` in the case of the commit
message via ignoring the to-owned side of it (but I assume Josh didn't
mean to suggest that).

Anyway, it can be easily configured out from our `alloc`, so I will
send the patch.

Cheers,
Miguel
  
Josh Triplett Dec. 5, 2022, 11 p.m. UTC | #6
On Sun, Dec 04, 2022 at 05:36:08PM +0000, Wedson Almeida Filho wrote:
> On Sun, 4 Dec 2022 at 10:31, Gary Guo <gary@garyguo.net> wrote:
> >
> > On Fri, 2 Dec 2022 15:41:59 -0800
> > Josh Triplett <josh@joshtriplett.org> wrote:
> >
> > > On Fri, Dec 02, 2022 at 05:14:58PM +0100, ojeda@kernel.org wrote:
> > > > From: Wedson Almeida Filho <wedsonaf@gmail.com>
> > > >
> > > > Introduce the new `types` module of the `kernel` crate with
> > > > `Either` as its first type.
> > > >
> > > > `Either<L, R>` is a sum type that always holds either a value
> > > > of type `L` (`Left` variant) or `R` (`Right` variant).
> > > >
> > > > For instance:
> > > >
> > > >     struct Executor {
> > > >         queue: Either<BoxedQueue, &'static Queue>,
> > > >     }
> > >
> > > This specific example seems like it would be better served by the
> > > existing `Cow` type.
> >
> > We use `no_global_oom_handling`, which gates most `ToOwned`
> > implementations (e.g. `str` cannot implement `to_owned()` because it
> > cannot guarantee allocation success).
> >
> > So the Rust `Cow` is pretty much useless in the kernel.
> 
> It's also implemented in `std`, which the kernel doesn't include.
> (Which is actually good for us, since we can't really use it.)
> 
> Josh, how do you feel about adding a `TryToOwned` trait to
> `core::borrow`? This would be similar to the precedent of `TryFrom` in
> addition to `From` for the fallible case, and would be usable by the
> kernel.

I'd expect it to be in alloc rather than core (though I suppose it
doesn't *fundamentally* depend on an allocator itself), but I'd be happy
to see a fallible version proposed, yeah.
  

Patch

diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index a3abc110ff97..53040fa9e897 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -31,6 +31,7 @@  mod static_assert;
 #[doc(hidden)]
 pub mod std_vendor;
 pub mod str;
+pub mod types;
 
 #[doc(hidden)]
 pub use bindings;
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
new file mode 100644
index 000000000000..3b0c44769708
--- /dev/null
+++ b/rust/kernel/types.rs
@@ -0,0 +1,12 @@ 
+// SPDX-License-Identifier: GPL-2.0
+
+//! Kernel types.
+
+/// A sum type that always holds either a value of type `L` or `R`.
+pub enum Either<L, R> {
+    /// Constructs an instance of [`Either`] containing a value of type `L`.
+    Left(L),
+
+    /// Constructs an instance of [`Either`] containing a value of type `R`.
+    Right(R),
+}