rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/1] rust: refactor to_result to return the original value
@ 2025-09-09 17:00 Onur Özkan
  2025-09-09 17:00 ` [PATCH v2 1/1] " Onur Özkan
  0 siblings, 1 reply; 19+ messages in thread
From: Onur Özkan @ 2025-09-09 17:00 UTC (permalink / raw)
  To: rust-for-linux
  Cc: linux-kernel, daniel, dirk.behme, felipe_life, tamird, dakr,
	tmgross, aliceryhl, a.hindborg, lossin, bjorn3_gh, gary,
	boqun.feng, alex.gaynor, ojeda, Onur Özkan

Changelog in v2:
  - Removed `map(|_| ())` calls from v1 and replaced them with
  `to_result(...)?` and `Ok(())` (except miscdevice.rs, as it
  required `Ok::<(), Error>(())` which is less clean).

  - Rebased on latest regulator/for-next and fixed the build error.

Onur Özkan (1):
  rust: refactor to_result to return the original value

 rust/kernel/auxiliary.rs        |  3 ++-
 rust/kernel/block/mq/tag_set.rs |  3 ++-
 rust/kernel/cpufreq.rs          |  5 +++--
 rust/kernel/devres.rs           |  3 ++-
 rust/kernel/dma.rs              | 11 ++++++++---
 rust/kernel/error.rs            | 17 ++++++++++++-----
 rust/kernel/miscdevice.rs       |  2 +-
 rust/kernel/mm/virt.rs          |  3 ++-
 rust/kernel/pci.rs              |  6 ++++--
 rust/kernel/platform.rs         |  3 ++-
 rust/kernel/regulator.rs        | 14 ++++++++------
 11 files changed, 46 insertions(+), 24 deletions(-)

--
2.50.0


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v2 1/1] rust: refactor to_result to return the original value
  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 ` Onur Özkan
  2025-09-09 17:17   ` Miguel Ojeda
                     ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Onur Özkan @ 2025-09-09 17:00 UTC (permalink / raw)
  To: rust-for-linux
  Cc: linux-kernel, daniel, dirk.behme, felipe_life, tamird, dakr,
	tmgross, aliceryhl, a.hindborg, lossin, bjorn3_gh, gary,
	boqun.feng, alex.gaynor, ojeda, Onur Özkan

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>
---
 rust/kernel/auxiliary.rs        |  3 ++-
 rust/kernel/block/mq/tag_set.rs |  3 ++-
 rust/kernel/cpufreq.rs          |  6 ++++--
 rust/kernel/devres.rs           |  3 ++-
 rust/kernel/dma.rs              | 11 ++++++++---
 rust/kernel/error.rs            | 17 ++++++++++++-----
 rust/kernel/miscdevice.rs       |  2 +-
 rust/kernel/mm/virt.rs          |  3 ++-
 rust/kernel/pci.rs              |  6 ++++--
 rust/kernel/platform.rs         |  3 ++-
 rust/kernel/regulator.rs        | 14 ++++++++------
 11 files changed, 47 insertions(+), 24 deletions(-)

diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs
index 4749fb6bffef..74b4da1192e1 100644
--- a/rust/kernel/auxiliary.rs
+++ b/rust/kernel/auxiliary.rs
@@ -42,7 +42,8 @@ unsafe fn register(
         // SAFETY: `adrv` is guaranteed to be a valid `RegType`.
         to_result(unsafe {
             bindings::__auxiliary_driver_register(adrv.get(), module.0, name.as_char_ptr())
-        })
+        })?;
+        Ok(())
     }

     unsafe fn unregister(adrv: &Opaque<Self::RegType>) {
diff --git a/rust/kernel/block/mq/tag_set.rs b/rust/kernel/block/mq/tag_set.rs
index c3cf56d52bee..e8adb9d72475 100644
--- a/rust/kernel/block/mq/tag_set.rs
+++ b/rust/kernel/block/mq/tag_set.rs
@@ -65,7 +65,8 @@ pub fn new(
                 // SAFETY: we do not move out of `tag_set`.
                 let tag_set: &mut Opaque<_> = unsafe { Pin::get_unchecked_mut(tag_set) };
                 // SAFETY: `tag_set` is a reference to an initialized `blk_mq_tag_set`.
-                error::to_result( unsafe { bindings::blk_mq_alloc_tag_set(tag_set.get())})
+                error::to_result( unsafe { bindings::blk_mq_alloc_tag_set(tag_set.get())})?;
+                Ok(())
             }),
             _p: PhantomData,
         })
diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs
index afc15e72a7c3..b9db81aea5c6 100644
--- a/rust/kernel/cpufreq.rs
+++ b/rust/kernel/cpufreq.rs
@@ -157,7 +157,8 @@ pub fn as_raw(&self) -> *mut bindings::cpufreq_policy_data {
     #[inline]
     pub fn generic_verify(&self) -> Result {
         // SAFETY: By the type invariant, the pointer stored in `self` is valid.
-        to_result(unsafe { bindings::cpufreq_generic_frequency_table_verify(self.as_raw()) })
+        to_result(unsafe { bindings::cpufreq_generic_frequency_table_verify(self.as_raw()) })?;
+        Ok(())
     }
 }

@@ -520,7 +521,8 @@ pub fn set_suspend_freq(&mut self, freq: Hertz) -> &mut Self {
     #[inline]
     pub fn generic_suspend(&mut self) -> Result {
         // SAFETY: By the type invariant, the pointer stored in `self` is valid.
-        to_result(unsafe { bindings::cpufreq_generic_suspend(self.as_mut_ref()) })
+        to_result(unsafe { bindings::cpufreq_generic_suspend(self.as_mut_ref()) })?;
+        Ok(())
     }

     /// Provides a wrapper to the generic get routine.
diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs
index d04e3fcebafb..487e194f7d96 100644
--- a/rust/kernel/devres.rs
+++ b/rust/kernel/devres.rs
@@ -327,7 +327,8 @@ fn register_foreign<P>(dev: &Device<Bound>, data: P) -> Result
         // `devm_add_action_or_reset()` also calls `callback` on failure, such that the
         // `ForeignOwnable` is released eventually.
         bindings::devm_add_action_or_reset(dev.as_raw(), Some(callback::<P>), ptr.cast())
-    })
+    })?;
+    Ok(())
 }

 /// Encapsulate `data` in a [`KBox`] and [`Drop::drop`] `data` once `dev` is unbound.
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index 2bc8ab51ec28..04ca70f6f684 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -33,7 +33,8 @@ unsafe fn dma_set_mask(&self, mask: DmaMask) -> Result {
         // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
         // - The safety requirement of this function guarantees that there are no concurrent calls
         //   to DMA allocation and mapping primitives using this mask.
-        to_result(unsafe { bindings::dma_set_mask(self.as_ref().as_raw(), mask.value()) })
+        to_result(unsafe { bindings::dma_set_mask(self.as_ref().as_raw(), mask.value()) })?;
+        Ok(())
     }

     /// Set up the device's DMA coherent addressing capabilities.
@@ -50,7 +51,10 @@ unsafe fn dma_set_coherent_mask(&self, mask: DmaMask) -> Result {
         // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
         // - The safety requirement of this function guarantees that there are no concurrent calls
         //   to DMA allocation and mapping primitives using this mask.
-        to_result(unsafe { bindings::dma_set_coherent_mask(self.as_ref().as_raw(), mask.value()) })
+        to_result(unsafe {
+            bindings::dma_set_coherent_mask(self.as_ref().as_raw(), mask.value())
+        })?;
+        Ok(())
     }

     /// Set up the device's DMA addressing capabilities.
@@ -71,7 +75,8 @@ unsafe fn dma_set_mask_and_coherent(&self, mask: DmaMask) -> Result {
         //   to DMA allocation and mapping primitives using this mask.
         to_result(unsafe {
             bindings::dma_set_mask_and_coherent(self.as_ref().as_raw(), mask.value())
-        })
+        })?;
+        Ok(())
     }
 }

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)
     }
 }

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(|_| ())
             }),
             _t: PhantomData,
         })
diff --git a/rust/kernel/mm/virt.rs b/rust/kernel/mm/virt.rs
index 6086ca981b06..62c00dcdb5e1 100644
--- a/rust/kernel/mm/virt.rs
+++ b/rust/kernel/mm/virt.rs
@@ -194,7 +194,8 @@ pub unsafe fn from_raw<'a>(vma: *const bindings::vm_area_struct) -> &'a Self {
     pub fn vm_insert_page(&self, address: usize, page: &Page) -> Result {
         // SAFETY: By the type invariant of `Self` caller has read access and has verified that
         // `VM_MIXEDMAP` is set. By invariant on `Page` the page has order 0.
-        to_result(unsafe { bindings::vm_insert_page(self.as_ptr(), address, page.as_ptr()) })
+        to_result(unsafe { bindings::vm_insert_page(self.as_ptr(), address, page.as_ptr()) })?;
+        Ok(())
     }
 }

diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 887ee611b553..b52a7be488d0 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -47,7 +47,8 @@ unsafe fn register(
         // SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
         to_result(unsafe {
             bindings::__pci_register_driver(pdrv.get(), module.0, name.as_char_ptr())
-        })
+        })?;
+        Ok(())
     }

     unsafe fn unregister(pdrv: &Opaque<Self::RegType>) {
@@ -437,7 +438,8 @@ impl Device<device::Core> {
     /// Enable memory resources for this device.
     pub fn enable_device_mem(&self) -> Result {
         // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`.
-        to_result(unsafe { bindings::pci_enable_device_mem(self.as_raw()) })
+        to_result(unsafe { bindings::pci_enable_device_mem(self.as_raw()) })?;
+        Ok(())
     }

     /// Enable bus-mastering for this device.
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index 8f028c76f9fa..751b65bfc357 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -54,7 +54,8 @@ unsafe fn register(
         }

         // SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
-        to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) })
+        to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) })?;
+        Ok(())
     }

     unsafe fn unregister(pdrv: &Opaque<Self::RegType>) {
diff --git a/rust/kernel/regulator.rs b/rust/kernel/regulator.rs
index 34bb24ec8d4d..a5f357bda6e9 100644
--- a/rust/kernel/regulator.rs
+++ b/rust/kernel/regulator.rs
@@ -260,15 +260,15 @@ pub fn set_voltage(&self, min_voltage: Voltage, max_voltage: Voltage) -> Result
                 min_voltage.as_microvolts(),
                 max_voltage.as_microvolts(),
             )
-        })
+        })?;
+        Ok(())
     }

     /// Gets the current voltage of the regulator.
     pub fn get_voltage(&self) -> Result<Voltage> {
         // SAFETY: Safe as per the type invariants of `Regulator`.
-        let voltage = unsafe { bindings::regulator_get_voltage(self.inner.as_ptr()) };
-
-        to_result(voltage).map(|()| Voltage::from_microvolts(voltage))
+        to_result(unsafe { bindings::regulator_get_voltage(self.inner.as_ptr()) })
+            .map(Voltage::from_microvolts)
     }

     fn get_internal(dev: &Device, name: &CStr) -> Result<Regulator<T>> {
@@ -288,12 +288,14 @@ fn get_internal(dev: &Device, name: &CStr) -> Result<Regulator<T>> {

     fn enable_internal(&self) -> Result {
         // SAFETY: Safe as per the type invariants of `Regulator`.
-        to_result(unsafe { bindings::regulator_enable(self.inner.as_ptr()) })
+        to_result(unsafe { bindings::regulator_enable(self.inner.as_ptr()) })?;
+        Ok(())
     }

     fn disable_internal(&self) -> Result {
         // SAFETY: Safe as per the type invariants of `Regulator`.
-        to_result(unsafe { bindings::regulator_disable(self.inner.as_ptr()) })
+        to_result(unsafe { bindings::regulator_disable(self.inner.as_ptr()) })?;
+        Ok(())
     }
 }

--
2.50.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  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-10  6:26   ` Alice Ryhl
  2025-09-12  8:41   ` kernel test robot
  2 siblings, 1 reply; 19+ messages in thread
From: Miguel Ojeda @ 2025-09-09 17:17 UTC (permalink / raw)
  To: Onur Özkan
  Cc: rust-for-linux, linux-kernel, daniel, dirk.behme, felipe_life,
	tamird, dakr, tmgross, aliceryhl, a.hindborg, lossin, bjorn3_gh,
	gary, boqun.feng, alex.gaynor, ojeda

On Tue, Sep 9, 2025 at 7:01 PM Onur Özkan <work@onurozkan.dev> wrote:
>
> 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

I think Daniel asked in the previous version what you mean by "callers
that broke" here -- it is a bit confusing, since it seems this is a
fix (and thus needs to be prioritized).

Is that the case?

Thanks!

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-09 17:17   ` Miguel Ojeda
@ 2025-09-09 17:43     ` Onur Özkan
  2025-09-09 18:25       ` Onur
                         ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Onur Özkan @ 2025-09-09 17:43 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: rust-for-linux, linux-kernel, daniel, dirk.behme, felipe_life,
	tamird, dakr, tmgross, aliceryhl, a.hindborg, lossin, bjorn3_gh,
	gary, boqun.feng, alex.gaynor, ojeda

On Tue, 9 Sep 2025 19:17:56 +0200
Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote:

> On Tue, Sep 9, 2025 at 7:01 PM Onur Özkan <work@onurozkan.dev> wrote:
> >
> > 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
> 
> I think Daniel asked in the previous version what you mean by "callers
> that broke" here -- it is a bit confusing, since it seems this is a
> fix (and thus needs to be prioritized).
> 
> Is that the case?
> 
> Thanks!
> 
> Cheers,
> Miguel

What I meant is that the change on `to_result` signature introduced a
breaking change so I had to update its callers accordingly.

The fix I mentioned in this version is a different matter.

Before the rebase, the regulator module had a get_voltage function like
this:

	let voltage = unsafe {...};

	if voltage < 0 {
    		Err(...)
	} else {
    		Ok(Voltage::from_microvolts(voltage))
	}

But on the regulator/for-next branch, a patch was applied that changed
it to:

	let voltage = unsafe {...};
	to_result(voltage).map(|()| Voltage::from_microvolts(voltage))

That change was incompatible with v1 (due to the different signature of
to_result), which fails to build with my patch. This version (v2)
fixes the issue introduced in v1.

Sorry for the confusion, I hope it's more clear now.

Thanks,
Onur

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-09 17:43     ` Onur Özkan
@ 2025-09-09 18:25       ` Onur
  2025-09-09 18:25       ` Daniel Almeida
  2025-09-09 20:05       ` Miguel Ojeda
  2 siblings, 0 replies; 19+ messages in thread
From: Onur @ 2025-09-09 18:25 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: rust-for-linux, linux-kernel, daniel, dirk.behme, felipe_life,
	tamird, dakr, tmgross, aliceryhl, a.hindborg, lossin, bjorn3_gh,
	gary, boqun.feng, alex.gaynor, ojeda

On Tue, 9 Sep 2025 20:43:08 +0300
Onur Özkan <work@onurozkan.dev> wrote:

> On Tue, 9 Sep 2025 19:17:56 +0200
> Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote:
> 
> > On Tue, Sep 9, 2025 at 7:01 PM Onur Özkan <work@onurozkan.dev>
> > wrote:
> > >
> > > 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
> > 
> > I think Daniel asked in the previous version what you mean by
> > "callers that broke" here -- it is a bit confusing, since it seems
> > this is a fix (and thus needs to be prioritized).
> > 
> > Is that the case?
> > 
> > Thanks!
> > 
> > Cheers,
> > Miguel
> 
> What I meant is that the change on `to_result` signature introduced a
> breaking change so I had to update its callers accordingly.
> 
> The fix I mentioned in this version is a different matter.
> 
> Before the rebase, the regulator module had a get_voltage function
> like this:
> 
> 	let voltage = unsafe {...};
> 
> 	if voltage < 0 {
>     		Err(...)
> 	} else {
>     		Ok(Voltage::from_microvolts(voltage))
> 	}
> 
> But on the regulator/for-next branch, a patch was applied that changed
> it to:
> 
> 	let voltage = unsafe {...};
> 	to_result(voltage).map(|()| Voltage::from_microvolts(voltage))
> 
> That change was incompatible with v1 (due to the different signature
> of to_result), which fails to build with my patch. This version (v2)
> fixes the issue introduced in v1.
> 
> Sorry for the confusion, I hope it's more clear now.
> 
> Thanks,
> Onur

If I am not mistaken the way I prepared v2 is also not correct. I guess
the fix for regulator/for-next should be a separate patch.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  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:05       ` Miguel Ojeda
  2 siblings, 1 reply; 19+ messages in thread
From: Daniel Almeida @ 2025-09-09 18:25 UTC (permalink / raw)
  To: Onur Özkan
  Cc: Miguel Ojeda, rust-for-linux, linux-kernel, daniel, dirk.behme,
	felipe_life, tamird, dakr, tmgross, aliceryhl, a.hindborg, lossin,
	bjorn3_gh, gary, boqun.feng, alex.gaynor, ojeda

Onur,

> On 9 Sep 2025, at 14:43, Onur Özkan <work@onurozkan.dev> wrote:
> 
> On Tue, 9 Sep 2025 19:17:56 +0200
> Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote:
> 
>> On Tue, Sep 9, 2025 at 7:01 PM Onur Özkan <work@onurozkan.dev> wrote:
>>> 
>>> 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
>> 
>> I think Daniel asked in the previous version what you mean by "callers
>> that broke" here -- it is a bit confusing, since it seems this is a
>> fix (and thus needs to be prioritized).
>> 
>> Is that the case?
>> 
>> Thanks!
>> 
>> Cheers,
>> Miguel
> 
> What I meant is that the change on `to_result` signature introduced a
> breaking change so I had to update its callers accordingly.
> 
> The fix I mentioned in this version is a different matter.
> 
> Before the rebase, the regulator module had a get_voltage function like
> this:
> 
> let voltage = unsafe {...};
> 
> if voltage < 0 {
>     Err(...)
> } else {
>     Ok(Voltage::from_microvolts(voltage))
> }
> 
> But on the regulator/for-next branch, a patch was applied that changed
> it to:
> 
> let voltage = unsafe {...};
> to_result(voltage).map(|()| Voltage::from_microvolts(voltage))
> 
> That change was incompatible with v1 (due to the different signature of
> to_result), which fails to build with my patch. This version (v2)
> fixes the issue introduced in v1.

Fixes what issue? What is the actual problem being addressed here?

It looks like a mere change from

to_result(…) and,
to_result(…).map()

To:

to_result(…)?;
Ok(())

and

-        let voltage = unsafe { bindings::regulator_get_voltage(self.inner.as_ptr()) };
-
-        to_result(voltage).map(|()| Voltage::from_microvolts(voltage))
+        to_result(unsafe { bindings::regulator_get_voltage(self.inner.as_ptr()) })
+            .map(Voltage::from_microvolts)
    }


