Skip to content

Conversation

@pkch
Copy link
Contributor

@pkch pkch commented Mar 14, 2017

Fixes #2993

Copy link
Member

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add unit tests?

mypy/checker.py Outdated
type = erase_typevars(type.items()[0].ret_type)

types.append(type)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are too many blank lines here. IMO the only blank line should be outside the for-loop, before the assert on line 2720 below.

@pkch pkch force-pushed the fix-isinstance-inference branch from a61bf32 to 79a8085 Compare March 14, 2017 20:30
@ilevkivskyi
Copy link
Member

It looks like all commits from this PR and from #2995 are also included in #3005. I have made a review on the latter that also concern this PR and #2995.

For the future, I would propose to have non-overlapping PRs, it will be much easier to understand them.

mypy/semanal.py Outdated
# bar in its namespace. This must be done for all types of bar.
file = base.node
assert isinstance(file, (MypyFile, type(None)))
file = cast(Optional[MypyFile], base.node)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment describing why we don't use assert isinstance here.

mypy/semanal.py Outdated
# the build would terminate after semantic analysis
# and we wouldn't be able to report any type errors.
full_name = '%s.%s' % (file.fullname() if file is not None else None, expr.name)
full_name = '%s.%s' % (file.fullname() if file is not None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change seems unnecessary now?

from typing import *
def f(x: Union[int, str], typ: type) -> None:
if isinstance(x, (typ, int)):
x + 1 # E: Unsupported operand types for + (likely involving Union)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add also an else: block and do a reveal_type(x) in that block. Add another reveal_type(x) just after the if statement.

if isinstance(x, (typ, int)):
x + 1 # E: Unsupported operand types for + (likely involving Union)
[builtins fixtures/isinstancelist.pyi]

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add test for the type object that is Type[A] or similar. Example:

class A: pass

def f(x: Union[int, A], a: Type[A]) -> None:
    if isinstance(x, a):
        reveal_type(x)
    elif isinstance(x, int):
        reveal_type(x)
    else:
        reveal_type(x)
    reveal_type(x)

@pkch pkch force-pushed the fix-isinstance-inference branch from bca997d to 6ea4f4d Compare March 18, 2017 21:30
@pkch pkch force-pushed the fix-isinstance-inference branch from 2fa26d1 to be30faa Compare March 19, 2017 01:58
return UnionType(types)
types.append(TypeRange(type, is_upper_bound=False))
elif isinstance(type, TypeType):
types.append(TypeRange(type.item, is_upper_bound=True))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment here describing why is_upper_bound=True.

mypy/checker.py Outdated
types.append(TypeRange(type.item, is_upper_bound=True))
else: # we didn't see an actual type, but rather a variable whose value is unknown to us
return None
assert len(types) != 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should return None if the length if 0? For example, what happens if we have isinstance(x, ())?

x + 1 # E: Unsupported operand types for + (likely involving Union)
reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.str]'
else:
reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.str]'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we could actually infer the type to be builtins.str, since we know that it can't be builtins.int due to the isinstance check.

reveal_type(x) # E: Revealed type is '__main__.A'
reveal_type(x) # E: Revealed type is 'Union[builtins.int, __main__.A]'

[builtins fixtures/isinstancelist.pyi]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not directly related, but can you add a test case that does something like isinstance(x, ())?

mypy/checker.py Outdated
if current_type:
if is_proper_subtype(current_type, proposed_type):
# Expression is always of type proposed_type
if not any(type_range.is_upper_bound for type_range in proposed_type_ranges) \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use if (...)" to avoid the use of \.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants