Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Better message when inferred variable type conflicts with later use #2529

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
TRManderson opened this issue Dec 6, 2016 · 5 comments
Closed

Comments

@TRManderson
Copy link
Contributor

TRManderson commented Dec 6, 2016

If you can come up with a better name for this issue, please let me know, this one is poor. The naming difficulty also lead to difficulty searching to see if this already existed, so apologies in advance if this is a duplicate issue.

When running this code through the typechecker:

from typing import Union, Dict, List
def g() -> List[Union[str, int]]:
    x = ['a']
    x += [1]
    return x

def f() -> Dict[str, Union[str, int]]:
    d = {'a': 'a'}
    d['b'] = 1
    return d

I get this output:

test.py: note: In function "g":
test.py:4: error: List item 0 has incompatible type "int"
test.py:5: error: Incompatible return value type (got List[str], expected List[Union[str, int]])
test.py: note: In function "f":
test.py:9: error: Incompatible types in assignment (expression has type "int", target has type "str")
test.py:10: error: Incompatible return value type (got Dict[str, str], expected Dict[str, Union[str, int]])

With both these functions, mypy is assuming the type on assignment, then having type errors due to conflicts with the explicitly declared return type.

Surely there should be a way to correctly infer the original type based on the return type?

@JukkaL
Copy link
Collaborator

JukkaL commented Dec 7, 2016

Mypy infers types roughly from top to bottom. This usually makes reasoning about inferred types easier and the implementation is also relatively straightforward. However, there are cases like your example this has undesirable results.

You can add a type annotation to make the error go away:

from typing import Union, Dict, List
def g() -> List[Union[str, int]]:
    x = ['a']  # type: List[Union[str, int]]
    x += [1]
    return x

def f() -> Dict[str, Union[str, int]]:
    d = {'a': 'a'}  # type: Dict[str, Union[str, int]]
    d['b'] = 1
    return d

Modifying type inference to take the return type into consideration in cases like this would be hard and would complicate the relatively simple and predictable (once you understand a few principles) model that mypy currently uses. However, it might be useful to detect some cases like this and give a better error message. Potential better message:

test.py: note: In function "g":
test.py:3: note: Perhaps a type annotation is missing here? Suggestion: List[Union[str, int]]
test.py:4: error: List item 0 has incompatible type "int"
test.py:5: error: Incompatible return value type (got List[str], expected List[Union[str, int]])

@JukkaL
Copy link
Collaborator

JukkaL commented Dec 7, 2016

As it's unlikely that type inference will change for now, I'll update the title to consider a better error message.

@JukkaL JukkaL changed the title Variable assignment assumes a type that might conflict with later explicit declaration Better message when inferred variable type conflicts with later use Dec 7, 2016
@JukkaL JukkaL added the feature label Dec 7, 2016
@TRManderson
Copy link
Contributor Author

If #2542 and #2543 get merged I've got a not-so-nice PR to make that includes this kind of error message (without the suggestion, though, I'm still working on that)

@quartox
Copy link
Contributor

quartox commented May 23, 2017

I will take a look at this.

@quartox
Copy link
Contributor

quartox commented May 23, 2017

Should this note only cover the case when the object type conflicts with the return type or should it also cover the following:

from typing import List, Any
def g() -> List[Any]:
    x = ['a']
    x += [1]
    return x

which currently only outputs

test.py:4: error: List item 0 has incompatible type "int"

I am planning on proceeding with only enhancing the message when it conflicts with the return and not cover the above case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants