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

Self does not work with delegation and an explicit return type #18182

Closed
voidspace opened this issue Nov 24, 2024 · 2 comments
Closed

Self does not work with delegation and an explicit return type #18182

voidspace opened this issue Nov 24, 2024 · 2 comments
Labels
bug mypy got something wrong

Comments

@voidspace
Copy link

Bug Report

typing.Self should be used where a class method returns an instance of the class. If the class method delegates to a function that has an explicit return type then mypy reports an error for the use of self.

To Reproduce

This Python code in "test.py":

from typing import Self


class Thing:

    @classmethod
    def constructor(cls) -> Self:
        return function()
        
def function() -> Thing:
    return Thing()

Expected Behavior

No Errors

Actual Behavior

Produces this report from mypy:

$ mypy test.py
test.py:8: error: Incompatible return value type (got "Thing", expected "Self")  [return-value]

Your Environment

  • Mypy version used:
$ mypy --version
mypy 1.13.0 (compiled: yes)

Python 3.12, Ubuntu 24.04

@voidspace voidspace added the bug mypy got something wrong label Nov 24, 2024
@brianschubert
Copy link
Collaborator

Mypy is correct to report an error here. Self isn't equivalent to the type of current class. Rather, it works like a type variable with an upper bound of the current class. Returning a Thing from a function with a return type of Self isn't allowed, since that would be invalid in cases where Self gets bound to a subtype of Thing. Consider:

class SubThing(Thing):
    def foo():
        pass

# Here, 'Self' is bound to 'SubThing', so 'x' has type 'SubThing'
x = SubThing.constructor()

# The type system says this should be ok...
x.foo()  # boom! AttributeError: 'Thing' object has no attribute 'foo'

See also Generic - Self from the typing spec for more details on how Self works.

@brianschubert brianschubert closed this as not planned Won't fix, can't repro, duplicate, stale Nov 24, 2024
@voidspace
Copy link
Author

You're right, the code plays terribly with subclasses. (It's from an example for a course.) I've moved the code into the method and am using cls() instead of the hardcoded type in the function. Much better. I was surprised it didn't work though - thanks for the explanation.

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

No branches or pull requests

2 participants