Skip to content
Open
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
18 changes: 9 additions & 9 deletions conformance/results/mypy/narrowing_typeis.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
conformant = "Pass"
output = """
narrowing_typeis.py:105: error: "TypeIs" functions must have a positional argument [valid-type]
narrowing_typeis.py:110: error: "TypeIs" functions must have a positional argument [valid-type]
narrowing_typeis.py:132: error: Argument 1 to "takes_callable_str" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], str]" [arg-type]
narrowing_typeis.py:152: error: Argument 1 to "takes_callable_str_proto" has incompatible type "Callable[[object], TypeIs[int]]"; expected "CallableStrProto" [arg-type]
narrowing_typeis.py:152: note: "CallableStrProto.__call__" has type "def __call__(self, val: object) -> str"
narrowing_typeis.py:169: error: Argument 1 to "takes_typeguard" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], TypeGuard[int]]" [arg-type]
narrowing_typeis.py:170: error: Argument 1 to "takes_typeis" has incompatible type "Callable[[object], TypeGuard[int]]"; expected "Callable[[object], TypeIs[int]]" [arg-type]
narrowing_typeis.py:191: error: Argument 1 to "takes_int_typeis" has incompatible type "Callable[[object], TypeIs[bool]]"; expected "Callable[[object], TypeIs[int]]" [arg-type]
narrowing_typeis.py:195: error: Narrowed type "str" is not a subtype of input type "int" [narrowed-type-not-subtype]
narrowing_typeis.py:199: error: Narrowed type "list[int]" is not a subtype of input type "list[object]" [narrowed-type-not-subtype]
narrowing_typeis.py:115: error: "TypeIs" functions must have a positional argument [valid-type]
narrowing_typeis.py:137: error: Argument 1 to "takes_callable_str" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], str]" [arg-type]
narrowing_typeis.py:157: error: Argument 1 to "takes_callable_str_proto" has incompatible type "Callable[[object], TypeIs[int]]"; expected "CallableStrProto" [arg-type]
narrowing_typeis.py:157: note: "CallableStrProto.__call__" has type "def __call__(self, val: object) -> str"
narrowing_typeis.py:174: error: Argument 1 to "takes_typeguard" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], TypeGuard[int]]" [arg-type]
narrowing_typeis.py:175: error: Argument 1 to "takes_typeis" has incompatible type "Callable[[object], TypeGuard[int]]"; expected "Callable[[object], TypeIs[int]]" [arg-type]
narrowing_typeis.py:196: error: Argument 1 to "takes_int_typeis" has incompatible type "Callable[[object], TypeIs[bool]]"; expected "Callable[[object], TypeIs[int]]" [arg-type]
narrowing_typeis.py:200: error: Narrowed type "str" is not a subtype of input type "int" [narrowed-type-not-subtype]
narrowing_typeis.py:204: error: Narrowed type "list[int]" is not a subtype of input type "list[object]" [narrowed-type-not-subtype]
"""
conformance_automated = "Pass"
errors_diff = """
Expand Down
16 changes: 8 additions & 8 deletions conformance/results/pyrefly/narrowing_typeis.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ conformance_automated = "Pass"
errors_diff = """
"""
output = """
ERROR narrowing_typeis.py:105:9-13: Type guard functions must accept at least one positional argument [bad-function-definition]
ERROR narrowing_typeis.py:110:9-13: Type guard functions must accept at least one positional argument [bad-function-definition]
ERROR narrowing_typeis.py:132:20-36: Argument `(val: object) -> TypeIs[int]` is not assignable to parameter `f` with type `(object) -> str` in function `takes_callable_str` [bad-argument-type]
ERROR narrowing_typeis.py:152:26-42: Argument `(val: object) -> TypeIs[int]` is not assignable to parameter `f` with type `CallableStrProto` in function `takes_callable_str_proto` [bad-argument-type]
ERROR narrowing_typeis.py:169:17-30: Argument `(val: object) -> TypeIs[int]` is not assignable to parameter `f` with type `(object) -> TypeGuard[int]` in function `takes_typeguard` [bad-argument-type]
ERROR narrowing_typeis.py:170:14-30: Argument `(val: object) -> TypeGuard[int]` is not assignable to parameter `f` with type `(object) -> TypeIs[int]` in function `takes_typeis` [bad-argument-type]
ERROR narrowing_typeis.py:191:18-29: Argument `(val: object) -> TypeIs[bool]` is not assignable to parameter `f` with type `(object) -> TypeIs[int]` in function `takes_int_typeis` [bad-argument-type]
ERROR narrowing_typeis.py:195:5-15: Return type `str` must be assignable to the first argument type `int` [bad-function-definition]
ERROR narrowing_typeis.py:199:5-24: Return type `list[int]` must be assignable to the first argument type `list[object]` [bad-function-definition]
ERROR narrowing_typeis.py:115:9-13: Type guard functions must accept at least one positional argument [bad-function-definition]
ERROR narrowing_typeis.py:137:20-36: Argument `(val: object) -> TypeIs[int]` is not assignable to parameter `f` with type `(object) -> str` in function `takes_callable_str` [bad-argument-type]
ERROR narrowing_typeis.py:157:26-42: Argument `(val: object) -> TypeIs[int]` is not assignable to parameter `f` with type `CallableStrProto` in function `takes_callable_str_proto` [bad-argument-type]
ERROR narrowing_typeis.py:174:17-30: Argument `(val: object) -> TypeIs[int]` is not assignable to parameter `f` with type `(object) -> TypeGuard[int]` in function `takes_typeguard` [bad-argument-type]
ERROR narrowing_typeis.py:175:14-30: Argument `(val: object) -> TypeGuard[int]` is not assignable to parameter `f` with type `(object) -> TypeIs[int]` in function `takes_typeis` [bad-argument-type]
ERROR narrowing_typeis.py:196:18-29: Argument `(val: object) -> TypeIs[bool]` is not assignable to parameter `f` with type `(object) -> TypeIs[int]` in function `takes_int_typeis` [bad-argument-type]
ERROR narrowing_typeis.py:200:5-15: Return type `str` must be assignable to the first argument type `int` [bad-function-definition]
ERROR narrowing_typeis.py:204:5-24: Return type `list[int]` must be assignable to the first argument type `list[object]` [bad-function-definition]
"""
16 changes: 8 additions & 8 deletions conformance/results/pyright/narrowing_typeis.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,34 @@ conformance_automated = "Pass"
errors_diff = """
"""
output = """
narrowing_typeis.py:105:9 - error: User-defined type guard functions and methods must have at least one input parameter (reportGeneralTypeIssues)
narrowing_typeis.py:110:9 - error: User-defined type guard functions and methods must have at least one input parameter (reportGeneralTypeIssues)
narrowing_typeis.py:132:20 - error: Argument of type "(val: object) -> TypeIs[int]" cannot be assigned to parameter "f" of type "(object) -> str" in function "takes_callable_str"
narrowing_typeis.py:115:9 - error: User-defined type guard functions and methods must have at least one input parameter (reportGeneralTypeIssues)
narrowing_typeis.py:137:20 - error: Argument of type "(val: object) -> TypeIs[int]" cannot be assigned to parameter "f" of type "(object) -> str" in function "takes_callable_str"
  Type "(val: object) -> TypeIs[int]" is not assignable to type "(object) -> str"
    Function return type "TypeIs[int]" is incompatible with type "str"
      "TypeIs[int]" is not assignable to "str"
      "bool" is not assignable to "str" (reportArgumentType)
narrowing_typeis.py:152:26 - error: Argument of type "(val: object) -> TypeIs[int]" cannot be assigned to parameter "f" of type "CallableStrProto" in function "takes_callable_str_proto"
narrowing_typeis.py:157:26 - error: Argument of type "(val: object) -> TypeIs[int]" cannot be assigned to parameter "f" of type "CallableStrProto" in function "takes_callable_str_proto"
  Type "(val: object) -> TypeIs[int]" is not assignable to type "(val: object) -> str"
    Function return type "TypeIs[int]" is incompatible with type "str"
      "TypeIs[int]" is not assignable to "str"
      "bool" is not assignable to "str" (reportArgumentType)
narrowing_typeis.py:169:17 - error: Argument of type "(val: object) -> TypeIs[int]" cannot be assigned to parameter "f" of type "(object) -> TypeGuard[int]" in function "takes_typeguard"
narrowing_typeis.py:174:17 - error: Argument of type "(val: object) -> TypeIs[int]" cannot be assigned to parameter "f" of type "(object) -> TypeGuard[int]" in function "takes_typeguard"
  Type "(val: object) -> TypeIs[int]" is not assignable to type "(object) -> TypeGuard[int]"
    Function return type "TypeIs[int]" is incompatible with type "TypeGuard[int]"
      "TypeIs[int]" is not assignable to "TypeGuard[int]"
      "bool" is not assignable to "TypeGuard[int]" (reportArgumentType)
narrowing_typeis.py:170:14 - error: Argument of type "(val: object) -> TypeGuard[int]" cannot be assigned to parameter "f" of type "(object) -> TypeIs[int]" in function "takes_typeis"
narrowing_typeis.py:175:14 - error: Argument of type "(val: object) -> TypeGuard[int]" cannot be assigned to parameter "f" of type "(object) -> TypeIs[int]" in function "takes_typeis"
  Type "(val: object) -> TypeGuard[int]" is not assignable to type "(object) -> TypeIs[int]"
    Function return type "TypeGuard[int]" is incompatible with type "TypeIs[int]"
      "TypeGuard[int]" is not assignable to "TypeIs[int]"
      "bool" is not assignable to "TypeIs[int]" (reportArgumentType)
narrowing_typeis.py:191:18 - error: Argument of type "(val: object) -> TypeIs[bool]" cannot be assigned to parameter "f" of type "(object) -> TypeIs[int]" in function "takes_int_typeis"
narrowing_typeis.py:196:18 - error: Argument of type "(val: object) -> TypeIs[bool]" cannot be assigned to parameter "f" of type "(object) -> TypeIs[int]" in function "takes_int_typeis"
  Type "(val: object) -> TypeIs[bool]" is not assignable to type "(object) -> TypeIs[int]"
    Function return type "TypeIs[bool]" is incompatible with type "TypeIs[int]"
      "TypeIs[bool]" is not assignable to "TypeIs[int]"
        Type parameter "T@TypeIs" is invariant, but "bool" is not the same as "int"
      "bool" is not assignable to "TypeIs[int]" (reportArgumentType)
