Skip to content

Bug (?) with Sequence / List #1113

Closed
Closed

Description

@rmcgibbo

This is from the latest master (pip install git+git://github.com/JukkaL/mypy.git).

$ cat file.py
from typing import Dict, Sequence
def f(data: Dict[str, Sequence[int]]) -> None:
    pass
data = {"a": [1, 2]}
f(data)

$ mypy file.py
file.py:7: error: Argument 1 to "f" has incompatible type Dict[str, List[int]]; expected Dict[str, Sequence[int]]

If I replace the function call with f({"a": [1, 2]}), instead of defining the dict on a separate line, then it works.

Activity

  1. gvanrossum commented on Jan 11, 2016

    @gvanrossum
    Member
  2. JukkaL commented on Jan 11, 2016

    @JukkaL
    Collaborator

    The behavior is correct, as the second type parameter to Dict is invariant. However, if you'd use Mapping[str, Sequence[int]], this should work (but it doesn't).

  3. JukkaL commented on Jan 11, 2016

    @JukkaL
    Collaborator

    To see why mypy complains about the code, consider this slightly different example:

    from typing import Dict, Sequence
    def f(data: Dict[str, Sequence[int]]) -> None:
        data['x'] = (1, 2)
    data = {"a": [1, 2]}
    f(data)
    data['x'].append(1)   # error, tuple doesn't support append
    

    If the value type parameter of Dict would be covariant, mypy wouldn't complain about the above example but it would fail with a runtime error -> type checking would be unsound.

  4. gvanrossum commented on Jan 11, 2016

    @gvanrossum
    Member
  5. JukkaL commented on Jan 11, 2016

    @JukkaL
    Collaborator

    Mypy treats Mapping as invariant, but the value type should probably be covariant, at least. The key type could also be covariant.

  6. JukkaL commented on Jan 11, 2016

    @JukkaL
    Collaborator

    Another idea: mypy could give a more useful error message when it detects an issue like the original one.

    Consider this potential output, for example:

    $ mypy file.py
    file.py:7: error: Argument 1 to "f" has incompatible type Dict[str, List[int]]; expected Dict[str, Sequence[int]]
    file.py:8: note: The second type parameter of "Dict" is invariant; consider using "Mapping" instead, which is covariant
    

    This would give more context even for somebody who doesn't understand covariance/invariance -- these terms are easy to google.

    Even better, we could give a pointer to relevant documentation.

  7. gvanrossum commented on Jan 11, 2016

    @gvanrossum
    Member
  8. rmcgibbo commented on Jan 11, 2016

    @rmcgibbo
    Author

    I would have thought that the two snippets

    data = {"a": [1, 2]}
    f(data)
    

    and

    f({"a": [1, 2]})
    

    would either both typecheck, or both fail to typecheck, but I'm kind of new at this.

    Let me know if you want me to close this issue, since it seems taken care of.

  9. JukkaL commented on Jan 11, 2016

    @JukkaL
    Collaborator

    The latter is different, though the reason is somewhat technical -- as the dictionary is immediately given as an argument to f, mypy infers a type Dict[str, Sequence[int]] for it. You could achieve the same effect my giving an annotation for data:

    data = {"a" : [1, 2]}  # type: Dict[str, Sequence[int]]
    f(data)   # OK!
    

    If you construct a dictionary as a function argument, the declared argument type effectively acts as an implicit type annotation. However, mypy doesn't look forward when inferring the type of data, so you have to give an annotation to override the default inferred type.

  10. rmcgibbo commented on Jan 11, 2016

    @rmcgibbo
    Author

    Got it. Thanks, @JukkaL! (The only type system I've really played with is Haskell's -- this one is in most ways much simpler, but I'm just starting to learn the differences.)

  11. gvanrossum commented on Jan 11, 2016

    @gvanrossum
    Member

    Robert, can we close this issue (now that we've explained the reason and filed the issues for actual bugs)?

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions