-
Notifications
You must be signed in to change notification settings - Fork 802
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # 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: