8000 Error If Return Annotation Is Provided (Generics + TypeVar + isinstance) · Issue #12873 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

Error If Return Annotation Is Provided (Generics + TypeVar + isinstance) #12873

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

Closed
julzt0244 opened this issue May 26, 2022 · 4 comments
Closed
Labels
bug mypy got something wrong

Comments

@julzt0244
Copy link
julzt0244 commented May 26, 2022

I get this strange error whereby adding a return annotation causes mypy to fail to identify the code after the "isinstance" block.
Mypy gives an error on the last line of ErrorIfReturnIsAnnotated.foo() while it doesn't give any errors for WorksIfNoReturnAnnotation.foo()

The only difference in those two classes are that one of them declares an explicit None return annotation.

Environment

  • Mypy version used: 0.950 and 0.960
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: Python 3.10.4
  • Operating system and version: Windows 10 (Version 21H2)

Full simplified test code to reproduce the bug

from abc import ABCMeta
from typing import Generic, TypeVar, Union


class BaseEngine(metaclass=ABCMeta):
    pass


class BaseEngineVariantA(BaseEngine):
    pass


class BaseEngineVariantB(BaseEngine):
    pass


class VariantAConcreteEngine(BaseEngineVariantA):
    pass


T = TypeVar('T', bound=Union[BaseEngineVariantA, BaseEngineVariantB])


class IBase(Generic[T], metaclass=ABCMeta):
    def __init__(self, engine: T):
        self.engine = engine


class IAction(IBase[T], metaclass=ABCMeta):
    pass


class ErrorIfReturnIsAnnotated(IBase[T]):
    def __init__(self, something: T, actions_injected: type[IAction[T]]) -> None:
        self.something = something
        self.actions_injected = actions_injected

    def foo(self) -> None:
        if not isinstance(self.something, VariantAConcreteEngine):
            raise Exception("HI")

        self.actions_injected(self.something)  # Gives a mypy error of - error: Argument 1 to "IAction" has incompatible type "VariantAConcreteEngine"; expected "T"


class WorksIfNoReturnAnnotation(IBase[T]):
    def __init__(self, something: T, actions_injected: type[IAction[T]]) -> None:
        self.something = something
        self.actions_injected = actions_injected

    def foo(self):
        if not isinstance(self.something, VariantAConcreteEngine):
            raise Exception("HI")

        self.actions_injected(self.something)  # No errors

@julzt0244 julzt0244 added the bug mypy got something wrong label May 26, 2022
@JelleZijlstra
Copy link
Member

@JelleZijlstra JelleZijlstra closed this as not planned Won't fix, can't repro, duplicate, stale May 26, 2022
@julzt0244
Copy link
Author

Sorry can you explain why that is the case? I assume you're referring to "The function containing the error is not annotated" but the code for IAction has a init in its superclass IBase that dictates the first argument to be "T"

@JelleZijlstra
Copy link
Member

Mypy reports no errors in unannotated functions by default. It doesn't matter whether the function they're calling is annotated.

@julzt0244
Copy link
Author
julzt0244 commented May 26, 2022

I see thanks, is there a way for me to fix the mypy error for the first class ErrorIfReturnIsAnnotated without having to manually cast "cast(T, self.something)" after the isinstance block then? (That would be an incorrect cast as far as I know)

I would have assumed "actions_injected: type[IAction[T]]" would be happy to take in a concrete version (VariantAConcreteEngine) of one of its bound objects (BaseEngineVariantA) declared in the TypeVar

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
0