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

Confusing error message for property with @overloaded function #8737

Open
3rdcycle opened this issue Apr 28, 2020 · 4 comments
Open

Confusing error message for property with @overloaded function #8737

3rdcycle opened this issue Apr 28, 2020 · 4 comments
Labels

Comments

@3rdcycle
Copy link

The following does not seem to work:

from typing import overload


class Example:

	@overload
	def fun(self, p: int) -> int: ...
	@overload
	def fun(self, p: str) -> str: ...

	def fun(self, p=1):
		if isinstance(p, int):
			return 'foo'
		else:
			return 'bar'

	prop = property(fun)

Argument 1 to "property" has incompatible type overloaded function; expected "Optional[Callable[[Any], Any]]"

Is this a bug or expected?
Also, fun(0) returns a string instead of an int as specified in the stub, but mypy doesn't seem to catch this. Again, bug or expected?

@JelleZijlstra
Copy link
Member

The property part seems like a real bug, if a low-priority one (I doubt it's common to turn an overloaded function into a property).

As for not catching the incorrect return type, mypy doesn't type check the body of the overloaded function according to the overloads, only according to the annotations on the body itself. Since your function body has no annotation, mypy doesn't typecheck the body at all.

@JukkaL
Copy link
Collaborator

JukkaL commented May 1, 2020

But property should be called with a function that takes one argument, not two arguments like fun? The problem here seems to be a confusing error message.

@JukkaL JukkaL changed the title property with @overloaded function Confusing error message for property with @overloaded function May 1, 2020
@3rdcycle
Copy link
Author

Just to be sure, you're saying it's not enough that the implementation provides a default argument for p? Indeed, if I change the first overload to

def fun(self, p: int = 1) -> int: ...

It seems to work.

@AlexWaygood AlexWaygood added diagnostics topic-error-reporting How we report errors topic-descriptors Properties, class vs. instance attributes labels Apr 1, 2022
@Bibo-Joshi
Copy link

Hi. I'd like to come back to this old discussion with a new use case that's maybe a bit better. In short, the return value of the overloaded property depends on the generic attribute of the class.

import datetime as dtm
from typing import overload


class Example[T: (dtm.date, None)]:

    def __init__(self, date: T) -> None:
        self.date: T = date

    @overload
    def day(self: "Example[dtm.date]") -> int: ...

    @overload
    def day(self: "Example[None]") -> None: ...

    @property
    def day(self) -> int | None:
        if self.date is None:
            return None
        return self.date.day


def foo(example: Example) -> int:
    if example.day is None:
        return 0
    return example.day  # this is line 26


if __name__ == "__main__":
    print(foo(Example(dtm.date.today())))
    print(foo(Example(None)))

running mypy 1.11.2 with --enable-incomplete-feature=NewGenericSyntax gives

foo.py:26: error: Incompatible return value type (got overloaded function, expected "int")  [return-value]

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

No branches or pull requests

5 participants