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

#[new] can silently fail when arguments to the function can't be constructed #4470

Closed
Walter-Reactor opened this issue Aug 23, 2024 · 4 comments · Fixed by #4481
Closed

#[new] can silently fail when arguments to the function can't be constructed #4470

Walter-Reactor opened this issue Aug 23, 2024 · 4 comments · Fixed by #4481
Labels

Comments

@Walter-Reactor
Copy link

Bug Description

When using #[new] on a function where one of the parameters can't be constructed by PyO3, the constructor silently fails and attempting to construct the object will at runtime trigger a "No constructor defined" exception.

Steps to Reproduce

The following compiles with no warning or error, but attempting to create a Foo from python will fail.

#[pyclass]
#[derive(Clone)]
pub struct Param(String); // Simple! forgot to provide an impl block with new on it.

#[pyclass]
pub struct Foo{...}

#[pymethods]
impl Foo{
  #[new]
  pub fn new(param : Param) -> Self {
    Foo{}
  }

Backtrace

No response

Your operating system and version

Windows 11

Your Python version (python --version)

Python 3.12.4

Your Rust version (rustc --version)

rustc 1.80.1 (3f5fd8dd4 2024-08-06)

Your PyO3 version

0.22.1

How did you install python? Did you use a virtualenv?

System python, invoked via uv 0.3.0's uv run

Additional Info

No response

@attack68
Copy link
Contributor

This has a crossover with #4465 which defines #[new] on simple enums for a separate reason.

@davidhewitt
Copy link
Member

@Walter-Reactor can you provide a more complete minimal repro along with the proposed change to behaviour you would like to see?

The problem, as I see it currently, is that you cannot create a Param() because you didn't define a way, and Foo has nothing to do with this case.

@Walter-Reactor
Copy link
Author

Walter-Reactor commented Aug 23, 2024

That's accurate, but the inability to construct Foo seemed like it was being contagious. Now that I consider it, if there were some other way to construct Param, that's not actually true.

My main issue here is one of diagnostsics. It was extremely confusing when I tried to write Foo("some string"), and was told that the constructor didn't exist, yet there was clearly a #[new] block on it. If the error message included the name of the type, I think this would be much clearer

@birkenfeld
Copy link
Member

It was extremely confusing when I tried to write Foo("some string"), and was told that the constructor didn't exist

I can't reproduce this. Using the code you posted above:

>>> Foo("a")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument 'param': 'str' object cannot be converted to 'Param'
>>> Param("a")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: No constructor defined

Still, it could indeed be good to mention the type name in the "no constructor defined" message.

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

Successfully merging a pull request may close this issue.

4 participants