Skip to content

Infer variable type if initializer is an empty collection #1055

Closed
@JukkaL

Description

@JukkaL

Code like this is one of the most common cases where we need a variable annotation (DONE):

def f() -> None:
    x = []   # mypy insists on annotation (such as List[int]) here
    for i in range(5):
        x.append(i * 2)

Mypy could do a better job of inferring types in cases like these:

  • Variable is initialized with an empty collection (or more generally, a generic type where the type argument values are indeterminate using only local statement context).
  • The first reference to the variable after initialization (in the same scope) mutates the collection and allows us to infer the item types.

These cases would still require an annotation:

  • Collection is read after initialization and before mutation (this happens sometimes but not too often).
  • The variable is not mutated in the scope that initializes it. For example, an attribute is initialized in __init__ and mutated in another method.

This is related to #254.

More common examples where this should work:

(1) DONE

x = {}
x['key'] = 2

(2) DONE

x = set()
x.add(2)

Additional, less common examples (not done):

(3) [postponed -- too rare and complicated]

x = {}
x.setdefault('key', []).append(1)   # this is harder than most examples

(4) DONE

x = {}
x.update({'x': 1})

(5) [rejected -- too rare]

x = set()
x |= {1, 2}

(6) DONE (#8036)

if cond():
    x = []
else:
    x = [1]

(7) DONE (#8167 and #8039)

Similar to above but with a user-defined generic type or a standard library generic type that is not list, dict or set.

Update: After some more analysis, only defaultdict and OrderedDict seem common enough to support.

Not sure about this:

(8) [rejected idea]

x = []
foo(x)  # Should we infer type of x from the argument type? Probably not.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions