Conversation
Diagnostic diff on typing conformance testsChanges were detected when running ty on typing conformance tests--- old-output.txt 2025-09-19 04:58:24.463113203 +0000
+++ new-output.txt 2025-09-19 04:58:27.522106846 +0000
@@ -109,9 +109,8 @@
callables_kwargs.py:35:5: error[type-assertion-failure] Argument does not have asserted type `str`
callables_kwargs.py:41:5: error[type-assertion-failure] Argument does not have asserted type `TD1`
callables_kwargs.py:52:11: error[too-many-positional-arguments] Too many positional arguments to function `func1`: expected 0, got 3
-callables_kwargs.py:62:5: error[missing-argument] No argument provided for required parameter `v3` of function `func2`
callables_kwargs.py:64:11: error[invalid-argument-type] Argument to function `func2` is incorrect: Expected `str`, found `Literal[1]`
-callables_kwargs.py:65:5: error[missing-argument] No argument provided for required parameter `v3` of function `func2`
+callables_kwargs.py:64:14: error[parameter-already-assigned] Multiple values provided for parameter `v3` of function `func2`
callables_kwargs.py:103:1: error[invalid-assignment] Object of type `def func1(**kwargs: @Todo(`Unpack[]` special form)) -> None` is not assignable to `TDProtocol5`
callables_kwargs.py:134:1: error[invalid-assignment] Object of type `def func7(*, v1: int, v3: str, v2: str = Literal[""]) -> None` is not assignable to `TDProtocol6`
callables_protocol.py:35:1: error[invalid-assignment] Object of type `def cb1_bad1(*vals: bytes, *, max_items: int | None) -> list[bytes]` is not assignable to `Proto1`
@@ -374,6 +373,7 @@
generics_defaults_specialization.py:30:1: error[non-subscriptable] Cannot subscript object of type `<class 'SomethingWithNoDefaults[int, typing.TypeVar]'>` with no `__class_getitem__` method
generics_defaults_specialization.py:45:1: error[type-assertion-failure] Argument does not have asserted type `@Todo(unsupported nested subscript in type[X])`
generics_paramspec_basic.py:27:38: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `int`
+generics_paramspec_components.py:49:20: error[invalid-argument-type] Argument expression after ** must be a mapping type: Found `tuple[Unknown, ...]`
generics_paramspec_components.py:83:18: error[parameter-already-assigned] Multiple values provided for parameter 1 (`x`) of function `foo`
generics_paramspec_semantics.py:13:56: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `(...) -> str`
generics_paramspec_semantics.py:17:40: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `int` |
|
ee6e221 to
e2bcd45
Compare
e2bcd45 to
afc277c
Compare
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
invalid-argument-type |
790 | 1 | 0 |
missing-argument |
0 | 600 | 10 |
unused-ignore-comment |
13 | 12 | 0 |
no-matching-overload |
6 | 9 | 0 |
unknown-argument |
14 | 0 | 0 |
unresolved-attribute |
10 | 1 | 0 |
possibly-unbound-attribute |
0 | 0 | 6 |
possibly-unbound-implicit-call |
0 | 0 | 4 |
too-many-positional-arguments |
0 | 0 | 4 |
invalid-return-type |
1 | 2 | 0 |
call-non-callable |
0 | 1 | 0 |
type-assertion-failure |
1 | 0 | 0 |
| Total | 835 | 626 | 24 |
612ef71 to
5c2c73d
Compare
Ecosystem analysisIn In def optional[T](value: T | None, default: T) -> T: ...
def _(value: dict | None = None):
# Here, `None` shouldn't be present
# revealed: dict[Unknown, Unknown] | None
reveal_type(optional(value), {})In from typing import TypedDict
class Foo1(TypedDict):
a: int
class Foo2(TypedDict):
b: str
def _(f: Foo1 | Foo2):
if "a" in f:
# This should reveal `Foo1`
reveal_type(f)
else:
# This should reveal `Foo2`
reveal_type(f)In In
|
|
The benchmark is failing because ty is now raising more number of diagnostics than the current limit for ruff/crates/ruff_benchmark/benches/ty_walltime.rs Lines 221 to 237 in fed9d6d I'll increase the limit to 600. The new diagnostics seems valid and Pyright raises them too. They're due to the following pattern where the data = dict(...)
func(**data)Here's an example in the Pyright raises these errors as well but it's being silenced using |
This sounds somewhat similar to astral-sh/ty#643. Maybe we could add a comment there that this is another use-case? |
|
|
Looking at the conformance suite, it seems the issues there are related to still lacking |
So this would be another case to consider in astral-sh/ty#136
And this is astral-sh/ty#623 |
Yeah, that's correct. |
|
(Happy to address any other feedback on this PR in a follow-up :)) |
Summary
This PR adds support for unpacking
**kwargsargument.This can be matched against any standard (positional or keyword), keyword-only, or keyword variadic parameter that haven't been matched yet.
This PR also takes care of special casing
TypedDictbecause the key names and the corresponding value type is known, so we can be more precise in our matching and type checking step. In the future, this special casing would be extended to includeParamSpecas well.Part of astral-sh/ty#247
Test Plan
Add test cases for various scenarios.