Skip to content

Commit 25e73e5

Browse files
conformance: Fix TypeIs Any intersection case (#2236)
The `assert_type(val, int)` here is incorrect in the negative case if a type checker is sufficiently precise in its implementation of intersections. ty currently infers int & ~Awaitable[object], apparently because it has chosen to always use the top materialization of TypeIs. A change I am about to make to pycroscope will have it infer `int | Awaitable[int]`, because it drops the negated part of Not types.
1 parent ca2a7db commit 25e73e5

File tree

6 files changed

+48
-43
lines changed

6 files changed

+48
-43
lines changed

conformance/results/mypy/narrowing_typeis.toml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
conformant = "Pass"
22
output = """
3-
narrowing_typeis.py:105: error: "TypeIs" functions must have a positional argument [valid-type]
43
narrowing_typeis.py:110: error: "TypeIs" functions must have a positional argument [valid-type]
5-
narrowing_typeis.py:132: error: Argument 1 to "takes_callable_str" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], str]" [arg-type]
6-
narrowing_typeis.py:152: error: Argument 1 to "takes_callable_str_proto" has incompatible type "Callable[[object], TypeIs[int]]"; expected "CallableStrProto" [arg-type]
7-
narrowing_typeis.py:152: note: "CallableStrProto.__call__" has type "def __call__(self, val: object) -> str"
8-
narrowing_typeis.py:169: error: Argument 1 to "takes_typeguard" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], TypeGuard[int]]" [arg-type]
9-
narrowing_typeis.py:170: error: Argument 1 to "takes_typeis" has incompatible type "Callable[[object], TypeGuard[int]]"; expected "Callable[[object], TypeIs[int]]" [arg-type]
10-
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]
11-
narrowing_typeis.py:195: error: Narrowed type "str" is not a subtype of input type "int" [narrowed-type-not-subtype]
12-
narrowing_typeis.py:199: error: Narrowed type "list[int]" is not a subtype of input type "list[object]" [narrowed-type-not-subtype]
4+
narrowing_typeis.py:115: error: "TypeIs" functions must have a positional argument [valid-type]
5+
narrowing_typeis.py:137: error: Argument 1 to "takes_callable_str" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], str]" [arg-type]
6+
narrowing_typeis.py:157: error: Argument 1 to "takes_callable_str_proto" has incompatible type "Callable[[object], TypeIs[int]]"; expected "CallableStrProto" [arg-type]
7+
narrowing_typeis.py:157: note: "CallableStrProto.__call__" has type "def __call__(self, val: object) -> str"
8+
narrowing_typeis.py:174: error: Argument 1 to "takes_typeguard" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], TypeGuard[int]]" [arg-type]
9+
narrowing_typeis.py:175: error: Argument 1 to "takes_typeis" has incompatible type "Callable[[object], TypeGuard[int]]"; expected "Callable[[object], TypeIs[int]]" [arg-type]
10+
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]
11+
narrowing_typeis.py:200: error: Narrowed type "str" is not a subtype of input type "int" [narrowed-type-not-subtype]
12+
narrowing_typeis.py:204: error: Narrowed type "list[int]" is not a subtype of input type "list[object]" [narrowed-type-not-subtype]
1313
"""
1414
conformance_automated = "Pass"
1515
errors_diff = """

conformance/results/pyrefly/narrowing_typeis.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ conformance_automated = "Pass"
33
errors_diff = """
44
"""
55
output = """
6-
ERROR narrowing_typeis.py:105:9-13: Type guard functions must accept at least one positional argument [bad-function-definition]
76
ERROR narrowing_typeis.py:110:9-13: Type guard functions must accept at least one positional argument [bad-function-definition]
8-
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]
9-
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]
10-
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]
11-
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]
12-
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]
13-
ERROR narrowing_typeis.py:195:5-15: Return type `str` must be assignable to the first argument type `int` [bad-function-definition]
14-
ERROR narrowing_typeis.py:199:5-24: Return type `list[int]` must be assignable to the first argument type `list[object]` [bad-function-definition]
7+
ERROR narrowing_typeis.py:115:9-13: Type guard functions must accept at least one positional argument [bad-function-definition]
8+
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]
9+
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]
10+
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]
11+
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]
12+
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]
13+
ERROR narrowing_typeis.py:200:5-15: Return type `str` must be assignable to the first argument type `int` [bad-function-definition]
14+
ERROR narrowing_typeis.py:204:5-24: Return type `list[int]` must be assignable to the first argument type `list[object]` [bad-function-definition]
1515
"""

conformance/results/pyright/narrowing_typeis.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,34 @@ conformance_automated = "Pass"
33
errors_diff = """
44
"""
55
output = """
6-
narrowing_typeis.py:105:9 - error: User-defined type guard functions and methods must have at least one input parameter (reportGeneralTypeIssues)
76
narrowing_typeis.py:110:9 - error: User-defined type guard functions and methods must have at least one input parameter (reportGeneralTypeIssues)
8-
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"
7+
narrowing_typeis.py:115:9 - error: User-defined type guard functions and methods must have at least one input parameter (reportGeneralTypeIssues)
8+
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"
99
  Type "(val: object) -> TypeIs[int]" is not assignable to type "(object) -> str"
1010
    Function return type "TypeIs[int]" is incompatible with type "str"
1111
      "TypeIs[int]" is not assignable to "str"
1212
      "bool" is not assignable to "str" (reportArgumentType)
13-
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"
13+
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"
1414
  Type "(val: object) -> TypeIs[int]" is not assignable to type "(val: object) -> str"
1515
    Function return type "TypeIs[int]" is incompatible with type "str"
1616
      "TypeIs[int]" is not assignable to "str"
1717
      "bool" is not assignable to "str" (reportArgumentType)
18-
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"
18+
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"
1919
  Type "(val: object) -> TypeIs[int]" is not assignable to type "(object) -> TypeGuard[int]"
2020
    Function return type "TypeIs[int]" is incompatible with type "TypeGuard[int]"
2121
      "TypeIs[int]" is not assignable to "TypeGuard[int]"
2222
      "bool" is not assignable to "TypeGuard[int]" (reportArgumentType)
23-
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"
23+
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"
2424
  Type "(val: object) -> TypeGuard[int]" is not assignable to type "(object) -> TypeIs[int]"
2525
    Function return type "TypeGuard[int]" is incompatible with type "TypeIs[int]"
2626
      "TypeGuard[int]" is not assignable to "TypeIs[int]"
2727
      "bool" is not assignable to "TypeIs[int]" (reportArgumentType)
28-
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"
28+
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"
2929
  Type "(val: object) -> TypeIs[bool]" is not assignable to type "(object) -> TypeIs[int]"
3030
    Function return type "TypeIs[bool]" is incompatible with type "TypeIs[int]"
3131
      "TypeIs[bool]" is not assignable to "TypeIs[int]"
3232
        Type parameter "T@TypeIs" is invariant, but "bool" is not the same as "int"
3333
      "bool" is not assignable to "TypeIs[int]" (reportArgumentType)
34-
narrowing_typeis.py:195:27 - error: Return type of TypeIs ("str") is not consistent with value parameter type ("int") (reportGeneralTypeIssues)
35-
narrowing_typeis.py:199:45 - error: Return type of TypeIs ("list[int]") is not consistent with value parameter type ("list[object]") (reportGeneralTypeIssues)
34+
narrowing_typeis.py:200:27 - error: Return type of TypeIs ("str") is not consistent with value parameter type ("int") (reportGeneralTypeIssues)
35+
narrowing_typeis.py:204:45 - error: Return type of TypeIs ("list[int]") is not consistent with value parameter type ("list[object]") (reportGeneralTypeIssues)
3636
"""

conformance/results/ty/narrowing_typeis.toml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ Line 35: Unexpected errors ['narrowing_typeis.py:35:18: error[invalid-assignment
88
"""
99
output = """
1010
narrowing_typeis.py:35:18: error[invalid-assignment] Object of type `object` is not assignable to `int`
11-
narrowing_typeis.py:105:23: error[invalid-type-guard-definition] `TypeIs` function must have a parameter to narrow
12-
narrowing_typeis.py:110:22: error[invalid-type-guard-definition] `TypeIs` function must have a parameter to narrow
13-
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]`
14-
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]`
15-
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]`
16-
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]`
17-
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]`
18-
narrowing_typeis.py:195:27: error[invalid-type-guard-definition] Narrowed type `str` is not assignable to the declared parameter type `int`
19-
narrowing_typeis.py:199:45: error[invalid-type-guard-definition] Narrowed type `list[int]` is not assignable to the declared parameter type `list[object]`
11+
narrowing_typeis.py:110:23: error[invalid-type-guard-definition] `TypeIs` function must have a parameter to narrow
12+
narrowing_typeis.py:115:22: error[invalid-type-guard-definition] `TypeIs` function must have a parameter to narrow
13+
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]`
14+
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]`
15+
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]`
16+
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]`
17+
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]`
18+
narrowing_typeis.py:200:27: error[invalid-type-guard-definition] Narrowed type `str` is not assignable to the declared parameter type `int`
19+
narrowing_typeis.py:204:45: error[invalid-type-guard-definition] Narrowed type `list[int]` is not assignable to the declared parameter type `list[object]`
2020
"""

conformance/results/zuban/narrowing_typeis.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ conformance_automated = "Pass"
22
errors_diff = """
33
"""
44
output = """
5-
narrowing_typeis.py:105: error: "TypeIs" functions must have a positional argument [misc]
65
narrowing_typeis.py:110: error: "TypeIs" functions must have a positional argument [misc]
7-
narrowing_typeis.py:132: error: Argument 1 to "takes_callable_str" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], str]" [arg-type]
8-
narrowing_typeis.py:152: error: Argument 1 to "takes_callable_str_proto" has incompatible type "Callable[[object], TypeIs[int]]"; expected "CallableStrProto" [arg-type]
9-
narrowing_typeis.py:169: error: Argument 1 to "takes_typeguard" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], TypeGuard[int]]" [arg-type]
10-
narrowing_typeis.py:170: error: Argument 1 to "takes_typeis" has incompatible type "Callable[[object], TypeGuard[int]]"; expected "Callable[[object], TypeIs[int]]" [arg-type]
11-
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]
12-
narrowing_typeis.py:195: error: Narrowed type "str" is not a subtype of input type "int" [narrowed-type-not-subtype]
13-
narrowing_typeis.py:199: error: Narrowed type "list[int]" is not a subtype of input type "list[object]" [narrowed-type-not-subtype]
6+
narrowing_typeis.py:115: error: "TypeIs" functions must have a positional argument [misc]
7+
narrowing_typeis.py:137: error: Argument 1 to "takes_callable_str" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], str]" [arg-type]
8+
narrowing_typeis.py:157: error: Argument 1 to "takes_callable_str_proto" has incompatible type "Callable[[object], TypeIs[int]]"; expected "CallableStrProto" [arg-type]
9+
narrowing_typeis.py:174: error: Argument 1 to "takes_typeguard" has incompatible type "Callable[[object], TypeIs[int]]"; expected "Callable[[object], TypeGuard[int]]" [arg-type]
10+
narrowing_typeis.py:175: error: Argument 1 to "takes_typeis" has incompatible type "Callable[[object], TypeGuard[int]]"; expected "Callable[[object], TypeIs[int]]" [arg-type]
11+
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]
12+
narrowing_typeis.py:200: error: Narrowed type "str" is not a subtype of input type "int" [narrowed-type-not-subtype]
13+
narrowing_typeis.py:204: error: Narrowed type "list[int]" is not a subtype of input type "list[object]" [narrowed-type-not-subtype]
1414
"""

conformance/tests/narrowing_typeis.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@ async def func2(val: int | Awaitable[int]):
3535
x: int = await val
3636
return x
3737
else:
38-
assert_type(val, int)
38+
# We can't say much here. The strictly correct answer is
39+
# (int | Awaitable[int]) & ~Awaitable[Any], but conformant implementations
40+
# may simplify this.
41+
# But it should definitely remain assignable to `int | Awaitable[int]`.
42+
y: int | Awaitable[int] = val
43+
return y
3944

4045

4146
T_A = TypeVar("T_A", bound="A")

0 commit comments

Comments
 (0)