> 
> Sorry for the confusion, I hope it's more clear now.
> 
> Thanks,
> Onur
> 

Your last regulator patch was minor, correct, and was picked up (merged). It
cleared up an if/else, so that was an improvement.

I now see yet another change, doing apparently the same thing (correct me if
I’m wrong) in a slightly different way, in a patch that now has your previous regulator
patch as a dependency.

So my question is, why do we need this?

diff --git a/rust/kernel/regulator.rsb/rust/kernel/regulator.rs
index 34bb24ec8d4d..a5f357bda6e9 100644
--- a/rust/kernel/regulator.rs
+++ b/rust/kernel/regulator.rs
@@ -260,15 +260,15 @@ pub fn set_voltage(&self, min_voltage: Voltage, max_voltage: Voltage) -> Result
                min_voltage.as_microvolts(),
                max_voltage.as_microvolts(),
            )
-        })
+        })?;
+        Ok(())
    }

    /// Gets the current voltage of the regulator.
    pub fn get_voltage(&self) -> Result<Voltage> {
        // SAFETY: Safe as per the type invariants of `Regulator`.
-        let voltage = unsafe { bindings::regulator_get_voltage(self.inner.as_ptr()) };
-
-        to_result(voltage).map(|()| Voltage::from_microvolts(voltage))
+        to_result(unsafe { bindings::regulator_get_voltage(self.inner.as_ptr()) })
+            .map(Voltage::from_microvolts)
    }

    fn get_internal(dev: &Device, name: &CStr) -> Result<Regulator<T>> {
@@ -288,12 +288,14 @@ fn get_internal(dev: &Device, name: &CStr) -> Result<Regulator<T>> {

    fn enable_internal(&self) -> Result {
        // SAFETY: Safe as per the type invariants of `Regulator`.
-        to_result(unsafe { bindings::regulator_enable(self.inner.as_ptr()) })
+        to_result(unsafe { bindings::regulator_enable(self.inner.as_ptr()) })?;
+        Ok(())
    }

    fn disable_internal(&self) -> Result {
        // SAFETY: Safe as per the type invariants of `Regulator`.
-        to_result(unsafe { bindings::regulator_disable(self.inner.as_ptr()) })
+        to_result(unsafe { bindings::regulator_disable(self.inner.as_ptr()) })?;
+        Ok(())
    }


— Daniel

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-09 18:25       ` Daniel Almeida
@ 2025-09-09 18:53         ` Onur Özkan
  2025-09-09 20:13           ` Daniel Almeida
  0 siblings, 1 reply; 19+ messages in thread
From: Onur Özkan @ 2025-09-09 18:53 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Miguel Ojeda, rust-for-linux, linux-kernel, daniel, dirk.behme,
	felipe_life, tamird, dakr, tmgross, aliceryhl, a.hindborg, lossin,
	bjorn3_gh, gary, boqun.feng, alex.gaynor, ojeda

On Tue, 9 Sep 2025 15:25:55 -0300
Daniel Almeida <daniel.almeida@collabora.com> wrote:

> Onur,
> 
> > On 9 Sep 2025, at 14:43, Onur Özkan <work@onurozkan.dev> wrote:
> > 
> > On Tue, 9 Sep 2025 19:17:56 +0200
> > Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote:
> > 
> >> On Tue, Sep 9, 2025 at 7:01 PM Onur Özkan <work@onurozkan.dev>
> >> wrote:
> >>> 
> >>> 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
> >> 
> >> I think Daniel asked in the previous version what you mean by
> >> "callers that broke" here -- it is a bit confusing, since it seems
> >> this is a fix (and thus needs to be prioritized).
> >> 
> >> Is that the case?
> >> 
> >> Thanks!
> >> 
> >> Cheers,
> >> Miguel
> > 
> > What I meant is that the change on `to_result` signature introduced
> > a breaking change so I had to update its callers accordingly.
> > 
> > The fix I mentioned in this version is a different matter.
> > 
> > Before the rebase, the regulator module had a get_voltage function
> > like this:
> > 
> > let voltage = unsafe {...};
> > 
> > if voltage < 0 {
> >     Err(...)
> > } else {
> >     Ok(Voltage::from_microvolts(voltage))
> > }
> > 
> > But on the regulator/for-next branch, a patch was applied that
> > changed it to:
> > 
> > let voltage = unsafe {...};
> > to_result(voltage).map(|()| Voltage::from_microvolts(voltage))
> > 
> > That change was incompatible with v1 (due to the different
> > signature of to_result), which fails to build with my patch. This
> > version (v2) fixes the issue introduced in v1.
> 
> Fixes what issue? What is the actual problem being addressed here?
> 
> It looks like a mere change from
> 
> to_result(…) and,
> to_result(…).map()
> 
> To:
> 
> to_result(…)?;
> Ok(())
> 
> and
> 
> -        let voltage = unsafe {
> bindings::regulator_get_voltage(self.inner.as_ptr()) }; -
> -        to_result(voltage).map(|()|
> Voltage::from_microvolts(voltage))
> +        to_result(unsafe {
> bindings::regulator_get_voltage(self.inner.as_ptr()) })
> +            .map(Voltage::from_microvolts)
>     }
> 
> 
> > 
> > Sorry for the confusion, I hope it's more clear now.
> > 
> > Thanks,
> > Onur
> > 
> 
> Your last regulator patch was minor, correct, and was picked up
> (merged). It cleared up an if/else, so that was an improvement.
> 
> I now see yet another change, doing apparently the same thing
> (correct me if I’m wrong) in a slightly different way, in a patch
> that now has your previous regulator patch as a dependency.
> 
> So my question is, why do we need this?
>


If you look at the changes in rust/kernel/error.rs, you will see that
the `to_result` function has been modified and some of its callers were
updated because the function signature changed.

The regulator patch I sent earlier is unrelated to this one. They are
not doing the same thing. That patch aimed to make use of `to_result`
instead of handling errors manually. This patch on the other hand,
changes how `to_result` itself works and some of its callers need to be
updated accordingly just like in the other modules included here. The
reason for changing the `to_result` function is explained in the commit
description.

-Onur 


> diff --git a/rust/kernel/regulator.rsb/rust/kernel/regulator.rs
> index 34bb24ec8d4d..a5f357bda6e9 100644
> --- a/rust/kernel/regulator.rs
> +++ b/rust/kernel/regulator.rs
> @@ -260,15 +260,15 @@ pub fn set_voltage(&self, min_voltage: Voltage,
> max_voltage: Voltage) -> Result min_voltage.as_microvolts(),
>                 max_voltage.as_microvolts(),
>             )
> -        })
> +        })?;
> +        Ok(())
>     }
> 
>     /// Gets the current voltage of the regulator.
>     pub fn get_voltage(&self) -> Result<Voltage> {
>         // SAFETY: Safe as per the type invariants of `Regulator`.
> -        let voltage = unsafe {
> bindings::regulator_get_voltage(self.inner.as_ptr()) }; -
> -        to_result(voltage).map(|()|
> Voltage::from_microvolts(voltage))
> +        to_result(unsafe {
> bindings::regulator_get_voltage(self.inner.as_ptr()) })
> +            .map(Voltage::from_microvolts)
>     }
> 
>     fn get_internal(dev: &Device, name: &CStr) ->
> Result<Regulator<T>> { @@ -288,12 +288,14 @@ fn get_internal(dev:
> &Device, name: &CStr) -> Result<Regulator<T>> {
> 
>     fn enable_internal(&self) -> Result {
>         // SAFETY: Safe as per the type invariants of `Regulator`.
> -        to_result(unsafe {
> bindings::regulator_enable(self.inner.as_ptr()) })
> +        to_result(unsafe {
> bindings::regulator_enable(self.inner.as_ptr()) })?;
> +        Ok(())
>     }
> 
>     fn disable_internal(&self) -> Result {
>         // SAFETY: Safe as per the type invariants of `Regulator`.
> -        to_result(unsafe {
> bindings::regulator_disable(self.inner.as_ptr()) })
> +        to_result(unsafe {
> bindings::regulator_disable(self.inner.as_ptr()) })?;
> +        Ok(())
>     }
> 
> 
> — Daniel

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-09 17:43     ` Onur Özkan
  2025-09-09 18:25       ` Onur
  2025-09-09 18:25       ` Daniel Almeida
@ 2025-09-09 20:05       ` Miguel Ojeda
  2025-09-09 20:12         ` Daniel Almeida
  2025-09-10  4:50         ` Onur Özkan
  2 siblings, 2 replies; 19+ messages in thread
From: Miguel Ojeda @ 2025-09-09 20:05 UTC (permalink / raw)
  To: Onur Özkan
  Cc: rust-for-linux, linux-kernel, daniel, dirk.behme, felipe_life,
	tamird, dakr, tmgross, aliceryhl, a.hindborg, lossin, bjorn3_gh,
	gary, boqun.feng, alex.gaynor, ojeda

On Tue, Sep 9, 2025 at 7:43 PM Onur Özkan <work@onurozkan.dev> wrote:
>
> That change was incompatible with v1 (due to the different signature of
> to_result), which fails to build with my patch. This version (v2)
> fixes the issue introduced in v1.

In that case, please try to avoid mentioning "broken" or "fix" or
similar, i.e. there is nothing broken in the tree itself (the commit
message should mention what is done in the patch). If you want to give
extra clarifications, then you can always add them outside the commit
message, below the `---` line.

In addition, if the changes here are required to be done all at once,
then please do not rebase on top of regulator -- this would need to go
into the global Rust tree. Otherwise, any changes that does not need
to go at the same time should go separately so that it is easier to
land.

Finally, I am not sure I follow the `unwrap_or(0)` here. If one passes
a negative enough `i64`, wouldn't that mean `Ok` starts to be
returned? Currently all negatives that are not codes are supposed to
be bugs.

Either way, I think this should probably go on top of
https://lore.kernel.org/rust-for-linux/20250829192243.678079-3-ojeda@kernel.org/,
since that adds documentation, and thus it would be nice to adjust
that one to whatever the generic one should do now, especially if the
semantics are changing.

Thanks!

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  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
  1 sibling, 1 reply; 19+ messages in thread
From: Daniel Almeida @ 2025-09-09 20:12 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Onur Özkan, rust-for-linux, linux-kernel, daniel, dirk.behme,
	felipe_life, tamird, dakr, tmgross, aliceryhl, a.hindborg, lossin,
	bjorn3_gh, gary, boqun.feng, alex.gaynor, ojeda



> On 9 Sep 2025, at 17:05, Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote:
> 
> On Tue, Sep 9, 2025 at 7:43 PM Onur Özkan <work@onurozkan.dev> wrote:
>> 
>> That change was incompatible with v1 (due to the different signature of
>> to_result), which fails to build with my patch. This version (v2)
>> fixes the issue introduced in v1.
> 
> In that case, please try to avoid mentioning "broken" or "fix" or
> similar, i.e. there is nothing broken in the tree itself (the commit
> message should mention what is done in the patch). If you want to give
> extra clarifications, then you can always add them outside the commit
> message, below the `---` line.
> 
> In addition, if the changes here are required to be done all at once,
> then please do not rebase on top of regulator -- this would need to go

Merely rebasing on top of the rust tree will crate a conflict with his previous regulator patch.

My suggestion is to just wait for rc1.

> into the global Rust tree. Otherwise, any changes that does not need
> to go at the same time should go separately so that it is easier to
> land.
> 
> Finally, I am not sure I follow the `unwrap_or(0)` here. If one passes
> a negative enough `i64`, wouldn't that mean `Ok` starts to be
> returned? Currently all negatives that are not codes are supposed to
> be bugs.
> 
> Either way, I think this should probably go on top of
> https://lore.kernel.org/rust-for-linux/20250829192243.678079-3-ojeda@kernel.org/,
> since that adds documentation, and thus it would be nice to adjust
> that one to whatever the generic one should do now, especially if the
> semantics are changing.
> 
> Thanks!
> 
> Cheers,
> Miguel
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-09 18:53         ` Onur Özkan
@ 2025-09-09 20:13           ` Daniel Almeida
  0 siblings, 0 replies; 19+ messages in thread
From: Daniel Almeida @ 2025-09-09 20:13 UTC (permalink / raw)
  To: Onur Özkan
  Cc: Miguel Ojeda, rust-for-linux, linux-kernel, daniel, dirk.behme,
	felipe_life, tamird, dakr, tmgross, aliceryhl, a.hindborg, lossin,
	bjorn3_gh, gary, boqun.feng, alex.gaynor, ojeda

[…]

> If you look at the changes in rust/kernel/error.rs, you will see that
> the `to_result` function has been modified and some of its callers were
> updated because the function signature changed.
> 
> The regulator patch I sent earlier is unrelated to this one. They are
> not doing the same thing. That patch aimed to make use of `to_result`

This is the piece of information I was missing, thanks.

> instead of handling errors manually. This patch on the other hand,
> changes how `to_result` itself works and some of its callers need to be
> updated accordingly just like in the other modules included here. The
> reason for changing the `to_result` function is explained in the commit
> description.
> 
> -Onur 

— Daniel

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-09 20:12         ` Daniel Almeida
@ 2025-09-09 20:25           ` Miguel Ojeda
  0 siblings, 0 replies; 19+ messages in thread
From: Miguel Ojeda @ 2025-09-09 20:25 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Onur Özkan, rust-for-linux, linux-kernel, daniel, dirk.behme,
	felipe_life, tamird, dakr, tmgross, aliceryhl, a.hindborg, lossin,
	bjorn3_gh, gary, boqun.feng, alex.gaynor, ojeda

On Tue, Sep 9, 2025 at 10:12 PM Daniel Almeida
<daniel.almeida@collabora.com> wrote:
>
> Merely rebasing on top of the rust tree will crate a conflict with his previous regulator patch.
>
> My suggestion is to just wait for rc1.

Yes, but note that conflicts may happen either way, i.e. for treewide
patches like this, one may get other code landing that may also need
changing. If what you want is to try to catch as many as those as
possible, then it may be best checking -next.

In any case, I would like to see this on top of the patch adding
documentation I linked, so that we can clearly discuss the intended
semantics, because this is changing them for bigger types.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-09 20:05       ` Miguel Ojeda
  2025-09-09 20:12         ` Daniel Almeida
@ 2025-09-10  4:50         ` Onur Özkan
  1 sibling, 0 replies; 19+ messages in thread
From: Onur Özkan @ 2025-09-10  4:50 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: rust-for-linux, linux-kernel, daniel, dirk.behme, felipe_life,
	tamird, dakr, tmgross, aliceryhl, a.hindborg, lossin, bjorn3_gh,
	gary, boqun.feng, alex.gaynor, ojeda

On Tue, 9 Sep 2025 22:05:53 +0200
Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote:

> On Tue, Sep 9, 2025 at 7:43 PM Onur Özkan <work@onurozkan.dev> wrote:
> >
> > That change was incompatible with v1 (due to the different
> > signature of to_result), which fails to build with my patch. This
> > version (v2) fixes the issue introduced in v1.
> 
> In that case, please try to avoid mentioning "broken" or "fix" or
> similar, i.e. there is nothing broken in the tree itself (the commit
> message should mention what is done in the patch). If you want to give
> extra clarifications, then you can always add them outside the commit
> message, below the `---` line.
> 
> In addition, if the changes here are required to be done all at once,
> then please do not rebase on top of regulator -- this would need to go
> into the global Rust tree. Otherwise, any changes that does not need
> to go at the same time should go separately so that it is easier to
> land.
> 
> Finally, I am not sure I follow the `unwrap_or(0)` here. If one passes
> a negative enough `i64`, wouldn't that mean `Ok` starts to be
> returned? Currently all negatives that are not codes are supposed to
> be bugs.
> 

I think the best approach would be to return `EINVAL` from `to_result`,
what do yo think?

> Either way, I think this should probably go on top of
> https://lore.kernel.org/rust-for-linux/20250829192243.678079-3-ojeda@kernel.org/,
> since that adds documentation, and thus it would be nice to adjust
> that one to whatever the generic one should do now, especially if the
> semantics are changing.
> 
> Thanks!
> 
> Cheers,
> Miguel

I will do that in v3.

Thanks,
Onur

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-09 17:00 ` [PATCH v2 1/1] " Onur Özkan
  2025-09-09 17:17   ` Miguel Ojeda
@ 2025-09-10  6:26   ` Alice Ryhl
  2025-09-10 10:58     ` Onur Özkan
  2025-09-12  8:41   ` kernel test robot
  2 siblings, 1 reply; 19+ messages in thread
From: Alice Ryhl @ 2025-09-10  6:26 UTC (permalink / raw)
  To: Onur Özkan
  Cc: rust-for-linux, linux-kernel, daniel, dirk.behme, felipe_life,
	tamird, dakr, tmgross, a.hindborg, lossin, bjorn3_gh, gary,
	boqun.feng, alex.gaynor, ojeda

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

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-10  6:26   ` Alice Ryhl
@ 2025-09-10 10:58     ` Onur Özkan
  2025-09-10 11:05       ` Alice Ryhl
  0 siblings, 1 reply; 19+ messages in thread
From: Onur Özkan @ 2025-09-10 10:58 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: rust-for-linux, linux-kernel, daniel, dirk.behme, felipe_life,
	tamird, dakr, tmgross, a.hindborg, lossin, bjorn3_gh, gary,
	boqun.feng, alex.gaynor, ojeda

On Wed, 10 Sep 2025 06:26:27 +0000
Alice Ryhl <aliceryhl@google.com> wrote:

> 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)
> }
> 

