Skip to content

Crash when using type comments inside a generic class with constrained type variables. #16649

Closed
@picnixz

Description

@picnixz

I've encountered something really weird which is quite close to all issues related to AttributeError: attribute '_fullname' of 'TypeInfo' undefined but where I could reproduce the bug.

More precisely, the following crashes

from typing import Generic, TypeVar
NT = TypeVar('NT', int, float)
class Foo(Generic[NT]):
    def bar(self) -> None:
        p, q = 1, 2.0  # type: (int, float)

with a "AttributeError: attribute '_fullname' of 'TypeInfo' undefined". Obviously, the following succeeds:

from typing import Generic, TypeVar
NT = TypeVar('NT', int, float)
class Foo(Generic[NT]):
    def bar(self) -> None:
        p, q = 1, 2.0  # no type comment

So I thought that the issue was because of the type comment. However (!), I was surprised to see that the following also doesn't crash:

from typing import Generic, TypeVar
NT = TypeVar('NT', bound=int)  # here I have a bound and not a constraint !
class Foo(Generic[NT]):
    def bar(self) -> None:
        p, q = 1, 2.0  # type: (int, float)

Or even the following is fine:

from typing import Generic, TypeVar
NT = TypeVar('NT', int, float)  # here I have a constraint
class Foo(Generic[NT]):
    def bar(self) -> None:
        # but here I only have a single annotated object and not two on the same line
        p = 1  # type: int

Now, we could have thought that the issue stems from "constrained TypeVar" + "type comment with more than 2 objects". But actually, it's not entirely the case because the following actually works (!!):

from typing import Generic, TypeVar
NT = TypeVar('NT', int, float)
class Foo(Generic[NT]):
    p, q = 1, 2.0  # type: (int, float)

Also, if I do not inherit from Generic, then the original bug disappears. So I think the issue stems from the fact that I inherit from Generic, uses a constrainted TypeVar (although I don't understand why the type comment outside a method wouldn't produce a bug as well) and a type comment for two objects (note that this is allowed according to PEP 484).

Full traceback

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "mypy/checker.py", line 591, in accept
  File "mypy/nodes.py", line 785, in accept
  File "mypy/checker.py", line 1000, in visit_func_def
  File "mypy/checker.py", line 1004, in _visit_func_def
  File "mypy/checker.py", line 1077, in check_func_item
  File "mypy/checker.py", line 1104, in check_func_def
  File "mypy/checker.py", line 1867, in expand_typevars
  File "mypy/checker.py", line 7628, in expand_func
  File "mypy/treetransform.py", line 696, in node
  File "mypy/nodes.py", line 785, in accept
  File "mypy/treetransform.py", line 194, in visit_func_def
  File "mypy/treetransform.py", line 735, in block
  File "mypy/treetransform.py", line 279, in visit_block
  File "mypy/treetransform.py", line 746, in statements
  File "mypy/treetransform.py", line 713, in stmt
  File "mypy/nodes.py", line 1402, in accept
  File "mypy/treetransform.py", line 344, in visit_for_stmt
  File "mypy/treetransform.py", line 777, in optional_type
  File "mypy/checker.py", line 7639, in type
  File "mypy/expandtype.py", line 71, in expand_type
  File "mypy/types.py", line 2394, in accept
  File "mypy/expandtype.py", line 413, in visit_tuple_type
  File "mypy/types.py", line 1429, in accept
  File "mypy/expandtype.py", line 215, in visit_instance
  File "mypy/nodes.py", line 3099, in fullname
AttributeError: attribute '_fullname' of 'TypeInfo' undefined

Environment

Platform:              linux; (Linux-5.3.18-lp152.106-default-x86_64-with-glibc2.26)
Python version:        3.11.6 (main, Nov 29 2023, 14:46:32) [GCC 7.5.0])
Python implementation: CPython
MyPy version:          1.7.1 (compiled: yes)
Command:               python3.11 -m mypy -c "$code" --no-incremental

Here "$code" is a string containing any of the above programs, e.g.,

$ read -r -d '' code <<EOF
from typing import Generic, TypeVar
NT = TypeVar('NT', int, float)
class Foo(Generic[NT]):
    def bar(self) -> None:
        p, q = 1, 2.0  # type: (int, float)
EOF
$ python3.11 -m mypy -c "$code" --no-incremental --show-traceback
Traceback (most recent call last):
  ...
AttributeError: attribute '_fullname' of 'TypeInfo' undefined

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions