Visit the ParamSpec tail of Type::Concatenate - #4415
Open
markselby9 wants to merge 2 commits into
Open
Conversation
Two open issues report that `Concatenate` and `ParamSpec` behave correctly inside `Callable` but not inside user-defined generic classes. Capture the current (wrong) behaviour with `bug`-marked tests so the baseline is explicit before attempting a fix. - facebook#3706: `A[Concatenate[int, P]]` returned from a method of `A[**P]` is never specialized; the revealed type still mentions `P`. - facebook#3828: `A[Concatenate[int, P]]` as a parameter rejects every argument and infers an unsolved `@_` for `P`.
`Type::Concatenate(Box<[PrefixParam]>, Box<Type>)` stores its trailing ParamSpec as an ordinary `Type`, but the hand-written `Visit`/`VisitMut` impls for `Type` discarded that second field. Every traversal built on them — `subst`, `collect_quantifieds`, `contains_type_variable`, `transform_mut` and the solver's `resolve_vars` — was therefore a silent no-op on the tail. The `Callable` spelling was unaffected because it is normalized at construction into `Params::ParamSpec`, whose derived visitor sees both fields; only a bare `Concatenate` in a class type argument, e.g. `A[Concatenate[int, P]]`, hit the broken path. Visiting the tail is enough to fix the observable symptoms: the tail's `Var` now gets resolved, which lets the solver's existing `Concatenate[..., ParamSpecValue]` and `Concatenate[..., Concatenate]` collapses fire, and `P` is now discovered as a type variable when it occurs only inside a tail. This also subsumes the hand-rolled recursion in `tvars_to_tparams_for_type_alias`, which can now use `recurse_mut` like its neighbouring arms, leaving `PrefixParam::ty_mut` unused. Fixes facebook#3706, facebook#3828. The one changed expectation in `test_functools_partial_pattern` is the fix working: `_P2` inside a `Concatenate` now renders as `Ellipsis`, matching the sibling occurrence of the same ParamSpec in that message.
Contributor
|
This pull request has been imported. If you are a Meta employee, you can view this in D114585275. (Because this pull request was imported automatically, there will not be any future comments.) |
|
Diff from mypy_primer, showing the effect of this PR on open source code: asynq (https://github.com/quora/asynq)
- ERROR asynq/generator.py:127:16-25: Argument `AsyncDecorator[Any, [self: Self@_AsyncGenerator, value: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/generator.py:127:16-25: Argument `AsyncDecorator[Any, [self: Self@_AsyncGenerator, value: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, value: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/generator.py:148:16-32: Argument `AsyncDecorator[Any, [self: Self@_AsyncGenerator, first_task: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/generator.py:148:16-32: Argument `AsyncDecorator[Any, [self: Self@_AsyncGenerator, first_task: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, first_task: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_asynq_to_async.py:150:15-18: Argument `AsyncDecorator[Any, [self: test_method.A, x: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_asynq_to_async.py:150:15-18: Argument `AsyncDecorator[Any, [self: test_method.A, x: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, x: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_asynq_to_async.py:154:23-26: Argument `AsyncDecorator[Any, [self: test_method.A, x: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_asynq_to_async.py:154:23-26: Argument `AsyncDecorator[Any, [self: test_method.A, x: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, x: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_asynq_to_async.py:157:27-30: Argument `AsyncDecorator[Any, [self: test_method.A, x: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_asynq_to_async.py:157:27-30: Argument `AsyncDecorator[Any, [self: test_method.A, x: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, x: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_asynq_to_async.py:226:27-33: Argument `AsyncDecorator[Any, [self: Self@test_proxy_and_bind.B, x: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_asynq_to_async.py:226:27-33: Argument `AsyncDecorator[Any, [self: Self@test_proxy_and_bind.B, x: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, x: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_asynq_to_async.py:229:12-15: Argument `AsyncDecorator[Any, [self: test_proxy_and_bind.B, x: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_asynq_to_async.py:229:12-15: Argument `AsyncDecorator[Any, [self: test_proxy_and_bind.B, x: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, x: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_asynq_to_async.py:230:24-27: Argument `AsyncDecorator[Any, [self: test_proxy_and_bind.B, x: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_asynq_to_async.py:230:24-27: Argument `AsyncDecorator[Any, [self: test_proxy_and_bind.B, x: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, x: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:49:20-41: Argument `AsyncDecorator[Any, [cls: type[Self@MyClass], number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:49:20-41: Argument `AsyncDecorator[Any, [cls: type[Self@MyClass], number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, number: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:52:26-47: Argument `AsyncDecorator[Any, [cls: type[Self@MyClass], number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:52:26-47: Argument `AsyncDecorator[Any, [cls: type[Self@MyClass], number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, number: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:55:21-32: Argument `PureAsyncDecorator[Any, [number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.PureAsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:55:21-32: Argument `PureAsyncDecorator[Any, [number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.PureAsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:55:33-39: The type of this argument is unknown [unknown-argument-type]
+ ERROR asynq/tests/test_decorators.py:55:33-39: Expected 0 positional arguments, got 1 in function `asynq.decorators.PureAsyncDecoratorBinder.__call__` [bad-argument-count]
- ERROR asynq/tests/test_decorators.py:57:21-35: Argument `AsyncDecorator[Any, [number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:57:21-35: Argument `AsyncDecorator[Any, [number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:57:42-48: The type of this argument is unknown [unknown-argument-type]
+ ERROR asynq/tests/test_decorators.py:57:42-48: Expected 0 positional arguments, got 1 in function `asynq.decorators.AsyncDecoratorBinder.asynq` [bad-argument-count]
- ERROR asynq/tests/test_decorators.py:59:30-58: Argument `AsyncDecorator[Any, [cls: type[Self@MyClass], number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:59:30-58: Argument `AsyncDecorator[Any, [cls: type[Self@MyClass], number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, number: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:67:16-36: Argument `AsyncDecorator[Any, [cls: type[Self@MyClass], number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:67:16-36: Argument `AsyncDecorator[Any, [cls: type[Self@MyClass], number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, number: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:73:16-30: Argument `AsyncDecorator[Any, [cls: type[Self@MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:73:16-30: Argument `AsyncDecorator[Any, [cls: type[Self@MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:74:23-37: Argument `AsyncDecorator[Any, [cls: type[Self@MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:74:23-37: Argument `AsyncDecorator[Any, [cls: type[Self@MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:75:16-27: Argument `PureAsyncDecorator[Any, [cls: type[Self@MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.PureAsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:75:16-27: Argument `PureAsyncDecorator[Any, [cls: type[Self@MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.PureAsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:76:23-34: Argument `PureAsyncDecorator[Any, [cls: type[Self@MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.PureAsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:76:23-34: Argument `PureAsyncDecorator[Any, [cls: type[Self@MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.PureAsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:188:29-44: Argument `PureAsyncDecorator[Any, [cls: type[MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.PureAsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:188:29-44: Argument `PureAsyncDecorator[Any, [cls: type[MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.PureAsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:189:33-51: Argument `AsyncDecorator[Any, [cls: type[MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:189:33-51: Argument `AsyncDecorator[Any, [cls: type[MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:227:19-29: Argument `AsyncDecorator[Any, [self: MyClass, number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:227:19-29: Argument `AsyncDecorator[Any, [self: MyClass, number: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, number: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:231:36-62: Argument `AsyncDecorator[Any, []]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:231:36-62: Argument `AsyncDecorator[Any, []]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, @_]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:232:37-63: Argument `AsyncDecorator[Any, []]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:232:37-63: Argument `AsyncDecorator[Any, []]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, @_]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:236:36-61: Argument `AsyncDecorator[Any, [cls: type[MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:236:36-61: Argument `AsyncDecorator[Any, [cls: type[MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:237:35-60: Argument `AsyncDecorator[Any, [cls: type[MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:237:35-60: Argument `AsyncDecorator[Any, [cls: type[MyClass]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:242:30-51: Argument `AsyncDecorator[Any, [self: MyClass]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:242:30-51: Argument `AsyncDecorator[Any, [self: MyClass]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_decorators.py:243:31-52: Argument `AsyncDecorator[Any, [self: MyClass]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_decorators.py:243:31-52: Argument `AsyncDecorator[Any, [self: MyClass]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_mock.py:62:17-38: Argument `AsyncDecorator[Any, [cls: type[Cls]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_mock.py:62:17-38: Argument `AsyncDecorator[Any, [cls: type[Cls]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_mock.py:63:18-39: Argument `AsyncDecorator[Any, [cls: type[Cls]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_mock.py:63:18-39: Argument `AsyncDecorator[Any, [cls: type[Cls]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_mock.py:67:12-33: Argument `AsyncDecorator[Any, [cls: type[Cls]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_mock.py:67:12-33: Argument `AsyncDecorator[Any, [cls: type[Cls]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_mock.py:71:18-39: Argument `AsyncDecorator[Any, [cls: type[Cls]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_mock.py:71:18-39: Argument `AsyncDecorator[Any, [cls: type[Cls]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_mock.py:77:17-33: Argument `AsyncDecorator[Any, [self: Cls]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_mock.py:77:17-33: Argument `AsyncDecorator[Any, [self: Cls]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_mock.py:78:18-34: Argument `AsyncDecorator[Any, [self: Cls]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_mock.py:78:18-34: Argument `AsyncDecorator[Any, [self: Cls]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_mock.py:82:12-30: Argument `AsyncDecorator[Any, [self: Cls]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_mock.py:82:12-30: Argument `AsyncDecorator[Any, [self: Cls]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_mock.py:86:18-36: Argument `AsyncDecorator[Any, [self: Cls]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_mock.py:86:18-36: Argument `AsyncDecorator[Any, [self: Cls]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_mock.py:200:34-55: Argument `AsyncDecorator[Any, [cls: type[Cls]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_mock.py:200:34-55: Argument `AsyncDecorator[Any, [cls: type[Cls]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_mock.py:200:57-75: Argument `AsyncDecorator[Any, [self: Cls]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_mock.py:200:57-75: Argument `AsyncDecorator[Any, [self: Cls]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_mock.py:208:38-59: Argument `AsyncDecorator[Any, [cls: type[Cls]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_mock.py:208:38-59: Argument `AsyncDecorator[Any, [cls: type[Cls]]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_mock.py:208:61-79: Argument `AsyncDecorator[Any, [self: Cls]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_mock.py:208:61-79: Argument `AsyncDecorator[Any, [self: Cls]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_multiple_inheritance.py:43:15-40: Argument `AsyncDecorator[Any, [self: Self@Child]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_multiple_inheritance.py:43:15-40: Argument `AsyncDecorator[Any, [self: Self@Child]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_multiple_inheritance.py:44:15-29: Argument `AsyncDecorator[Any, [self: Parent2]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_multiple_inheritance.py:44:15-29: Argument `AsyncDecorator[Any, [self: Parent2]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_multiple_inheritance.py:44:36-40: Expected 0 positional arguments, got 1 in function `asynq.decorators.AsyncDecoratorBinder.asynq` [bad-argument-count]
- ERROR asynq/tests/test_multiple_inheritance.py:52:15-30: Argument `AsyncDecorator[Any, [self: Child]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_multiple_inheritance.py:52:15-30: Argument `AsyncDecorator[Any, [self: Child]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_tools.py:189:17-36: Argument `AsyncDecorator[Any, [self: AsyncObject, index: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_tools.py:189:17-36: Argument `AsyncDecorator[Any, [self: AsyncObject, index: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, index: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_tools.py:189:17-36: Argument `AsyncDecorator[Any, [self: UnhashableAcached, index: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
+ ERROR asynq/tests/test_tools.py:189:17-36: Argument `AsyncDecorator[Any, [self: UnhashableAcached, index: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, [Any, index: Unknown]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
- ERROR asynq/tests/test_tools.py:192:22-35: Argument `AsyncDecorator[Any, [self: AsyncObject, index: Unknown]]` is not assignable to parameter `self` with type `PureAsyncDecorator[Any, Concatenate[Any, _P2]]` in function `asynq.decorators.AsyncDecorator.__get__` [bad-argument-type]
... (truncated 68 lines) ...
|
yangdanny97
approved these changes
Aug 5, 2026
yangdanny97
left a comment
Contributor
There was a problem hiding this comment.
Review automatically exported from Phabricator review in Meta.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Type::Concatenate(Box<[PrefixParam]>, Box<Type>)stores its trailing ParamSpec as an ordinaryType, but the hand-writtenVisit/VisitMutimpls forTypediscarded that second field:Every traversal built on those two functions —
subst,collect_quantifieds,contains_type_variable,transform_mut, and the solver'sresolve_vars— was therefore a silent no-op on the tail. TheCallablespelling was unaffected because it is normalized at construction intoParams::ParamSpec, whose derived visitor sees both fields; only a bareConcatenatein a class type argument, e.g.A[Concatenate[int, P]], reached the broken path. That asymmetry is exactly what both issues report.Visiting the tail is sufficient. Once the tail's
Varis reachable it gets resolved, which lets the solver's existingConcatenate[..., ParamSpecValue]andConcatenate[..., Concatenate]collapses fire for the first time, andPis now discovered as a type variable when it occurs only inside a tail. It also subsumes the hand-rolled recursion intvars_to_tparams_for_type_alias, which can now userecurse_mutlike its neighbouring arms, leavingPrefixParam::ty_mutunused.I kept the impl hand-written rather than switching to
#[derive(Visit, VisitMut)]:impl Visit for Typeis deliberately monomorphic (Visit<Type> for Type), while the derive emitsimpl<To> Visit<To>with a where-clause per field — and several ofType's payload types (TArgs,Union,Arc<TParams>, …) only implement the monomorphic form, so it would not compile. The hand-written arms also elide no-op recursion on the checker's hottest traversal. I added a comment on both arms stating the invariant so the omission can't quietly come back.Fixes #3706, #3828.
Test Plan
cargo test -p pyrefly --lib— 7468 passed, 0 failed. Full workspacecargo testgreen. Conformance output (conformance.exp,conformance.result,results.json) is byte-identical to the committed versions, with all fourgenerics_paramspec_*cases still passing.First commit adds the repros as
bug-marked tests capturing the current wrong behaviour; the second removes the markers and updates them to the correct results. Also added coverage for paths that were previously unreachable: the nestedConcatenate[..., Concatenate[...]]collapse, a bareConcatenatein both legacy and PEP 695 type aliases, and aParamSpecreachable only through a tail being recognised as a type variable.Exactly one pre-existing expectation changed, in
test_functools_partial_pattern:partial[Concatenate[*tuple[Unknown, ...], _P2], Ellipsis, Any, object, ...]partial[Concatenate[*tuple[Unknown, ...], Ellipsis], Ellipsis, Any, object, ...]That is the fix working. The overload-consistency check instantiates the declared return type with gradual forms, and the
_P2in the second type-argument position was already rendering asEllipsis— only the one inside theConcatenatetail was leaking through unsubstituted. The two now agree. That test keeps its unrelatedbugmarker.One known gap, left as a
bug-marked test (test_concatenate_paramspec_tail_gradual): a gradualA[...]still doesn't bind the tail, sodrop_int(g)givesA[@_]andadd_int(g)givesA[Concatenate[int, Ellipsis]], where theCallableequivalents are correct. Both issues report concrete parameter lists, which this fixes; the...case needs separate work.