`Error::from_errno` is limited to i32, that's why I followed the
`TryInto<i32>` approach, but I like this design too.

> > 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


I left that part intentionally and explained the reason in v2 changelog.

Thanks,
Onur

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-10 10:58     ` Onur Özkan
@ 2025-09-10 11:05       ` Alice Ryhl
  2025-09-10 12:47         ` Onur Özkan
  0 siblings, 1 reply; 19+ messages in thread
From: Alice Ryhl @ 2025-09-10 11:05 UTC (permalink / raw)
  To: Onur Özkan
  Cc: rust-for-linux, linux-kernel, daniel, dirk.behme, felipe_life,
	tamird, dakr, tmgross, a.hindborg, lossin, bjorn3_gh, gary,
	boqun.feng, alex.gaynor, ojeda

On Wed, Sep 10, 2025 at 12:59 PM Onur Özkan <work@onurozkan.dev> wrote:
>
> On Wed, 10 Sep 2025 06:26:27 +0000
> Alice Ryhl <aliceryhl@google.com> wrote:
>
> > 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)
> > }
> >
>
> `Error::from_errno` is limited to i32, that's why I followed the
> `TryInto<i32>` approach, but I like this design too.

If you pass an i32 that is not a valid errno, then it becomes EINVAL.
In the case of `isize`, I would say that if a negative isize does not
fit in i32, then that should fall into the same scenario.


> > > 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
>
>
> I left that part intentionally and explained the reason in v2 changelog.

I missed that, ok. I still prefer Ok::<...>()

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-10 11:05       ` Alice Ryhl
@ 2025-09-10 12:47         ` Onur Özkan
  2025-09-10 12:50           ` Alice Ryhl
  0 siblings, 1 reply; 19+ messages in thread
From: Onur Özkan @ 2025-09-10 12:47 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: rust-for-linux, linux-kernel, daniel, dirk.behme, felipe_life,
	tamird, dakr, tmgross, a.hindborg, lossin, bjorn3_gh, gary,
	boqun.feng, alex.gaynor, ojeda

On Wed, 10 Sep 2025 13:05:42 +0200
Alice Ryhl <aliceryhl@google.com> wrote:

> On Wed, Sep 10, 2025 at 12:59 PM Onur Özkan <work@onurozkan.dev>
> wrote:
> >
> > On Wed, 10 Sep 2025 06:26:27 +0000
> > Alice Ryhl <aliceryhl@google.com> wrote:
> >
> > > 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)
> > > }
> > >
> >
> > `Error::from_errno` is limited to i32, that's why I followed the
> > `TryInto<i32>` approach, but I like this design too.
> 
> If you pass an i32 that is not a valid errno, then it becomes EINVAL.
> In the case of `isize`, I would say that if a negative isize does not
> fit in i32, then that should fall into the same scenario.
> 

In that case replacing `unwrap_or(0)` with `map_err(|_| code::EINVAL)`
should do the job?

I also thought of an alternative to the custom-trait–based approach.
What do you think about something like this:

    pub fn to_result<T, R>(code: T) -> Result<R>
    where
        T: Copy + TryInto<i32> + TryInto<R>,
    {
        // Try casting into `i32`.
        let casted: crate::ffi::c_int = code.try_into().map_err(|_|
    code::EINVAL)?;

        if casted < 0 {
            Err(Error::from_errno(casted))
        } else {
            // Return the original input value as `R`.
            code.try_into().map_err(|_| code::EINVAL)
        }
    }


On the caller side, it would look like this:

    let val: u16 = to_result(...)?;

The main difference here is that this version can be used to cast into
multiple different types, not just `i32 -> u32` or `i64 -> u64`.

Regards,
Onur

> 
> > > > 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
> >
> >
> > I left that part intentionally and explained the reason in v2
> > changelog.
> 
> I missed that, ok. I still prefer Ok::<...>()


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-10 12:47         ` Onur Özkan
@ 2025-09-10 12:50           ` Alice Ryhl
  2025-09-10 12:55             ` Onur Özkan
  0 siblings, 1 reply; 19+ messages in thread
From: Alice Ryhl @ 2025-09-10 12:50 UTC (permalink / raw)
  To: Onur Özkan
  Cc: rust-for-linux, linux-kernel, daniel, dirk.behme, felipe_life,
	tamird, dakr, tmgross, a.hindborg, lossin, bjorn3_gh, gary,
	boqun.feng, alex.gaynor, ojeda

On Wed, Sep 10, 2025 at 2:47 PM Onur Özkan <work@onurozkan.dev> wrote:
>
> On Wed, 10 Sep 2025 13:05:42 +0200
> Alice Ryhl <aliceryhl@google.com> wrote:
>
> > On Wed, Sep 10, 2025 at 12:59 PM Onur Özkan <work@onurozkan.dev>
> > wrote:
> > >
> > > On Wed, 10 Sep 2025 06:26:27 +0000
> > > Alice Ryhl <aliceryhl@google.com> wrote:
> > >
> > > > 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)
> > > > }
> > > >
> > >
> > > `Error::from_errno` is limited to i32, that's why I followed the
> > > `TryInto<i32>` approach, but I like this design too.
> >
> > If you pass an i32 that is not a valid errno, then it becomes EINVAL.
> > In the case of `isize`, I would say that if a negative isize does not
> > fit in i32, then that should fall into the same scenario.
> >
>
> In that case replacing `unwrap_or(0)` with `map_err(|_| code::EINVAL)`
> should do the job?
>
> I also thought of an alternative to the custom-trait–based approach.
> What do you think about something like this:
>
>     pub fn to_result<T, R>(code: T) -> Result<R>
>     where
>         T: Copy + TryInto<i32> + TryInto<R>,
>     {
>         // Try casting into `i32`.
>         let casted: crate::ffi::c_int = code.try_into().map_err(|_|
>     code::EINVAL)?;
>
>         if casted < 0 {
>             Err(Error::from_errno(casted))
>         } else {
>             // Return the original input value as `R`.
>             code.try_into().map_err(|_| code::EINVAL)
>         }
>     }
>
>
> On the caller side, it would look like this:
>
>     let val: u16 = to_result(...)?;
>
> The main difference here is that this version can be used to cast into
> multiple different types, not just `i32 -> u32` or `i64 -> u64`.

I think making the return type a separate generic makes this too
difficult to use. It means that any time you would write this:

to_result(unsafe { ... })?;
Ok(())

now you need to tell the compiler what kind of integer you want to get
from to_result, just so you can immediately ignore the integer.

Alice

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-10 12:50           ` Alice Ryhl
@ 2025-09-10 12:55             ` Onur Özkan
  0 siblings, 0 replies; 19+ messages in thread
From: Onur Özkan @ 2025-09-10 12:55 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: rust-for-linux, linux-kernel, daniel, dirk.behme, felipe_life,
	tamird, dakr, tmgross, a.hindborg, lossin, bjorn3_gh, gary,
	boqun.feng, alex.gaynor, ojeda

On Wed, 10 Sep 2025 14:50:03 +0200
Alice Ryhl <aliceryhl@google.com> wrote:

> On Wed, Sep 10, 2025 at 2:47 PM Onur Özkan <work@onurozkan.dev> wrote:
> >
> > On Wed, 10 Sep 2025 13:05:42 +0200
> > Alice Ryhl <aliceryhl@google.com> wrote:
> >
> > > On Wed, Sep 10, 2025 at 12:59 PM Onur Özkan <work@onurozkan.dev>
> > > wrote:
> > > >
> > > > On Wed, 10 Sep 2025 06:26:27 +0000
> > > > Alice Ryhl <aliceryhl@google.com> wrote:
> > > >
> > > > > 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)
> > > > > }
> > > > >
> > > >
> > > > `Error::from_errno` is limited to i32, that's why I followed the
> > > > `TryInto<i32>` approach, but I like this design too.
> > >
> > > If you pass an i32 that is not a valid errno, then it becomes
> > > EINVAL. In the case of `isize`, I would say that if a negative
> > > isize does not fit in i32, then that should fall into the same
> > > scenario.
> > >
> >
> > In that case replacing `unwrap_or(0)` with `map_err(|_|
> > code::EINVAL)` should do the job?
> >
> > I also thought of an alternative to the custom-trait–based approach.
> > What do you think about something like this:
> >
> >     pub fn to_result<T, R>(code: T) -> Result<R>
> >     where
> >         T: Copy + TryInto<i32> + TryInto<R>,
> >     {
> >         // Try casting into `i32`.
> >         let casted: crate::ffi::c_int = code.try_into().map_err(|_|
> >     code::EINVAL)?;
> >
> >         if casted < 0 {
> >             Err(Error::from_errno(casted))
> >         } else {
> >             // Return the original input value as `R`.
> >             code.try_into().map_err(|_| code::EINVAL)
> >         }
> >     }
> >
> >
> > On the caller side, it would look like this:
> >
> >     let val: u16 = to_result(...)?;
> >
> > The main difference here is that this version can be used to cast
> > into multiple different types, not just `i32 -> u32` or `i64 ->
> > u64`.
> 
> I think making the return type a separate generic makes this too
> difficult to use. It means that any time you would write this:
> 
> to_result(unsafe { ... })?;
> Ok(())
> 
> now you need to tell the compiler what kind of integer you want to get
> from to_result, just so you can immediately ignore the integer.
> 
> Alice

Yes, and with the custom trait you need to import it in order to use
the `to_result` helper. I don't have a strong preference either way.
I guess I will wait a couple of days to get more feedback from others
as well. Thank you for your quick feedback and review so far!

-Onur

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/1] rust: refactor to_result to return the original value
  2025-09-09 17:00 ` [PATCH v2 1/1] " Onur Özkan
  2025-09-09 17:17   ` Miguel Ojeda
  2025-09-10  6:26   ` Alice Ryhl
