Visit the ParamSpec tail of Type::Concatenate - #4415
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.
|
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
left a comment
There was a problem hiding this comment.
Review automatically exported from Phabricator review in Meta.
|
The
|
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.