Add strict validation for ParamSpec forwarding patterns (#2802)#2802
Add strict validation for ParamSpec forwarding patterns (#2802)#2802grievejia wants to merge 2 commits intofacebook:mainfrom
Conversation
|
@grievejia has exported this pull request. If you are a Meta employee, you can view the originating Diff in D96510931. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…imal fix Summary: When one generic helper forwards `*args: P.args, **kwargs: P.kwargs` to another generic helper that also takes `Callable[P, R]`, the solver binds the callee's ParamSpec Var to the caller's still-quantified `P`. The `var_to_rparams` closure didn't handle `Type::Quantified` and fell through to the error branch, producing a bogus "Expected `P` to be a ParamSpec value" error. Fix: recognize `Type::Quantified(q) if q.is_param_spec()` in `var_to_rparams` so the forwarded ParamSpec is handled instead of erroring. The next diff in this stack adds strict validation of the forwarding pattern. Differential Revision: D96510930
b1a98d1 to
47015df
Compare
Summary: Follow-up to the minimal fix: instead of permissively accepting all arguments when a ParamSpec Var resolves to a quantified ParamSpec, validate that the remaining args/kwargs actually follow the `*P.args` / `**P.kwargs` forwarding pattern. This mirrors the existing validation in the `Params::ParamSpec` / `Type::Quantified` dispatch (callable_infer), but for the deferred case where the Var is resolved mid-matching inside `callable_infer_params`. The validation is extracted into a `check_paramspec_forwarding` method to avoid code duplication and keep `var_to_rparams` simple. Fixes facebook#823 Differential Revision: D96510931
Summary: Pull Request resolved: facebook#2802 Follow-up to the minimal fix: instead of permissively accepting all arguments when a ParamSpec Var resolves to a quantified ParamSpec, validate that the remaining args/kwargs actually follow the `*P.args` / `**P.kwargs` forwarding pattern. This mirrors the existing validation in the `Params::ParamSpec` / `Type::Quantified` dispatch (callable_infer), but for the deferred case where the Var is resolved mid-matching inside `callable_infer_params`. The validation is extracted into a `check_paramspec_forwarding` method to avoid code duplication and keep `var_to_rparams` simple. Fixes facebook#823 Differential Revision: D96510931
47015df to
26d0b53
Compare
|
Diff from mypy_primer, showing the effect of this PR on open source code: async-utils (https://github.com/mikeshardmind/async-utils)
- ERROR src/async_utils/bg_tasks.py:192:48-80: Expected `P` to be a ParamSpec value in function `_sem_fut` [bad-argument-type]
- ERROR src/async_utils/gen_transform.py:206:36-56: Expected `P` to be a ParamSpec value in function `_sync_to_async_gen` [bad-argument-type]
- ERROR src/async_utils/gen_transform.py:243:35-55: Expected `P` to be a ParamSpec value in function `_sync_to_async_gen` [bad-argument-type]
pwndbg (https://github.com/pwndbg/pwndbg)
- ERROR pwndbg/commands/__init__.py:948:41-61: Expected `P` to be a ParamSpec value in function `_try2run_heap_command` [bad-argument-type]
- ERROR pwndbg/commands/__init__.py:963:45-65: Expected `P` to be a ParamSpec value in function `_try2run_heap_command` [bad-argument-type]
starlette (https://github.com/encode/starlette)
- ERROR starlette/applications.py:101:50-85: Expected `P` to be a ParamSpec value in function `starlette.middleware.Middleware.__init__` [bad-argument-type]
- ERROR starlette/background.py:31:30-53: Expected `P` to be a ParamSpec value in function `BackgroundTask.__init__` [bad-argument-type]
zulip (https://github.com/zulip/zulip)
- ERROR zerver/lib/profile.py:34:30-53: Expected `ParamT` to be a ParamSpec value in function `cProfile.Profile.runcall` [bad-argument-type]
pandas (https://github.com/pandas-dev/pandas)
- ERROR pandas/core/generic.py:6134:27-73: No matching overload found for function `pandas.core.common.pipe` called with arguments: (Self@NDFrame, ((Self@NDFrame, ParamSpec(P)) -> T) | tuple[(...) -> T, str], *tuple[Any, ...], **dict[str, Any]) [no-matching-overload]
- ERROR pandas/core/groupby/groupby.py:540:24-53: No matching overload found for function `pandas.core.common.pipe` called with arguments: (Self@BaseGroupBy, ((Self@BaseGroupBy, ParamSpec(P)) -> T) | tuple[(...) -> T, str], *tuple[Any, ...], **dict[str, Any]) [no-matching-overload]
- ERROR pandas/core/resample.py:342:28-51: No matching overload found for function `pandas.core.groupby.groupby.BaseGroupBy.pipe` called with arguments: (((Self@Resampler, ParamSpec(P)) -> T) | tuple[(...) -> T, str], *tuple[Any, ...], **dict[str, Any]) [no-matching-overload]
- ERROR pandas/core/window/expanding.py:435:28-51: No matching overload found for function `pandas.core.window.rolling.RollingAndExpandingMixin.pipe` called with arguments: (((Self@Expanding, ParamSpec(P)) -> T) | tuple[(...) -> T, str], *tuple[Any, ...], **dict[str, Any]) [no-matching-overload]
- ERROR pandas/core/window/rolling.py:1634:24-53: No matching overload found for function `pandas.core.common.pipe` called with arguments: (Self@RollingAndExpandingMixin, ((Self@RollingAndExpandingMixin, ParamSpec(P)) -> T) | tuple[(...) -> T, str], *tuple[Any, ...], **dict[str, Any]) [no-matching-overload]
- ERROR pandas/core/window/rolling.py:2376:28-51: No matching overload found for function `RollingAndExpandingMixin.pipe` called with arguments: (((Self@Rolling, ParamSpec(P)) -> T) | tuple[(...) -> T, str], *tuple[Any, ...], **dict[str, Any]) [no-matching-overload]
- ERROR pandas/io/formats/style.py:4200:24-53: No matching overload found for function `pandas.core.common.pipe` called with arguments: (Self@Styler, ((Self@Styler, ParamSpec(P)) -> T) | tuple[(...) -> T, str], *tuple[Any, ...], **dict[str, Any]) [no-matching-overload]
pytest-robotframework (https://github.com/detachhead/pytest-robotframework)
- ERROR pytest_robotframework/__init__.py:303:30-68: Expected `P` to be a ParamSpec value in function `_KeywordDecorator.inner` [bad-argument-type]
trio (https://github.com/python-trio/trio)
- ERROR src/trio/_socket.py:440:46-76: Expected `P` to be a ParamSpec value in function `_SocketType._nonblocking_helper` [bad-argument-type]
paasta (https://github.com/yelp/paasta)
- ERROR paasta_tools/async_utils.py:184:24-51: Expected `P` to be a ParamSpec value in function `run_sync` [bad-argument-type]
scrapy (https://github.com/scrapy/scrapy)
- ERROR scrapy/utils/asyncio.py:222:34-57: Expected `_P` to be a ParamSpec value in function `AsyncioLoopingCall.__init__` [bad-argument-type]
- ERROR scrapy/utils/defer.py:288:60-290:6: Expected `_P` to be a ParamSpec value in function `_AsyncCooperatorAdapter.__init__` [bad-argument-type]
- ERROR scrapy/utils/defer.py:430:31-54: Expected `_P` to be a ParamSpec value in function `_maybeDeferred_coro` [bad-argument-type]
prefect (https://github.com/PrefectHQ/prefect)
- ERROR src/prefect/_internal/concurrency/api.py:32:23-46: Expected `P` to be a ParamSpec value in function `prefect._internal.concurrency.calls.Call.new` [bad-argument-type]
- ERROR src/prefect/utilities/asyncutils.py:400:44-73: Expected `P` to be a ParamSpec value in function `run_async_from_worker_thread` [bad-argument-type]
- ERROR src/prefect/utilities/asyncutils.py:404:37-66: Expected `P` to be a ParamSpec value in function `run_async_in_new_loop` [bad-argument-type]
|
Primer Diff Classification✅ 10 improvement(s) | 10 project(s) total | -24 errors 10 improvement(s) across async-utils, pwndbg, starlette, zulip, pandas, pytest-robotframework, trio, paasta, scrapy, prefect.
Detailed analysis✅ Improvement (10)async-utils (-3)
pwndbg (-2)
starlette (-2)
zulip (-1)
pandas (-7)
pytest-robotframework (-1)
trio (-1)
paasta (-1)
scrapy (-3)
prefect (-3)
Was this helpful? React with 👍 or 👎 Classification by primer-classifier (10 LLM) |
yangdanny97
left a comment
There was a problem hiding this comment.
Review automatically exported from Phabricator review in Meta.
Summary:
Follow-up to the minimal fix: instead of permissively accepting all arguments when a ParamSpec Var resolves to a quantified ParamSpec, validate that the remaining args/kwargs actually follow the
*P.args/**P.kwargsforwarding pattern.This mirrors the existing validation in the
Params::ParamSpec/Type::Quantifieddispatch (callable_infer), but for the deferred case where the Var is resolved mid-matching insidecallable_infer_params. The validation is extracted into acheck_paramspec_forwardingmethod to avoid code duplication and keepvar_to_rparamssimple.Fixes #823
Differential Revision: D96510931