@ 2025-09-12  8:41   ` kernel test robot
  2 siblings, 0 replies; 19+ messages in thread
From: kernel test robot @ 2025-09-12  8:41 UTC (permalink / raw)
  To: Onur Özkan, rust-for-linux
  Cc: llvm, oe-kbuild-all, linux-kernel, daniel, dirk.behme,
	felipe_life, tamird, dakr, tmgross, aliceryhl, a.hindborg, lossin,
	bjorn3_gh, gary, boqun.feng, alex.gaynor, ojeda, Onur Özkan

Hi Onur,

kernel test robot noticed the following build errors:

[auto build test ERROR on broonie-regulator/for-next]
[cannot apply to driver-core/driver-core-testing driver-core/driver-core-next driver-core/driver-core-linus rafael-pm/linux-next rafael-pm/bleeding-edge rust/alloc-next rust/rust-next char-misc/char-misc-testing char-misc/char-misc-next char-misc/char-misc-linus akpm-mm/mm-everything pci/next pci/for-linus rust/rust-block-next linus/master v6.17-rc5 next-20250912]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Onur-zkan/rust-refactor-to_result-to-return-the-original-value/20250910-010803
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next
patch link:    https://lore.kernel.org/r/20250909170013.16025-2-work%40onurozkan.dev
patch subject: [PATCH v2 1/1] rust: refactor to_result to return the original value
config: x86_64-rhel-9.4-rust (https://download.01.org/0day-ci/archive/20250912/202509121607.yxpZ3HBS-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
rustc: rustc 1.88.0 (6b00bc388 2025-06-23)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250912/202509121607.yxpZ3HBS-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509121607.yxpZ3HBS-lkp@intel.com/

All errors (new ones prefixed by >>):

>> error[E0277]: the trait bound `i32: From<()>` is not satisfied
   --> rust/kernel/configfs.rs:181:17
   |
>> 179 |             crate::error::to_result(
   |             ----------------------- required by a bound introduced by this call
   180 |                 // SAFETY: We initialized `this.subsystem` according to C API contract above.
   181 |                 unsafe { bindings::configfs_register_subsystem(this.subsystem.get()) },
   |                 ^^^^^^^^^-----------------------------------------------------------^^
   |                 |        |
   |                 |        this tail expression is of type `i32`
   |                 the trait `From<()>` is not implemented for `i32`
   |
   = help: the following other types implement trait `From<T>`:
   `i32` implements `From<CpuId>`
   `i32` implements `From<bool>`
   `i32` implements `From<i16>`
   `i32` implements `From<i8>`
   `i32` implements `From<u16>`
   `i32` implements `From<u8>`
   = note: required for `()` to implement `Into<i32>`
   = note: required for `i32` to implement `TryFrom<()>`
   = note: required for `()` to implement `TryInto<i32>`
   note: required by a bound in `error::to_result`
   --> rust/kernel/error.rs:382:15
   |
   380 | pub fn to_result<T>(code: T) -> Result<T>
   |        --------- required by a bound in this function
   381 | where
   382 |     T: Copy + TryInto<i32>,
   |               ^^^^^^^^^^^^ required by this bound in `to_result`
--
>> error[E0277]: the trait bound `i32: From<()>` is not satisfied
   --> rust/kernel/net/phy/reg.rs:122:19
   |
   122 |           to_result(unsafe {
   |  _________---------_^
   | |         |
   | |         required by a bound introduced by this call
   123 | |             bindings::mdiobus_write((*phydev).mdio.bus, (*phydev).mdio.addr, self.0.into(), val)
   | |             ------------------------------------------------------------------------------------ this tail expression is of type `i32`
   124 | |         })
   | |_________^ the trait `From<()>` is not implemented for `i32`
   |
   = help: the following other types implement trait `From<T>`:
   `i32` implements `From<CpuId>`
   `i32` implements `From<bool>`
   `i32` implements `From<i16>`
   `i32` implements `From<i8>`
   `i32` implements `From<u16>`
   `i32` implements `From<u8>`
   = note: required for `()` to implement `Into<i32>`
   = note: required for `i32` to implement `TryFrom<()>`
   = note: required for `()` to implement `TryInto<i32>`
   note: required by a bound in `error::to_result`
   --> rust/kernel/error.rs:382:15
   |
   380 | pub fn to_result<T>(code: T) -> Result<T>
   |        --------- required by a bound in this function
   381 | where
   382 |     T: Copy + TryInto<i32>,
   |               ^^^^^^^^^^^^ required by this bound in `to_result`
--
>> error[E0277]: the trait bound `i32: From<()>` is not satisfied
   --> rust/kernel/net/phy/reg.rs:211:19
   |
   211 |           to_result(unsafe {
   |  _________---------_^
   | |         |
   | |         required by a bound introduced by this call
   212 | |             bindings::phy_write_mmd(phydev, self.devad.0.into(), self.regnum.into(), val)
   | |             ----------------------------------------------------------------------------- this tail expression is of type `i32`
   213 | |         })
   | |_________^ the trait `From<()>` is not implemented for `i32`
   |
   = help: the following other types implement trait `From<T>`:
   `i32` implements `From<CpuId>`
   `i32` implements `From<bool>`
   `i32` implements `From<i16>`
   `i32` implements `From<i8>`
   `i32` implements `From<u16>`
   `i32` implements `From<u8>`
   = note: required for `()` to implement `Into<i32>`
   = note: required for `i32` to implement `TryFrom<()>`
   = note: required for `()` to implement `TryInto<i32>`
   note: required by a bound in `error::to_result`
   --> rust/kernel/error.rs:382:15
   |
   380 | pub fn to_result<T>(code: T) -> Result<T>
   |        --------- required by a bound in this function
   381 | where
   382 |     T: Copy + TryInto<i32>,
   |               ^^^^^^^^^^^^ required by this bound in `to_result`
--
>> error[E0277]: the trait bound `i32: From<()>` is not satisfied
   --> rust/kernel/net/phy.rs:219:19
   |
   219 |         to_result(unsafe { bindings::genphy_soft_reset(phydev) })
   |         --------- ^^^^^^^^^-----------------------------------^^
   |         |         |        |
   |         |         |        this tail expression is of type `i32`
   |         |         the trait `From<()>` is not implemented for `i32`
   |         required by a bound introduced by this call
   |
   = help: the following other types implement trait `From<T>`:
   `i32` implements `From<CpuId>`
   `i32` implements `From<bool>`
   `i32` implements `From<i16>`
   `i32` implements `From<i8>`
   `i32` implements `From<u16>`
   `i32` implements `From<u8>`
   = note: required for `()` to implement `Into<i32>`
   = note: required for `i32` to implement `TryFrom<()>`
   = note: required for `()` to implement `TryInto<i32>`
   note: required by a bound in `error::to_result`
   --> rust/kernel/error.rs:382:15
   |
   380 | pub fn to_result<T>(code: T) -> Result<T>
   |        --------- required by a bound in this function
   381 | where
   382 |     T: Copy + TryInto<i32>,
   |               ^^^^^^^^^^^^ required by this bound in `to_result`
--
>> error[E0277]: the trait bound `i32: From<()>` is not satisfied
   --> rust/kernel/net/phy.rs:227:19
   |
   227 |         to_result(unsafe { bindings::phy_init_hw(phydev) })
   |         --------- ^^^^^^^^^-----------------------------^^
   |         |         |        |
   |         |         |        this tail expression is of type `i32`
   |         |         the trait `From<()>` is not implemented for `i32`
   |         required by a bound introduced by this call
   |
   = help: the following other types implement trait `From<T>`:
   `i32` implements `From<CpuId>`
   `i32` implements `From<bool>`
   `i32` implements `From<i16>`
   `i32` implements `From<i8>`
   `i32` implements `From<u16>`
   `i32` implements `From<u8>`
   = note: required for `()` to implement `Into<i32>`
   = note: required for `i32` to implement `TryFrom<()>`
   = note: required for `()` to implement `TryInto<i32>`
   note: required by a bound in `error::to_result`
   --> rust/kernel/error.rs:382:15
   |
   380 | pub fn to_result<T>(code: T) -> Result<T>
   |        --------- required by a bound in this function
   381 | where
   382 |     T: Copy + TryInto<i32>,
   |               ^^^^^^^^^^^^ required by this bound in `to_result`
--
>> error[E0277]: the trait bound `i32: From<()>` is not satisfied
   --> rust/kernel/net/phy.rs:235:19
   |
   235 |         to_result(unsafe { bindings::_phy_start_aneg(phydev) })
   |         --------- ^^^^^^^^^---------------------------------^^
   |         |         |        |
   |         |         |        this tail expression is of type `i32`
   |         |         the trait `From<()>` is not implemented for `i32`
   |         required by a bound introduced by this call
   |
   = help: the following other types implement trait `From<T>`:
   `i32` implements `From<CpuId>`
   `i32` implements `From<bool>`
   `i32` implements `From<i16>`
   `i32` implements `From<i8>`
   `i32` implements `From<u16>`
   `i32` implements `From<u8>`
   = note: required for `()` to implement `Into<i32>`
   = note: required for `i32` to implement `TryFrom<()>`
   = note: required for `()` to implement `TryInto<i32>`
   note: required by a bound in `error::to_result`
   --> rust/kernel/error.rs:382:15
   |
   380 | pub fn to_result<T>(code: T) -> Result<T>
   |        --------- required by a bound in this function
   381 | where
   382 |     T: Copy + TryInto<i32>,
   |               ^^^^^^^^^^^^ required by this bound in `to_result`
--
>> error[E0277]: the trait bound `i32: From<()>` is not satisfied
   --> rust/kernel/net/phy.rs:243:19
   |
   243 |         to_result(unsafe { bindings::genphy_resume(phydev) })
   |         --------- ^^^^^^^^^-------------------------------^^
   |         |         |        |
   |         |         |        this tail expression is of type `i32`
   |         |         the trait `From<()>` is not implemented for `i32`
   |         required by a bound introduced by this call
   |
   = help: the following other types implement trait `From<T>`:
   `i32` implements `From<CpuId>`
   `i32` implements `From<bool>`
   `i32` implements `From<i16>`
   `i32` implements `From<i8>`
   `i32` implements `From<u16>`
   `i32` implements `From<u8>`
   = note: required for `()` to implement `Into<i32>`
   = note: required for `i32` to implement `TryFrom<()>`
   = note: required for `()` to implement `TryInto<i32>`
   note: required by a bound in `error::to_result`
   --> rust/kernel/error.rs:382:15
   |
   380 | pub fn to_result<T>(code: T) -> Result<T>
   |        --------- required by a bound in this function
   381 | where
   382 |     T: Copy + TryInto<i32>,
   |               ^^^^^^^^^^^^ required by this bound in `to_result`
--
>> error[E0277]: the trait bound `i32: From<()>` is not satisfied
   --> rust/kernel/net/phy.rs:251:19
   |
   251 |         to_result(unsafe { bindings::genphy_suspend(phydev) })
   |         --------- ^^^^^^^^^--------------------------------^^
   |         |         |        |
   |         |         |        this tail expression is of type `i32`
   |         |         the trait `From<()>` is not implemented for `i32`
   |         required by a bound introduced by this call
   |
   = help: the following other types implement trait `From<T>`:
   `i32` implements `From<CpuId>`
   `i32` implements `From<bool>`
   `i32` implements `From<i16>`
   `i32` implements `From<i8>`
   `i32` implements `From<u16>`
   `i32` implements `From<u8>`
   = note: required for `()` to implement `Into<i32>`
   = note: required for `i32` to implement `TryFrom<()>`
   = note: required for `()` to implement `TryInto<i32>`
   note: required by a bound in `error::to_result`
   --> rust/kernel/error.rs:382:15
   |
   380 | pub fn to_result<T>(code: T) -> Result<T>
   |        --------- required by a bound in this function
   381 | where
   382 |     T: Copy + TryInto<i32>,
   |               ^^^^^^^^^^^^ required by this bound in `to_result`
--
>> error[E0277]: the trait bound `i32: From<()>` is not satisfied
   --> rust/kernel/net/phy.rs:264:19
   |
   264 |         to_result(unsafe { bindings::genphy_update_link(phydev) })
   |         --------- ^^^^^^^^^------------------------------------^^
   |         |         |        |
   |         |         |        this tail expression is of type `i32`
   |         |         the trait `From<()>` is not implemented for `i32`
   |         required by a bound introduced by this call
   |
   = help: the following other types implement trait `From<T>`:
   `i32` implements `From<CpuId>`
   `i32` implements `From<bool>`
   `i32` implements `From<i16>`
   `i32` implements `From<i8>`
   `i32` implements `From<u16>`
   `i32` implements `From<u8>`
   = note: required for `()` to implement `Into<i32>`
   = note: required for `i32` to implement `TryFrom<()>`
   = note: required for `()` to implement `TryInto<i32>`
   note: required by a bound in `error::to_result`
   --> rust/kernel/error.rs:382:15
   |
   380 | pub fn to_result<T>(code: T) -> Result<T>
   |        --------- required by a bound in this function
   381 | where
   382 |     T: Copy + TryInto<i32>,
   |               ^^^^^^^^^^^^ required by this bound in `to_result`
--
>> error[E0277]: the trait bound `i32: From<()>` is not satisfied
   --> rust/kernel/net/phy.rs:272:19
   |
   272 |         to_result(unsafe { bindings::genphy_read_lpa(phydev) })
   |         --------- ^^^^^^^^^---------------------------------^^
   |         |         |        |
   |         |         |        this tail expression is of type `i32`
   |         |         the trait `From<()>` is not implemented for `i32`
   |         required by a bound introduced by this call
   |
   = help: the following other types implement trait `From<T>`:
   `i32` implements `From<CpuId>`
   `i32` implements `From<bool>`
   `i32` implements `From<i16>`
   `i32` implements `From<i8>`
   `i32` implements `From<u16>`
   `i32` implements `From<u8>`
   = note: required for `()` to implement `Into<i32>`
   = note: required for `i32` to implement `TryFrom<()>`
   = note: required for `()` to implement `TryInto<i32>`
   note: required by a bound in `error::to_result`
   --> rust/kernel/error.rs:382:15
   |
   380 | pub fn to_result<T>(code: T) -> Result<T>
   |        --------- required by a bound in this function
   381 | where
   382 |     T: Copy + TryInto<i32>,
   |               ^^^^^^^^^^^^ required by this bound in `to_result`
--
>> error[E0277]: the trait bound `i32: From<()>` is not satisfied
   --> rust/kernel/net/phy.rs:280:19
   |
   280 |         to_result(unsafe { bindings::genphy_read_abilities(phydev) })
   |         --------- ^^^^^^^^^---------------------------------------^^
   |         |         |        |
   |         |         |        this tail expression is of type `i32`
   |         |         the trait `From<()>` is not implemented for `i32`
   |         required by a bound introduced by this call
   |
   = help: the following other types implement trait `From<T>`:
   `i32` implements `From<CpuId>`
   `i32` implements `From<bool>`
   `i32` implements `From<i16>`
   `i32` implements `From<i8>`
   `i32` implements `From<u16>`
   `i32` implements `From<u8>`
   = note: required for `()` to implement `Into<i32>`
   = note: required for `i32` to implement `TryFrom<()>`
   = note: required for `()` to implement `TryInto<i32>`
   note: required by a bound in `error::to_result`
   --> rust/kernel/error.rs:382:15
   |
   380 | pub fn to_result<T>(code: T) -> Result<T>
   |        --------- required by a bound in this function
   381 | where
   382 |     T: Copy + TryInto<i32>,
   |               ^^^^^^^^^^^^ required by this bound in `to_result`
..

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2025-09-12  8:41 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).