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

Skip to content

Taking a slice that contains unions produces Any #4286

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
rserbitar opened this issue Nov 27, 2017 · 9 comments · Fixed by #6475
Closed

Taking a slice that contains unions produces Any #4286

rserbitar opened this issue Nov 27, 2017 · 9 comments · Fixed by #6475
Assignees
Labels

Comments

@rserbitar
Copy link

rserbitar commented Nov 27, 2017

def a() -> typing.Union[typing.Tuple[str, str, str],
                        typing.Tuple[typing.List[str], typing.List[str], typing.List[str]]]:
    return '1', '1', '1'


def b() -> typing.Union[typing.Tuple[str, str, str],
                        typing.Tuple[typing.List[str], typing.List[str], typing.List[str]]]:
    return a()


def c() -> typing.Union[typing.Tuple[str, str, str],
                        typing.Tuple[typing.List[str], typing.List[str], typing.List[str]]]:
    x, y, z = a()
    return x, y, z

Result:
error: Incompatible return value type (got "Tuple[Union[str, List[str]], Union[str, List[str]], Union[str, List[str]]]", expected "Union[Tuple[str, str, str], Tuple[List[str], List[str], List[str]]]")

Why?

@ilevkivskyi
Copy link
Member

Because after you unpacked, there are three independent variables x, y, and z each with type Union[str, List[str]], mypy does not store any cross-variable constraints like if x is str then y should be also str. And I doubt it ever will.

@rserbitar
Copy link
Author

This however works fine:

def a() -> typing.Union[typing.Tuple[str, str, str],
                        typing.Tuple[typing.List[str], typing.List[str], typing.List[str]]]:
    return '1', '1', '1'

def c() -> typing.Union[typing.Tuple[str, str, str],
                        typing.Tuple[typing.List[str], typing.List[str], typing.List[str]]]:
    x, y, z = a()[:]
    return x, y, z

@ilevkivskyi
Copy link
Member

ilevkivskyi commented Nov 27, 2017

This however works fine:

And this is a bug!

def c() -> typing.Union[typing.Tuple[str, str, str],
                        typing.Tuple[typing.List[str], typing.List[str], typing.List[str]]]:
    x, y, z = a()[:]
    reveal_type(x)  # Revealed type is Any
    return x, y, z

I think however this is not an independent problem, but a manifestation of a known problem of interactions between unions and overloads. @JukkaL what do you think?

@ilevkivskyi ilevkivskyi added the bug mypy got something wrong label Nov 27, 2017
@ilevkivskyi ilevkivskyi changed the title Errors when unpacking tuples with union Taking a slice that contains unions produces Any Nov 27, 2017
@JukkaL
Copy link
Collaborator

JukkaL commented Nov 27, 2017

Looks like there are two problems. First, the fallback of the tuple types seems to be Tuple[Any, ...], which is not right. Second, we should special case unions in type inference of indexing expressions. Currently it just falls back to calling __getitem__ which loses the special semantics for tuple types.

@ilevkivskyi
Copy link
Member

ilevkivskyi commented Nov 27, 2017

First, the fallback of the tuple types seems to be Tuple[Any, ...], which is not right.

There is an issue for this already, and I am going to fix it soon (I am going to go with join like for other similar cases).

Second, we should special case unions in type inference of indexing expressions. Currently it just falls back to calling __getitem__ which loses the special semantics for tuple types.

I think with the first one fixed, this seems to be not urgent.

@JukkaL
Copy link
Collaborator

JukkaL commented Nov 28, 2017

I think with the first one fixed, this seems to be not urgent.

Yes, the first issue seems more urgent. I'll create a new issue to track second issue.

@JukkaL
Copy link
Collaborator

JukkaL commented Nov 28, 2017

Actually we can use this issue to track the second issues. Here's a simplified example:

from typing import Union, Tuple
t: Union[Tuple[int, float], Tuple[str, bool]]
reveal_type(t[0])  # Revealed type is 'Any'
reveal_type(t[:])  # Revealed type is 'builtins.tuple[Any]'

The expected revealed types are Union[int, str] and Union[Tuple[int, float], Tuple[str, bool]]. We lose both item types and the number of items in a tuple.

@ilevkivskyi
Copy link
Member

@JukkaL

Actually we can use this issue to track the second issues. Here's a simplified example:

Your tuple fallback PR causes a bunch of errors internally because fallback is now builtins.tuple[builtins.object] instead of builtins.tuple[Any]. This is however probably easy to fix. Special casing indexing unions (and maybe some other special methods on unions) makes sense to me.

@ilevkivskyi
Copy link
Member

@JukkaL #6475 fixes the problem.

ilevkivskyi added a commit that referenced this issue Feb 26, 2019
Fixes #4286
Fixes #2509

The fix is straightforward, map the indexing through union types. I decided to use the existing error message mentioning the full type. IMO `Value of type "Union[int, List[int]]" is not indexable` is better than `Value of type "int" is not idexable`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants