public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Alice Ryhl <aliceryhl@google.com>
To: "Onur Özkan" <work@onurozkan.dev>
Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
	 daniel@sedlak.dev, dirk.behme@de.bosch.com,
	felipe_life@live.com,  tamird@gmail.com, dakr@kernel.org,
	tmgross@umich.edu, a.hindborg@kernel.org,  lossin@kernel.org,
	bjorn3_gh@protonmail.com, gary@garyguo.net,
	 boqun.feng@gmail.com, alex.gaynor@gmail.com, ojeda@kernel.org
Subject: Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
Date: Wed, 10 Sep 2025 06:26:27 +0000	[thread overview]
Message-ID: <aMEaE2NEU2FctgH2@google.com> (raw)
In-Reply-To: <20250909170013.16025-2-work@onurozkan.dev>

On Tue, Sep 09, 2025 at 08:00:13PM +0300, Onur Özkan wrote:
> Current `to_result` helper takes a `c_int` and returns `Ok(())` on
> success and this has some issues like:
> 
>     - Callers lose the original return value and often have to store
> 	it in a temporary variable before calling `to_result`.
> 
>     - It only supports `c_int`, which makes callers to unnecessarily
> 	cast when working with other types (e.g. `u16` in phy
> 	abstractions). We even have some places that ignore to use
> 	`to_result` helper because the input doesn't fit in `c_int`
> 	(see [0]).
> 
> [0]: https://lore.kernel.org/all/20250822080252.773d6f54@nimda.home/
> 
> This patch changes `to_result` to be generic and also return the
> original value on success.
> 
> So that the code that previously looked like:
> 
>     let ret = unsafe { bindings::some_ffi_call() };
>     to_result(ret).map(|()| SomeType::new(ret))
> 
> can now be written more directly as:
> 
>     to_result(unsafe { bindings::some_ffi_call() })
> 	.map(|ret| SomeType::new(ret))
> 
> Similarly, code such as:
> 
>     let res: isize = $some_ffi_call();
>     if res < 0 {
> 	    return Err(Error::from_errno(res as i32));
>     }
> 
> can now be used with `to_result` as:
> 
>     to_result($some_ffi_call())?;
> 
> This patch only fixes the callers that broke after the changes on `to_result`.
> I haven't included all the improvements made possible by the new design since
> that could conflict with other ongoing patches [1]. Once this patch is approved
> and applied, I am planning to follow up with creating a "good first issue" on [2]
> for those additional changes.
> 
> [1]: https://lore.kernel.org/rust-for-linux/?q=to_result
> [2]: https://github.com/Rust-for-Linux/linux
> 
> Link: https://rust-for-linux.zulipchat.com/#narrow/channel/288089/topic/x/near/536374456
> Signed-off-by: Onur Özkan <work@onurozkan.dev>

> diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
> index a41de293dcd1..6563ea71e203 100644
> --- a/rust/kernel/error.rs
> +++ b/rust/kernel/error.rs
> @@ -376,12 +376,19 @@ fn from(e: core::convert::Infallible) -> Error {
>  pub type Result<T = (), E = Error> = core::result::Result<T, E>;
> 
>  /// Converts an integer as returned by a C kernel function to an error if it's negative, and
> -/// `Ok(())` otherwise.
> -pub fn to_result(err: crate::ffi::c_int) -> Result {
> -    if err < 0 {
> -        Err(Error::from_errno(err))
> +/// returns the original value otherwise.
> +pub fn to_result<T>(code: T) -> Result<T>
> +where
> +    T: Copy + TryInto<i32>,
> +{
> +    // Try casting into `i32`.
> +    let casted: crate::ffi::c_int = code.try_into().unwrap_or(0);
> +
> +    if casted < 0 {
> +        Err(Error::from_errno(casted))
>      } else {
> -        Ok(())
> +        // Return the original input value.
> +        Ok(code)
>      }
>  }

I don't think this is the best way to declare this function. The
conversions I would want are:

* i32 -> Result<u32>
* isize -> Result<usize>
* i64 -> Result<u64>

Your commit messages mentions i16, but does the error types even fit in
16 bits? Maybe. But they don't fit in i8. That is to say, I think it
should support all the types larger than i32 (the errors fit in those
types too), but for the ones that are smaller, it might not make sense
if the type is too small. That's the reverse of what you have now.

We probably need a new trait. E.g.:

trait ToResult {
    type Unsigned;
    fn to_result(self) -> Result<Self::Unsigned, Error>;
}

impl ToResult for i32 {
    type Unsigned = u32;
    fn to_result(self) -> Result<u32, Error> {
        ...
    }
}

impl ToResult for isize {
    type Unsigned = usize;
    fn to_result(self) -> Result<usize, Error> {
        ...
    }
}

pub fn to_result<T: ToResult>(code: T) -> Result<T::Unsigned> {
    T::to_result(code)
}

> diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
> index 6373fe183b27..22b72ae84c03 100644
> --- a/rust/kernel/miscdevice.rs
> +++ b/rust/kernel/miscdevice.rs
> @@ -79,7 +79,7 @@ pub fn register(opts: MiscDeviceOptions) -> impl PinInit<Self, Error> {
>                  // the destructor of this type deallocates the memory.
>                  // INVARIANT: If this returns `Ok(())`, then the `slot` will contain a registered
>                  // misc device.
> -                to_result(unsafe { bindings::misc_register(slot) })
> +                to_result(unsafe { bindings::misc_register(slot) }).map(|_| ())

This still uses the `map` pattern. Please change it too.

Alice

  parent reply	other threads:[~2025-09-10  6:26 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-09 17:00 [PATCH v2 0/1] rust: refactor to_result to return the original value Onur Özkan
2025-09-09 17:00 ` [PATCH v2 1/1] " Onur Özkan
2025-09-09 17:17   ` Miguel Ojeda
2025-09-09 17:43     ` Onur Özkan
2025-09-09 18:25       ` Onur
2025-09-09 18:25       ` Daniel Almeida
2025-09-09 18:53         ` Onur Özkan
2025-09-09 20:13           ` Daniel Almeida
2025-09-09 20:05       ` Miguel Ojeda
2025-09-09 20:12         ` Daniel Almeida
2025-09-09 20:25           ` Miguel Ojeda
2025-09-10  4:50         ` Onur Özkan
2025-09-10  6:26   ` Alice Ryhl [this message]
2025-09-10 10:58     ` Onur Özkan
2025-09-10 11:05       ` Alice Ryhl
2025-09-10 12:47         ` Onur Özkan
2025-09-10 12:50           ` Alice Ryhl
2025-09-10 12:55             ` Onur Özkan
2025-09-12  8:41   ` kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aMEaE2NEU2FctgH2@google.com \
    --to=aliceryhl@google.com \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=dakr@kernel.org \
    --cc=daniel@sedlak.dev \
    --cc=dirk.behme@de.bosch.com \
    --cc=felipe_life@live.com \
    --cc=gary@garyguo.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tamird@gmail.com \
    --cc=tmgross@umich.edu \
    --cc=work@onurozkan.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox