Skip to content

TypeVar bound with Optional checking does not work any more #12622

Closed
@darkclouder

Description

@darkclouder

Bug Report
I use a pattern where I bind a TypeVar to an optional so I can use a function to return either an optional or non-optional depending on what is passed to the function:
MaybeParent = TypeVar("MaybeParent", bound=Optional[Parent]).

So with a function with this signature try_copy(parent: MaybeParent) -> MaybeParent, the function returns a Parent if I pass a Parent and returns a Optional[Parent] if a pass a Optional[Parent].
So I can have a function which can handle optionals but explicitly returns a non-optional if I pass a non-optional.

This used to pass mypy with version 0.812 but now with 0.942, it yields an error as it does not manage to extract the optional type (any more) if you check for it first.
And IMO the typing is correct and it should therefore pass.

To Reproduce

  1. pip install mypy==0.942
  2. Check this code with mypy:
from typing import Optional, TypeVar

class Parent:
    def copy(self):
        return self

MaybeParent = TypeVar("MaybeParent", bound=Optional[Parent])

def try_copy_works(parent: Optional[Parent]) -> Optional[Parent]:
    if parent is None:
        return None
    return parent.copy()

def try_copy_doesnt_work(parent: MaybeParent) -> MaybeParent:
    if parent is None:
        return
    # Item "object" of the upper bound "Optional[Parent]" of type variable "MaybeParent" has no attribute "copy"
    return parent.copy()

def try_copy_doesnt_work_either(parent: MaybeParent) -> MaybeParent:
    if parent is None:
        return
    # Incompatible types in assignment (expression has type "MaybeParent", variable has type "Parent")
    guarded_parent: Parent = parent
    return guarded_parent.copy()

Expected Behavior
Should pass type checking as MaybeParent is bound with None | Parent.
Since I check None in the beginning, the variable should be bound with Parent.

Actual Behavior

Does not pass type checking:
Item "object" of the upper bound "Optional[Parent]" of type variable "MaybeParent" has no attribute "copy"
Incompatible types in assignment (expression has type "MaybeParent", variable has type "Parent")

Your Environment

  • Mypy version used: 0.942
  • Mypy command-line flags: none
  • Python version used: 3.8.13
  • Operating system and version: macOS 11.6.5

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions