Skip to content

No errors on typed function internals if function definition itself is untyped; I'd argue that's probably incorrect behavior, but at the very least it's *super* confusing and *very* hard to diagnose when it happens #10895

Closed
@posita

Description

@posita

Issue description

This doesn't generate an error:

# test_case7.py
from typing import List

def untyped_func_def_with_typed_body():
    a: List[int] = [0, 1, 2]
    key: str = "asdf"
    a[key]  # <- No error, despite internals being typed

This does:

# test_case8.py
from typing import List

def typed_func_def_with_typed_body() -> None:
    a: List[int] = [0, 1, 2]
    key: str = "asdf"
    a[key]  # <- *Now* this generates an error

That maybe technically "documented", but that's really esoteric and completely unintuitive. I've spent hours chasing this down.


Archived original flailing to arrive at core problem

UPDATE 2: Okay, this just keeps getting weirder and weirder. Consider:

# test_case3.py

def func():
    a = [0, 1, 2]
    a["asdf"]  # <- This doesn't generate an error

b = [0, 1, 2]
b["asdf"]  # <- But this does?!

Runtime:

% mypy --config=/dev/null test_case3.py
/dev/null: No [mypy] section in config file
test_case3.py:8: error: No overload variant of "__getitem__" of "list" matches argument type "str"
test_case3.py:8: note: Possible overload variants:
test_case3.py:8: note:     def __getitem__(self, SupportsIndex) -> int
test_case3.py:8: note:     def __getitem__(self, slice) -> List[int]
Found 1 error in 1 file (checked 1 source file)

UPDATE 1: You don't need the @overloads. It still doesn't work without them. Here's the simplified case:

# test_case2.py
from typing import List, Union

class GetItemTest:
    def __getitem__(self, key: Union[int, slice]) -> Union[int, List[int]]:
        return list(range(10))[key]

def test_a():
    a = GetItemTest()
    a["asdf"]  # <- Why isn't this a typing error?

Original case (same effect):

# test_case1.py
from typing import List, Union, overload

class GetItemTest:
    @overload
    def __getitem__(self, key: int) -> int:
        ...
    @overload
    def __getitem__(self, key: slice) -> List[int]:
        ...
    def __getitem__(self, key: Union[int, slice]) -> Union[int, List[int]]:
        return list(range(10))[key]

def test_a():
    a = GetItemTest()
    a["asdf"]  # <- Why isn't this a typing error?

Runtime:

% python --version
Python 3.9.6
% pip list
Package           Version
----------------- --------
mypy              0.910
mypy-extensions   0.4.3
pip               21.2.1
setuptools        57.4.0
toml              0.10.2
typing-extensions 3.10.0.0
% mypy --version
mypy 0.910
% mypy --config=/dev/null test_case1.py
/dev/null: No [mypy] section in config file
Success: no issues found in 1 source file

I can't prove it, but I feel like this used to work. It seems pretty basic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions