Skip to content

Invalid handling type narrowing with inf/float due to duck typing #12824

Closed
@CarliJoy

Description

@CarliJoy

Bug Report

Due to duck typing handling type narrowing within a function accepting both int and float (even explicitly) doesn't work correctly.

To Reproduce
Consider this code, that actually leads to a type error

from typing import NewType

Euro = NewType("Euro", float)

def to_eur(user_in: int | float | str) -> Euro:
    reveal_type(user_in) # int | float | str as expected
    if isinstance(user_in, float):
        reveal_type(user_in) # float
        return Euro(user_in)
    reveal_type(user_in) # str, but expected str | int
    converted = float(user_in.rstrip("€"))
    return Euro(converted)
    

print(to_eur(10))  # Raises type error as int has no method rstrip

Expected Behavior
I would expect that MyPy would warn me and that the expected reveal_type after the the isinstance call is int | float
This should be even the case, if int is not explicitly given.

Consider the modification of above:

from typing import NewType

Euro = NewType("Euro", float)

def to_eur(user_in: float | str) -> Euro:
    reveal_type(user_in) # float | str as expected
    if isinstance(user_in, float):
        reveal_type(user_in) # float
        return Euro(user_in)
    reveal_type(user_in) # str
    converted = float(user_in.rstrip("€"))
    return Euro(converted)
    

print(to_eur(10))   # Raises type error as int has no method rstrip

would still raise a runtime type error and no typing error at all.

Also handling all duck types explicitly as unions when type narrowing would probably handle the non reachable bugs described in
#12643.
This is also suggested in #11516

Actual Behavior
No error / warning raised by MyPy

Your Environment

See MyPy Playground

  • Mypy version used: 0.950
  • Mypy command-line flags: no
  • Python version used: 3.10
  • Operating system and version: Fedora/Online

Maybe related issues:
#11511

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-type-narrowingConditional type narrowing / binder

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions