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

Can't generate #[pyproto] impls from a macro #1258

Closed
1tgr opened this issue Oct 21, 2020 · 4 comments
Closed

Can't generate #[pyproto] impls from a macro #1258

1tgr opened this issue Oct 21, 2020 · 4 comments

Comments

@1tgr
Copy link
Contributor

1tgr commented Oct 21, 2020

The code generated for this example by the proc_macro causes a compiler error:

macro_rules! py_object_protocol {
    (_inner, Debug) => {
        fn __str__(&self) -> pyo3::prelude::PyResult<String> {
            Ok(format!("{:?}", self))
        }
    };

    ($ty:ty, $( $trait:ident ),*) => {
        #[pyo3::prelude::pyproto]
        impl pyo3::PyObjectProtocol for $ty {
            $(
                py_object_protocol!(_inner, $trait);
            )*
        }
    }
}

#[pyo3::prelude::pyclass]
#[derive(Debug)]
pub struct S {}

/* #[pyproto]
impl PyObjectProtocol for S {
    fn __str__(&self) -> PyResult<String> {
        Ok(format!("{:?}", self))
    }
} */

py_object_protocol!(S, Debug);

Compiler error from the example above:

error[E0053]: method `__str__` has an incompatible type for trait
 --> src/lib.rs:3:9
  |
3 |         fn __str__(&self) -> pyo3::prelude::PyResult<String> {
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found enum `std::result::Result`
  |
  = note: expected fn pointer `fn(&'p S) -> <S as pyo3::class::basic::PyObjectStrProtocol<'p>>::Result`
             found fn pointer `fn(&S) -> std::result::Result<std::string::String, pyo3::err::PyErr>`
  = note: consider constraining the associated type `<S as pyo3::class::basic::PyObjectStrProtocol<'p>>::Result` to `std::result::Result<std::string::String, pyo3::err::PyErr>` or calling a method that returns `<S as pyo3::class::basic::PyObjectStrProtocol<'p>>::Result`

Note that the equivalent code (commented out in the example) compiles fine.

This is pyo3 0.12.3, but I've seen the same error from previous versions.

@1tgr
Copy link
Contributor Author

1tgr commented Oct 21, 2020

I think it relates to expanding a macro inside the impl block, ie when the proc_macro sees tokens that originated from a macro. I can write a py_object_protocol macro provided it doesn't make a macro call inside the impl.

@1tgr
Copy link
Contributor Author

1tgr commented Oct 21, 2020

Looks like it's due to the fact that macros aren't eagerly expanded in the input to a proc_macro. This would be addressed by eager macro expansion in rust-lang/rfcs#2320.

@davidhewitt
Copy link
Member

Thanks @1tgr for reporting this. I'm not sure if there's anything easy that can be done to resolve this on our side - as you say it might require upstream support.

I might have a play with this sometime to get my head around it further. Won't promise anything though!

@davidhewitt
Copy link
Member

davidhewitt commented Sep 18, 2021

Will close as wontfix - we're in the process of merging #[pyproto] into #[pymethods]. #1864

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

2 participants