Skip to content

Wrong inference of the target of __new__ #9405

Closed

Description

@Hibou57

🐛 Bug Report

The target of an invocation of __new__ is an explicit class, but mypy erroneously believes it is another class.

To Reproduce

Create a file test.py with this content:

from typing import Any
class C(str):
    def __new__(cls, value: str) -> Any:
        return str.__new__(cls, value)

Then run mypy test.py

Side note # 1: this is a stripped down version to reproduce the issue, the original case has more real interest.
Side note # 2: __new__ should return C but the name C is not defined during class creation, so __new__ is declared to return Any, instead.

Expected Behavior

There should be no error, as one can check this way:

>>> import test
>>> s = test.C("abc")
# No exception raised
>>> type(s)
<class 'test.C'>

Actual Behavior

mypy complains:

test.py:4: error: Too many arguments for "__new__" of "object"
Found 1 error in 1 file (checked 1 source file)

It erroneously believes the target of __new__ is object while it is str

Your Environment

  • Mypy version used: mypy 0.782
  • Mypy command-line flags: none (just the file name)
  • Mypy configuration options from mypy.ini (and other config files): none (no config file)
  • Python version used: Python 3.8.2

Activity

  1. changed the title [-]Wrong inference of the type of the target of `__new__`[/-] [+]Wrong inference of the target of `__new__`[/+] on Sep 3, 2020
  2. gvanrossum commented on Sep 3, 2020

    @gvanrossum
    Member

    I think this could actually be fixed in typeshed -- the problem seems to be that no __new__ method is declared for class str.

    But another interpretation would be that we ought to automatically derive a signature for __new__ if one is given for __init__. That would not be a simple feature to add, and I suspect there's already some other issue open for it. (Maybe #5647 is related?)

  3. added and removed
    bugmypy got something wrong
    on Sep 3, 2020
  4. Hibou57 commented on Sep 3, 2020

    @Hibou57
    Author

    I’m not good at Python insides, anyway, my understanding is that the two issues are not that much related. The other issue as I understand it, is about __new__ vs __init__ to infer the type returned by a class constructor (I agree __new__ is the reference for that).

    I did not knew about typeshed, so just had a look: https://github.com/python/typeshed/blob/master/stdlib/2and3/builtins.pyi#L443

    Indeed, no __new__ is defined. But I was believing the arguments to __new__ and __init__, except for cls and self, are typically the same. If I’m not too wrong, when no __new__ is defined, what about relying on __init__ to infer its expected arguments? In that case, __new__(cls, o: object) could be inferred and would match the invocation.

  5. Hibou57 commented on Sep 6, 2020

    @Hibou57
    Author

    That said, I wonder if the error is finally in typeshed: I believe that’s a __new__ which should be declared for str, not an __init__ (and if so, probably the same for others like int, float, bool). There seems to be no __init__ for str.

  6. gvanrossum commented on Sep 6, 2020

    @gvanrossum
    Member
  7. JelleZijlstra commented on Sep 6, 2020

    @JelleZijlstra
    Member

    We tried this before in python/typeshed#1352 and terrible things happened (see python/typeshed#1464). Perhaps the enum issue I found back then got solved some other way since then, though.

  8. AlexWaygood commented on Mar 25, 2022

    @AlexWaygood
    Member

    Cannot be reproduced on mypy 0.800+

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions