Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 305
Proposed clarification of spec for int/float/complex promotion#1748
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
d2a3bdfcfefa40cf3486f6155dbda442bfe9dd5297File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,12 @@ | ||
| conformant = "Pass" | ||
| conformant = "Partial" | ||
| notes = """ | ||
| Does not narrow from float to int after isinstance() check | ||
| """ | ||
| output = """ | ||
| specialtypes_promotions.py:13: error: "float" has no attribute "numerator" [attr-defined] | ||
| specialtypes_promotions.py:17: error: "float" has no attribute "numerator" [attr-defined] | ||
| specialtypes_promotions.py:33: error: Incompatible return value type (got "complex", expected "float") [return-value] | ||
| """ | ||
| conformance_automated = "Pass" | ||
| conformance_automated = "Fail" | ||
| errors_diff = """ | ||
| Line 26: Expected 1 errors | ||
| """ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,13 @@ | ||
| conformant = "Partial" | ||
| notes = """ | ||
| Does not reject use of attribute that is compatible only with float. | ||
| Does not narrow from float to int after isinstance() check | ||
| """ | ||
| output = """ | ||
| specialtypes_promotions.py:33:8 Incompatible return type [7]: Expected `float` but got `complex`. | ||
| """ | ||
| conformance_automated = "Fail" | ||
| errors_diff = """ | ||
| Line 13: Expected 1 errors | ||
| Line 17: Expected 1 errors | ||
| Line 26: Expected 1 errors | ||
| """ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,2 @@ | ||
| version = "pyre 0.9.23" | ||
| test_duration = 10.7 | ||
| test_duration = 10.4 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,2 @@ | ||
| version = "pyright 1.1.402" | ||
| test_duration = 1.8 | ||
| test_duration = 1.5 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2,15 +2,36 @@ | ||
| Tests "type promotions" for float and complex when they appear in annotations. | ||
| """ | ||
| from typing import assert_type | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not clear to me which of these should report errors, and which shouldn't. deffoo(x: float):
assert_type(x, float|int)
defgoo(x: float):
assert_type(x, float)
defhoo(x: float|int):
assert_type(x, float)MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This follows from the definitions in https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions . Every time we're in a type expression, float means Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (So to spell it out, the answer is that none of those should report an error, because "parameter annotation" and "second argument to | ||
| # Specification: https://typing.readthedocs.io/en/latest/spec/special-types.html#special-cases-for-float-and-complex | ||
| v1: float = 1 | ||
| v2: complex = 1.2 | ||
| v2 = 1 | ||
| v1: int = 1 | ||
| v2: float = 1 | ||
| v3: float = v1 | ||
| v4: complex = 1.2 | ||
| v4 = 1 | ||
| def func1(f: float) -> int: | ||
| f.numerator # E: attribute exists on int but not float | ||
Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think worth having an unguarded
| ||
| if isinstance(f, float): | ||
| f.hex() # OK (attribute exists on float but not int) | ||
| return 1 | ||
| else: | ||
| assert_type(f, int) | ||
erictraut marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| # Make sure type checkers don't treat this branch as unreachable | ||
| # and skip checking it. | ||
| return "x" # E | ||
| def func1(f: float): | ||
| f.numerator # E | ||
| if not isinstance(f, float): | ||
| f.numerator # OK | ||
| def func2(x: int) -> float: | ||
| if x == 0: | ||
| return 1 | ||
| elif x == 1: | ||
| return 1j # E | ||
| elif x > 10: | ||
| return x | ||
| else: | ||
| return 1.0 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -110,11 +110,25 @@ Special cases for ``float`` and ``complex`` | ||
| Python's numeric types ``complex``, ``float`` and ``int`` are not | ||
| subtypes of each other, but to support common use cases, the type | ||
| system contains a straightforward shortcut: | ||
| when an argument is annotated as having | ||
| type ``float``, an argument of type ``int`` is acceptable; similar, | ||
| for an argument annotated as having type ``complex``, arguments of | ||
| type ``float`` or ``int`` are acceptable. | ||
| system contains a special case. | ||
| When a reference to the built-in type ``float`` appears in a :term:`type expression`, | ||
| it is interpreted as if it were a union of the built-in types ``float`` and ``int``. | ||
| Similarly, when a reference to the type ``complex`` appears, it is interpreted as | ||
| a union of the built-in types ``complex``, ``float`` and ``int``. | ||
| These implicit unions behave exactly like the corresponding explicit union types, | ||
| but type checkers may choose to display them differently in user-visible output | ||
| for clarity. | ||
| Type checkers should support narrowing the type of a variable to exactly ``float`` | ||
| or ``int``, without the implicit union, through a call to ``isinstance()``:: | ||
JelleZijlstra marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| def f(x: float) -> None: | ||
| reveal_type(x) # float | int, but type checkers may display just "float" | ||
| if isinstance(x, float): | ||
| reveal_type(x) # float | ||
| else: | ||
| reveal_type(x) # int | ||
| .. _`type-brackets`: | ||
Uh oh!
There was an error while loading. Please reload this page.