-
Notifications
You must be signed in to change notification settings - Fork 778
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
Fix IntoPyCallbackOutput paper cuts #2326
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
First commit message - "Make arrays of pyclasses easier to sue" - oops :)
7e54611
to
7477842
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice! Just a few final thoughts, and I think it would be better to change from IntoPyResult<R>
-> IntoPyResult<T>
. After that, I think this is good to merge 👍
pyo3-macros-backend/src/method.rs
Outdated
if false { | ||
use _pyo3::impl_::ghost::IntoPyResult; | ||
ret.into_py_result(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer this approach over what I did before. This won't actually call into_py_result
if an user accidentally writes it for their type.
src/impl_/ghost.rs
Outdated
/// If it does nothing, was it ever really there? 👻 | ||
/// | ||
/// This is code that is just type checked to e.g. create better compile errors, | ||
/// but that never affects anything at runtime, | ||
use crate::{IntoPy, PyErr, PyObject}; | ||
|
||
#[allow(clippy::wrong_self_convention)] | ||
pub trait IntoPyResult<T> { | ||
fn into_py_result(&mut self) {} | ||
} | ||
|
||
impl<T> IntoPyResult<T> for T where T: IntoPy<PyObject> {} | ||
|
||
impl<T, E> IntoPyResult<T> for Result<T, E> | ||
where | ||
T: IntoPy<PyObject>, | ||
E: Into<PyErr>, | ||
{ | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer this approach of code that doesn't actually do anything 😉
error[E0277]: the trait bound `Blah: IntoPyCallbackOutput<_>` is not satisfied | ||
--> tests/ui/missing_intopy.rs:3:1 | ||
| | ||
3 | #[pyo3::pyfunction] | ||
| ^^^^^^^^^^^^^^^^^^^ the trait `IntoPyCallbackOutput<_>` is not implemented for `Blah` | ||
| | ||
note: required by a bound in `pyo3::callback::convert` | ||
--> src/callback.rs | ||
| | ||
| T: IntoPyCallbackOutput<U>, | ||
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `pyo3::callback::convert` | ||
= note: this error originates in the attribute macro `pyo3::pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unfortunate this IntoPyCallbackOutput
part is back - but overall I think it's worth it. The first part of the error is very very good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sneaky! Nicely done 👍
src/impl_/ghost.rs
Outdated
/// but that never affects anything at runtime, | ||
use crate::{IntoPy, PyErr, PyObject}; | ||
|
||
#[allow(clippy::wrong_self_convention)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this lint actually necessary? I wonder if it's a hangover from experimentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that hits the methods called into_* usually take self by value
lint. The reason it takes &mut self is to prevent a cascade like this:
which is required by `Blah: IntoResult<Result<Blah, PyErr>>`
which is required by `Blah: IntoPyResult<Result<Blah, PyErr>>`
`&Blah: IntoPy<Py<PyAny>>`
which is required by `&Blah: IntoResult<Result<&Blah, PyErr>>`
which is required by `&Blah: IntoPyResult<Result<&Blah, PyErr>>`
`&mut Blah: IntoPy<Py<PyAny>>`
which is required by `&mut Blah: IntoResult<Result<&mut Blah, PyErr>>`
which is required by `&mut Blah: IntoPyResult<Result<&mut Blah, PyErr>>`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see! Do you think we should name the method differently then? E.g. into_py_result_hint
or assert_into_py_result
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, LGTM! To squash out the various interim commits I'm gonna squash-merge this one 👍
impl<T, const N: usize> IntoPy<PyObject> for [T; N]
to useIntoPy
for it elements instead. Fixes IntoPyCallbackOutput<_> is not implimented for arrays of pyclass #2323IntoPyCallbackOutput
, which (generally) generates a better compile error.For example, consider this:
Current error:
Error with this PR:
Todo: