Skip to content

Type of variable after isinstance check with 'and' #473

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
spkersten opened this issue Oct 11, 2014 · 8 comments
Closed

Type of variable after isinstance check with 'and' #473

spkersten opened this issue Oct 11, 2014 · 8 comments
Labels

Comments

@spkersten
Copy link
Contributor

After a guard with isinstance, mypy should consider the variable to be of that type.

For example:

def f(x: A) -> None:
    if isinstance(x, B) and x.value:
        pass

class A:
    pass
class B(A):
    value = 0

Here, mypy reports that x doesn't have a field value. This can of course be solved with a cast, but that is annoying to type and clutters the code. At least in simple case, mypy could infer that x is of type B in the rhs of the and-statement and in the block following the if-statement.

@JukkaL JukkaL added the feature label Oct 12, 2014
@JukkaL
Copy link
Collaborator

JukkaL commented Oct 12, 2014

This already works if the condition only has an isinstance check:

def f(x: A) -> None:
    if isinstance(x, B):
        print(x.value)  # Ok

class A:
    pass
class B(A):
    value = 0

Mypy should support more cases, including and expressions (your example should be valid).

Here is another case that could be useful (this could be a separate issue):

def f(x: object) -> None:
    if isinstance(x, int) or isinstance(x, str):   # or isinstance(x, (int, str))
        # type of x should be Union[int, str]
        pass

These improvements are important for proper type checking of None values (currently None is treated pretty much like null in Java, i.e. it is implicitly included in every type). For example, consider this code:

def f(x: Union[int, None]) -> None:
    if x and x > 3:   # Ok
        print(x * 2)   # Ok
    print(x * 2)   # Error, since can't multiply None

Currently there is no error reported for the the second print statement.

@JukkaL
Copy link
Collaborator

JukkaL commented Oct 12, 2014

Added related issues #475 and #476.

@refi64
Copy link
Contributor

refi64 commented Oct 12, 2014

Just to put it out there, the Cobra approach (see Compile-time Nil Tracking) to null values seems nicer, in my opinion, than using Union[T, None]. Basically, it would mean something like this:

def x(a: Nullable[int]) -> int:
    print(a*a) # ok; a is still an int
    return a # error; cannot convert Nullable type to none-Nullable type
    if a: return a # ok; a cannot be None

@gvanrossum
Copy link
Member

My preferred spelling would be Optional[int]. (Nullable reeks of SQL. :-)

On Sun, Oct 12, 2014 at 1:57 PM, Ryan Gonzalez [email protected]
wrote:

Just to put it out there, the Cobra
http://cobra-language.com/docs/quality/ approach (see Compile-time Nil
Tracking) to null values seems nicer, in my opinion, than using Union[T,
None]. Basically, it would mean something like this:

def x(a: Nullable[int]) -> int:
print(a*a) # ok; a is still an int
return a # error; cannot convert Nullable type to none-Nullable type
if a: return a # ok; a cannot be None


Reply to this email directly or view it on GitHub
#473 (comment).

--Guido van Rossum (python.org/~guido)

@refi64
Copy link
Contributor

refi64 commented Oct 12, 2014

@gvanrossum You're very right; I like Optional better.

@JukkaL
Copy link
Collaborator

JukkaL commented Oct 12, 2014

@kirbyfan64 I agree, special syntax would be preferable. But I'm not sure why a*a should be okay if a has an optional type. None * None raises an exception.

@JukkaL
Copy link
Collaborator

JukkaL commented Oct 12, 2014

Added issue #477 for Optional[T].

@JukkaL JukkaL changed the title Type of variable after isinstance check Type of variable after isinstance check with 'and' Oct 13, 2014
@rwbarton
Copy link
Contributor

The original program here has worked since commit 0b151c6. Also, Jukka's "another case" will be addressed by #1712, and the example with Union[int, None] already works under strict optional checking. So closing this as fixed.

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

No branches or pull requests

5 participants