Skip to content

TypeVar bound is ignored in generic alias #10445

Closed

Description

@JelleZijlstra

Bug Report

A generic alias using a TypeVar with a bound allows type arguments that don't match the bound

To Reproduce

% cat tvbound.py 
import typing

FooT = typing.TypeVar("FooT", bound=str)
FooIsh = typing.Union[int, FooT]

bat2: FooIsh[float] = 1.0

% mypy tvbound.py
Success: no issues found in 1 source file
% mypy --version
mypy 0.820+dev.e8afde621531880c2b9c51acba8e565a29cde0b1

Expected Behavior

I would expect an error saying that the value of FooT cannot be float.

Found this as a result of microsoft/pyright#1839.

Activity

  1. UnquietCode commented on Nov 1, 2021

    @UnquietCode

    I would like to mention that using mypy 0.91 I see a more general version of this error where the resolved GenericAlias isn't type checked at all regardless of the bound on the TypeVar. That is:

    FooT = typing.TypeVar("FooT")
    FooIsh = typing.Union[int, FooT]
    
    bat2: FooIsh[float] = "passes"

    fails to report an error.

  2. AlexWaygood commented on Jul 7, 2022

    @AlexWaygood
    Member

    I just closed #13086 as a duplicate of this issue, but @harahu notes in that issue that this bug is also present for generic type aliases that use constrained TypeVars (as well as those that use bound TypeVars):

    from typing import Generic, TypeVar, TypeAlias
    
    U = TypeVar("U", bytes, str)
    RestrictedTuple: TypeAlias = tuple[U]
    i_am_illegal: RestrictedTuple[int]  # Passes, even though this type shouldn't be possible!
  3. added a commit that references this issue on Nov 24, 2022
    13bd201
  4. harahu commented on Nov 24, 2022

    @harahu

    @ilevkivskyi Are you sure this should be closed? I just made a minimal playground example out of the issue I pointed out in #13086, that @AlexWaygood mentioned above:

    https://mypy-play.net/?mypy=master&python=3.11&flags=strict&gist=b251ba96b0e4c9632c8ba162f81280e8

    This example still fails when run with mypy from the master branch.

  5. AlexWaygood commented on Nov 24, 2022

    @AlexWaygood
    Member

    @harahu, if I run mypy with the master branch checked out locally on this snippet:

    import typing
    
    FooT = typing.TypeVar("FooT", bound=str)
    FooIsh = typing.Union[int, FooT]
    bat: FooIsh[float] = 1.0
    
    FooT2 = typing.TypeVar("FooT2")
    FooIsh2 = typing.Union[int, FooT]
    bat2: FooIsh[float] = "fails"
    
    U = typing.TypeVar("U", bytes, str)
    RestrictedTuple: typing.TypeAlias = tuple[U]
    i_am_illegal: RestrictedTuple[int]

    Then this is the output:

    test.py:5: error: Type argument "float" of "FooIsh" must be a subtype of "str"  [type-var]
    test.py:9: error: Incompatible types in assignment (expression has type "str", variable has type "Union[int, float]")  [assignment]
    test.py:13: error: Value of type variable "U" of "RestrictedTuple" cannot be "int"  [type-var]
    Found 3 errors in 1 file (checked 1 source file)
    

    This seems like the correct output to me; I think it was correct for this issue to be closed.

    The "run mypy with the master branch" option on mypy playground is often quite out of sync with what mypy's actual master branch is, unfortunately. (I sort-of think having that option is not particularly helpful if it's not going to be automatically synced with mypy's latest commit). Note that mypy playground isn't run by mypy; it's a third-party project that you can report issues to here: https://github.com/ymyzk/mypy-playground.

  6. harahu commented on Nov 24, 2022

    @harahu

    I see. You correctly pointed out where I was mistaken. I assumed playground was up to date. Sorry about the confusion.

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