Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions conformance/results/mypy/literals_interactions.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
conformant = "Partial"
notes = """
Does not narrow type of `x` with `x in Literal` type guard pattern.
Does not narrow `str` or `LiteralString` types to `Literal` string types via equality or containment checks.
"""
output = """
literals_interactions.py:14: error: Tuple index out of range [misc]
literals_interactions.py:15: error: Tuple index out of range [misc]
literals_interactions.py:16: error: Tuple index out of range [misc]
literals_interactions.py:17: error: Tuple index out of range [misc]
literals_interactions.py:18: error: Tuple index out of range [misc]
literals_interactions.py:106: error: Argument 1 to "expects_bad_status" has incompatible type "str"; expected "Literal['MALFORMED', 'ABORTED']" [arg-type]
literals_interactions.py:109: error: Argument 1 to "expects_pending_status" has incompatible type "str"; expected "Literal['PENDING']" [arg-type]
literals_interactions.py:111: error: Argument 1 to "expects_bad_status" has incompatible type "str"; expected "Literal['MALFORMED', 'ABORTED']" [arg-type]
literals_interactions.py:113: error: Argument 1 to "expects_bad_status" has incompatible type "str"; expected "Literal['MALFORMED', 'ABORTED']" [arg-type]
literals_interactions.py:116: error: Argument 1 to "expects_bad_status" has incompatible type "str"; expected "Literal['MALFORMED', 'ABORTED']" [arg-type]
literals_interactions.py:119: error: Argument 1 to "expects_pending_status" has incompatible type "str"; expected "Literal['PENDING']" [arg-type]
literals_interactions.py:128: error: Argument 1 to "expects_bad_status" has incompatible type "str"; expected "Literal['MALFORMED', 'ABORTED']" [arg-type]
literals_interactions.py:130: error: Argument 1 to "expects_bad_status" has incompatible type "str"; expected "Literal['MALFORMED', 'ABORTED']" [arg-type]
literals_interactions.py:133: error: Argument 1 to "expects_bad_status" has incompatible type "str"; expected "Literal['MALFORMED', 'ABORTED']" [arg-type]
literals_interactions.py:136: error: Argument 1 to "expects_pending_status" has incompatible type "str"; expected "Literal['PENDING']" [arg-type]
"""
conformance_automated = "Fail"
conformance_automated = "Pass"
errors_diff = """
Line 106: Unexpected errors ['literals_interactions.py:106: error: Argument 1 to "expects_bad_status" has incompatible type "str"; expected "Literal[\\'MALFORMED\\', \\'ABORTED\\']" [arg-type]']
Line 109: Unexpected errors ['literals_interactions.py:109: error: Argument 1 to "expects_pending_status" has incompatible type "str"; expected "Literal[\\'PENDING\\']" [arg-type]']
"""
8 changes: 4 additions & 4 deletions conformance/results/pyrefly/literals_interactions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ conformance_automated = "Pass"
errors_diff = """
"""
output = """
ERROR literals_interactions.py:15:7-8: Index 5 out of range for tuple with 3 elements [bad-index]
ERROR literals_interactions.py:16:7-8: Index -5 out of range for tuple with 3 elements [bad-index]
ERROR literals_interactions.py:17:7-8: Index 4 out of range for tuple with 3 elements [bad-index]
ERROR literals_interactions.py:18:7-9: Index -4 out of range for tuple with 3 elements [bad-index]
ERROR literals_interactions.py:14:7-8: Index 5 out of range for tuple with 3 elements [bad-index]
ERROR literals_interactions.py:15:7-8: Index -5 out of range for tuple with 3 elements [bad-index]
ERROR literals_interactions.py:16:7-8: Index 4 out of range for tuple with 3 elements [bad-index]
ERROR literals_interactions.py:17:7-9: Index -4 out of range for tuple with 3 elements [bad-index]
"""
8 changes: 4 additions & 4 deletions conformance/results/pyright/literals_interactions.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
conformant = "Pass"
output = """
literals_interactions.py:15:5 - error: Index 5 is out of range for type tuple[int, str, list[bool]] (reportGeneralTypeIssues)
literals_interactions.py:16:5 - error: Index -5 is out of range for type tuple[int, str, list[bool]] (reportGeneralTypeIssues)
literals_interactions.py:17:5 - error: Index 4 is out of range for type tuple[int, str, list[bool]] (reportGeneralTypeIssues)
literals_interactions.py:18:5 - error: Index -4 is out of range for type tuple[int, str, list[bool]] (reportGeneralTypeIssues)
literals_interactions.py:14:5 - error: Index 5 is out of range for type tuple[int, str, list[bool]] (reportGeneralTypeIssues)
literals_interactions.py:15:5 - error: Index -5 is out of range for type tuple[int, str, list[bool]] (reportGeneralTypeIssues)
literals_interactions.py:16:5 - error: Index 4 is out of range for type tuple[int, str, list[bool]] (reportGeneralTypeIssues)
literals_interactions.py:17:5 - error: Index -4 is out of range for type tuple[int, str, list[bool]] (reportGeneralTypeIssues)
"""
conformance_automated = "Pass"
errors_diff = """
Expand Down
4 changes: 2 additions & 2 deletions conformance/results/results.html
Original file line number Diff line number Diff line change
Expand Up @@ -569,11 +569,11 @@ <h3>Python Type System Conformance Test Results</h3>
<a class="test_group" href="https://typing.readthedocs.io/en/latest/spec/literal.html">Literals</a>
</th></tr>
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;literals_interactions</th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not narrow type of `x` with `x in Literal` type guard pattern.</p></span></div></th>
<th class="column col2 conformant"><div class="hover-text">Pass*<span class="tooltip-text" id="bottom"><p>Does not narrow `str` or `LiteralString` types to `Literal` string types via equality or containment checks.</p></span></div></th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Deliberately does not allow `str` to be narrowed to literal string types through equality or containment checks due to the possibility of `str` subclasses that could have unexpected equality semantics.</p></span></div></th>
<th class="column col2 conformant"><div class="hover-text">Pass*<span class="tooltip-text" id="bottom"><p>Deliberately does not allow `str` to be narrowed to literal string types through equality or containment checks due to the possibility of `str` subclasses that could have unexpected equality semantics.</p><p>Incorrectly fails to narrow the type `LiteralString & ~Literal["MALFORMED"]` to `Literal["ABORTED"]` after an `== "ABORTED"` check.</p></span></div></th>
</tr>
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;literals_literalstring</th>
<th class="column col2 not-conformant"><div class="hover-text">Unsupported<span class="tooltip-text" id="bottom"><p>Support for `LiteralString` is not implemented.</p></span></div></th>
Expand Down
21 changes: 11 additions & 10 deletions conformance/results/ty/literals_interactions.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
conformance_automated = "Fail"
conformant = "Partial"
conformance_automated = "Pass"
notes = """
Deliberately does not allow `str` to be narrowed to literal string types through equality or containment checks due to the possibility of `str` subclasses that could have unexpected equality semantics.
Incorrectly fails to narrow the type `LiteralString & ~Literal["MALFORMED"]` to `Literal["ABORTED"]` after an `== "ABORTED"` check.
"""
errors_diff = """
Line 106: Unexpected errors ['literals_interactions.py:106:35: error[invalid-argument-type] Argument to function `expects_bad_status` is incorrect: Expected `Literal["MALFORMED", "ABORTED"]`, found `str`']
Line 109: Unexpected errors ['literals_interactions.py:109:32: error[invalid-argument-type] Argument to function `expects_pending_status` is incorrect: Expected `Literal["PENDING"]`, found `str`']
"""
output = """
literals_interactions.py:15:5: error[index-out-of-bounds] Index 5 is out of bounds for tuple `tuple[int, str, list[bool]]` with length 3
literals_interactions.py:16:5: error[index-out-of-bounds] Index -5 is out of bounds for tuple `tuple[int, str, list[bool]]` with length 3
literals_interactions.py:17:5: error[index-out-of-bounds] Index 4 is out of bounds for tuple `tuple[int, str, list[bool]]` with length 3
literals_interactions.py:18:5: error[index-out-of-bounds] Index -4 is out of bounds for tuple `tuple[int, str, list[bool]]` with length 3
literals_interactions.py:106:35: error[invalid-argument-type] Argument to function `expects_bad_status` is incorrect: Expected `Literal["MALFORMED", "ABORTED"]`, found `str`
literals_interactions.py:109:32: error[invalid-argument-type] Argument to function `expects_pending_status` is incorrect: Expected `Literal["PENDING"]`, found `str`
literals_interactions.py:14:5: error[index-out-of-bounds] Index 5 is out of bounds for tuple `tuple[int, str, list[bool]]` with length 3
literals_interactions.py:15:5: error[index-out-of-bounds] Index -5 is out of bounds for tuple `tuple[int, str, list[bool]]` with length 3
literals_interactions.py:16:5: error[index-out-of-bounds] Index 4 is out of bounds for tuple `tuple[int, str, list[bool]]` with length 3
literals_interactions.py:17:5: error[index-out-of-bounds] Index -4 is out of bounds for tuple `tuple[int, str, list[bool]]` with length 3
literals_interactions.py:113:28: error[invalid-argument-type] Argument to function `expects_bad_status` is incorrect: Expected `Literal["MALFORMED", "ABORTED"]`, found `LiteralString & ~Literal["MALFORMED"]`
literals_interactions.py:128:28: error[invalid-argument-type] Argument to function `expects_bad_status` is incorrect: Expected `Literal["MALFORMED", "ABORTED"]`, found `str`
literals_interactions.py:130:28: error[invalid-argument-type] Argument to function `expects_bad_status` is incorrect: Expected `Literal["MALFORMED", "ABORTED"]`, found `str & ~Literal["MALFORMED"]`
literals_interactions.py:133:28: error[invalid-argument-type] Argument to function `expects_bad_status` is incorrect: Expected `Literal["MALFORMED", "ABORTED"]`, found `str`
literals_interactions.py:136:32: error[invalid-argument-type] Argument to function `expects_pending_status` is incorrect: Expected `Literal["PENDING"]`, found `str`
"""
2 changes: 1 addition & 1 deletion conformance/results/zuban/literals_interactions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ conformance_automated = "Pass"
errors_diff = """
"""
output = """
literals_interactions.py:14: error: Tuple index out of range [misc]
literals_interactions.py:15: error: Tuple index out of range [misc]
literals_interactions.py:16: error: Tuple index out of range [misc]
literals_interactions.py:17: error: Tuple index out of range [misc]
literals_interactions.py:18: error: Tuple index out of range [misc]
"""
37 changes: 32 additions & 5 deletions conformance/tests/literals_interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
"""

# Specification: https://typing.readthedocs.io/en/latest/spec/literal.html#interactions-with-other-types-and-features

from enum import Enum
from typing import IO, Any, Final, Generic, Literal, TypeVar, assert_type, overload
from typing import IO, Any, Final, Generic, Literal, TypeVar, LiteralString, assert_type, overload


def func1(v: tuple[int, str, list[bool]], a: Literal[0], b: Literal[5], c: Literal[-5]):
Expand Down Expand Up @@ -93,6 +92,12 @@ def parse_status1(s: str | Status) -> None:
assert_type(s, str)


# > Type checkers may optionally perform additional analysis for both
# > enum and non-enum Literal types beyond what is described in the section above.
#
# > For example, it may be useful to perform narrowing based on things
# > like containment or equality checks:

def expects_bad_status(status: Literal["MALFORMED", "ABORTED"]):
...

Expand All @@ -101,12 +106,34 @@ def expects_pending_status(status: Literal["PENDING"]):
...


def parse_status2(status: str) -> None:
def parse_status2(status: LiteralString) -> None:
if status == "MALFORMED":
expects_bad_status(status) # E? narrowing the type here is sound, but optional per the spec
elif status == "ABORTED":
expects_bad_status(status) # E? narrowing the type here is sound, but optional per the spec

if status in ("MALFORMED", "ABORTED"):
expects_bad_status(status) # E? narrowing the type here is sound, but optional per the spec

if status == "PENDING":
expects_pending_status(status) # E? narrowing the type here is sound, but optional per the spec


# Narrowing `str` to `Literal` strings is unsound given the possiblity of
# user-defined `str` subclasses that could have custom equality semantics,
# but is explicitly listed by the spec as optional analysis that type checkers
# may perform.
def parse_status3(status: str) -> None:
if status == "MALFORMED":
expects_bad_status(status) # E? narrowing the type here is unsound, but allowed per the spec
elif status == "ABORTED":
expects_bad_status(status) # E? narrowing the type here is unsound, but allowed per the spec

if status in ("MALFORMED", "ABORTED"):
return expects_bad_status(status)
expects_bad_status(status) # E? narrowing the type here is unsound, but allowed per the spec

if status == "PENDING":
expects_pending_status(status)
expects_pending_status(status) # E? narrowing the type here is unsound, but allowed per the spec


final_val1: Final = 3
Expand Down