narrowing_typeis.py:195:27 - error: Return type of TypeIs ("str") is not consistent with value parameter type ("int") (reportGeneralTypeIssues)
narrowing_typeis.py:199:45 - error: Return type of TypeIs ("list[int]") is not consistent with value parameter type ("list[object]") (reportGeneralTypeIssues)
narrowing_typeis.py:200:27 - error: Return type of TypeIs ("str") is not consistent with value parameter type ("int") (reportGeneralTypeIssues)
narrowing_typeis.py:204:45 - error: Return type of TypeIs ("list[int]") is not consistent with value parameter type ("list[object]") (reportGeneralTypeIssues)
"""
18 changes: 9 additions & 9 deletions conformance/results/ty/narrowing_typeis.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ Line 35: Unexpected errors ['narrowing_typeis.py:35:18: error[invalid-assignment
"""
output = """
narrowing_typeis.py:35:18: error[invalid-assignment] Object of type `object` is not assignable to `int`
narrowing_typeis.py:105:23: error[invalid-type-guard-definition] `TypeIs` function must have a parameter to narrow
narrowing_typeis.py:110:22: error[invalid-type-guard-definition] `TypeIs` function must have a parameter to narrow
narrowing_typeis.py:132:20: error[invalid-argument-type] Argument to function `takes_callable_str` is incorrect: Expected `(object, /) -> str`, found `def simple_typeguard(val: object) -> TypeIs[int]`
narrowing_typeis.py:152:26: error[invalid-argument-type] Argument to function `takes_callable_str_proto` is incorrect: Expected `CallableStrProto`, found `def simple_typeguard(val: object) -> TypeIs[int]`
narrowing_typeis.py:169:17: error[invalid-argument-type] Argument to function `takes_typeguard` is incorrect: Expected `(object, /) -> TypeGuard[int]`, found `def is_int_typeis(val: object) -> TypeIs[int]`
narrowing_typeis.py:170:14: error[invalid-argument-type] Argument to function `takes_typeis` is incorrect: Expected `(object, /) -> TypeIs[int]`, found `def is_int_typeguard(val: object) -> TypeGuard[int]`
narrowing_typeis.py:191:18: error[invalid-argument-type] Argument to function `takes_int_typeis` is incorrect: Expected `(object, /) -> TypeIs[int]`, found `def bool_typeis(val: object) -> TypeIs[bool]`
narrowing_typeis.py:195:27: error[invalid-type-guard-definition] Narrowed type `str` is not assignable to the declared parameter type `int`
narrowing_typeis.py:199:45: error[invalid-type-guard-definition] Narrowed type `list[int]` is not assignable to the declared parameter type `list[object]`
narrowing_typeis.py:110:23: error[invalid-type-guard-definition] `TypeIs` function must have a parameter to narrow
narrowing_typeis.py:115:22: error[invalid-type-guard-definition] `TypeIs` function must have a parameter to narrow
narrowing_typeis.py:137:20: error[invalid-argument-type] Argument to function `takes_callable_str` is incorrect: Expected `(object, /) -> str`, found `def simple_typeguard(val: object) -> TypeIs[int]`
narrowing_typeis.py:157:26: error[invalid-argument-type] Argument to function `takes_callable_str_proto` is incorrect: Expected `CallableStrProto`, found `def simple_typeguard(val: object) -> TypeIs[int]`
narrowing_typeis.py:174:17: error[invalid-argument-type] Argument to function `takes_typeguard` is incorrect: Expected `(object, /) -> TypeGuard[int]`, found `def is_int_typeis(val: object) -> TypeIs[int]`
narrowing_typeis.py:175:14: error[invalid-argument-type] Argument to function `takes_typeis` is incorrect: Expected `(object, /) -> TypeIs[int]`, found `def is_int_typeguard(val: object) -> TypeGuard[int]`
narrowing_typeis.py:196:18: error[invalid-argument-type] Argument to function `takes_int_typeis` is incorrect: Expected `(object, /) -> TypeIs[int]`, found `def bool_typeis(val: object) -> TypeIs[bool]`
narrowing_typeis.py:200:27: error[invalid-type-guard-definition] Narrowed type `str` is not assignable to the declared parameter type `int`
narrowing_typeis.py:204:45: error[invalid-type-guard-definition] Narrowed type `list[int]` is not assignable to the declared parameter type `list[object]`
"""
16 changes: 8 additions & 8 deletions conformance/results/zuban/narrowing_typeis.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ conformance_automated = "Pass"
errors_diff = """
"""
output = """
narrowing_typeis.py:105: error: "TypeIs" functions must have a positional argument [misc]
narrowing_typeis.py:110: error: "TypeIs" functions must have a positional argument [misc]
narrowing_typeis.py:132: error: Argument 1 to "takes_callable_str" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], str]" [arg-type]
narrowing_typeis.py:152: error: Argument 1 to "takes_callable_str_proto" has incompatible type "Callable[[object], TypeIs[int]]"; expected "CallableStrProto" [arg-type]
narrowing_typeis.py:169: error: Argument 1 to "takes_typeguard" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], TypeGuard[int]]" [arg-type]
narrowing_typeis.py:170: error: Argument 1 to "takes_typeis" has incompatible type "Callable[[object], TypeGuard[int]]"; expected "Callable[[object], TypeIs[int]]" [arg-type]
narrowing_typeis.py:191: error: Argument 1 to "takes_int_typeis" has incompatible type "Callable[[object], TypeIs[bool]]"; expected "Callable[[object], TypeIs[int]]" [arg-type]
narrowing_typeis.py:195: error: Narrowed type "str" is not a subtype of input type "int" [narrowed-type-not-subtype]
narrowing_typeis.py:199: error: Narrowed type "list[int]" is not a subtype of input type "list[object]" [narrowed-type-not-subtype]
narrowing_typeis.py:115: error: "TypeIs" functions must have a positional argument [misc]
narrowing_typeis.py:137: error: Argument 1 to "takes_callable_str" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], str]" [arg-type]
narrowing_typeis.py:157: error: Argument 1 to "takes_callable_str_proto" has incompatible type "Callable[[object], TypeIs[int]]"; expected "CallableStrProto" [arg-type]
narrowing_typeis.py:174: error: Argument 1 to "takes_typeguard" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], TypeGuard[int]]" [arg-type]
narrowing_typeis.py:175: error: Argument 1 to "takes_typeis" has incompatible type "Callable[[object], TypeGuard[int]]"; expected "Callable[[object], TypeIs[int]]" [arg-type]
narrowing_typeis.py:196: error: Argument 1 to "takes_int_typeis" has incompatible type "Callable[[object], TypeIs[bool]]"; expected "Callable[[object], TypeIs[int]]" [arg-type]
narrowing_typeis.py:200: error: Narrowed type "str" is not a subtype of input type "int" [narrowed-type-not-subtype]
narrowing_typeis.py:204: error: Narrowed type "list[int]" is not a subtype of input type "list[object]" [narrowed-type-not-subtype]
"""
7 changes: 6 additions & 1 deletion conformance/tests/narrowing_typeis.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ async def func2(val: int | Awaitable[int]):
x: int = await val
return x
else:
assert_type(val, int)
# We can't say much here. The strictly correct answer is
# (int | Awaitable[int]) & ~Awaitable[Any], but conformant implementations
# may simplify this.
# But it should definitely remain assignable to `int | Awaitable[int]`.
y: int | Awaitable[int] = val
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I feel like this isn't testing all that much anymore. Not sure how to improve it, though ^^;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, unfortunately I can't think of a better way here. Using theoretically correct intersection semantics is not always practical. For reference here are the tests I added to pycroscope while looking at this: https://github.com/JelleZijlstra/pycroscope/pull/444/changes#diff-17d47f7718e5c338fb6076c1e2971a2ca798555e661e881cd1653cf5e54d99fe

I tried both TypeIs[Awaitable[Any]] and TypeIs[Awaitable[object]].

Among the current type checkers, two type checkers actually have explicit intersections, but neither produces the full theoretically correct types. Ty treats the Awaitable[Any] TypeIs as if it's Awaitable[object]. That behaves better in some cases but worse in others; in this check it means that y: int = await val is rejected because val might also be int & Awaitable[object]. Pycroscope (unreleased version) doesn't do that but it drops negation types, so the else branch types are simpler.

Three of the other type checkers (mypy, zuban, pyright) narrow to Awaitable[int] and int for both the Any and object guards; pyrefly narrows to Awaitable[Any] for the TypeIs[Awaitable[Any]]. This is unsound but perhaps more practical than the precise intersection behavior.

return y


T_A = TypeVar("T_A", bound="A")
Expand Down