Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support IntoPyObject for Arc in pyclass for pyo3(get) #4887

Open
weixiao-huang opened this issue Feb 2, 2025 · 2 comments
Open

Support IntoPyObject for Arc in pyclass for pyo3(get) #4887

weixiao-huang opened this issue Feb 2, 2025 · 2 comments

Comments

@weixiao-huang
Copy link

I defined a class

#[pyclass(get_all)]
class MyClass {
  inner: Arc<Vec<String>>,
}

and I got the error below

`std::sync::Arc<std::vec::Vec<std::string::String>>` cannot be converted to a Python objec
@ngoldbaum
Copy link
Contributor

#4668 is somewhat related, but I think Arc may not have the same issues with semantics in Python that representing a rust atomic integer would?

@Icxolu
Copy link
Contributor

Icxolu commented Feb 8, 2025

I think the question here is to define how to convert Arc<T>. We don't have access to a T by value so we can't just forward it that way. I guess it would make the most sense to forward to the implementation for &T using HRTB, but I don't know of a way to name it in the associated types. We could of course erase the types and just return PyAny and PyErr, but I'm not so sure whether we should do that.

impl<'py, T> IntoPyObject<'py> for Arc<T>
where
    for<'a> &'a T: IntoPyObject<'py>,
{
    type Target = <??>::Target;
    type Output = <??>::Output;
    type Error = <??>::Error;

    #[inline]
    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
        (&*self).into_pyobject(py)
    }
}

It is possible to implement on a reference, which would make it work for #[pyo3(get)] on #[pyclass], but would not work for
#[derive(IntoPyObject)] (only #[derive(IntoPyObjectRef)]) or as return type.

impl<'a, 'py, T> IntoPyObject<'py> for &'a Arc<T>
where
    &'a T: IntoPyObject<'py>,
{
    type Target = <&'a T as IntoPyObject<'py>>::Target;
    type Output = <&'a T as IntoPyObject<'py>>::Output;
    type Error = <&'a T as IntoPyObject<'py>>::Error;

    #[inline]
    fn into_pyobject(self, py: crate::Python<'py>) -> Result<Self::Output, Self::Error> {
        (&**self).into_pyobject(py)
    }
}

I tend to think that writing a manual #[getter] for these cases is the better option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants