Skip to content

Pass through ParamSpec relation check for non-overloaded signatures#23927

Merged
dhruvmanila merged 2 commits intomainfrom
dhruv/paramspec-relation-check
Mar 17, 2026
Merged

Pass through ParamSpec relation check for non-overloaded signatures#23927
dhruvmanila merged 2 commits intomainfrom
dhruv/paramspec-relation-check

Conversation

@dhruvmanila
Copy link
Member

@dhruvmanila dhruvmanila commented Mar 13, 2026

Summary

This PR updates the constraint set assignability check to only special case overloaded callables against a callable containing ParamSpec and pass through any other callables to the check in Signature. This is to make sure for Concatenate (ref #23689) that we make sure that it goes through to Signature where the type checking / constraint set building would take place.

Here are the detailed list of changes:

In check_callable_signature_pair_inner,

  • Delegate the branch where both sides contain single signature with ParamSpec as the only parameter to check_signature_pair
  • For other branches where one side contain a single signature with ParamSpec as the only parameter, update the other side to check whether it's an overloaded callable. The reason is that the signatures_is_single_paramspec can return None even for non-overloaded non-ParamSpec callable which we should delegate to check_signature_pair

In check_signature_pair_inner,

  • Move the constraint set assignability branch before any special case of Top and gradual form handling. This is to support the delegation that happened from check_callable_signature_pair_inner so that the constraint set contains a node for the ParamSpec type variable because otherwise we would've short-circuit for Top / gradual form cases.

Test Plan

Make sure there are no regression and existing test cases pass.

I'm also working on top of this branch in #23689 to make sure these changes are valid, so far so good.

@astral-sh-bot astral-sh-bot bot added the ty Multi-file analysis & type inference label Mar 13, 2026
@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 13, 2026

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 85.29%. The percentage of expected errors that received a diagnostic held steady at 78.13%. The number of fully passing files held steady at 64/132.

@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 13, 2026

mypy_primer results

Changes were detected when running on open source projects
pydantic (https://github.com/pydantic/pydantic)
- pydantic/_internal/_core_metadata.py:87:54: error[invalid-assignment] Invalid assignment to key "pydantic_js_extra" with declared type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | ((dict[str, Divergent], type[Any], /) -> None)` on TypedDict `CoreMetadata`: value of type `dict[object, object]`
+ pydantic/_internal/_core_metadata.py:87:54: error[invalid-assignment] Invalid assignment to key "pydantic_js_extra" with declared type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | ((dict[str, int | float | str | ... omitted 3 union elements], type[Any], /) -> None)` on TypedDict `CoreMetadata`: value of type `dict[object, object]`
- pydantic/fields.py:949:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:949:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:989:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:989:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1032:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1032:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1072:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1072:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1115:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1115:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1154:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1154:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1194:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1194:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1573:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`, found `dict[str, Divergent] | dict[Never, Never] | (((dict[str, Divergent], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`
+ pydantic/fields.py:1573:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`, found `dict[str, int | float | str | ... omitted 3 union elements] | dict[Never, Never] | (((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`

prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/input/run_input.py:672:20: error[invalid-return-type] Return type does not match returned value: expected `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]`, found `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler] | Coroutine[Any, Any, T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]]`
+ src/prefect/input/run_input.py:672:20: error[invalid-return-type] Return type does not match returned value: expected `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]`, found `Unknown | Coroutine[Any, Any, Unknown]`

@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 13, 2026

Memory usage report

Summary

Project Old New Diff Outcome
prefect 700.38MB 700.49MB +0.02% (112.86kB)
sphinx 264.31MB 264.31MB +0.00% (3.38kB)
trio 116.53MB 116.53MB +0.00% (1.40kB)
flake8 48.22MB 48.22MB +0.00% (468.00B)

Significant changes

Click to expand detailed breakdown

prefect

Name Old New Diff Outcome
CallableType 1.67MB 1.69MB +1.53% (26.15kB)
infer_expression_types_impl 55.87MB 55.89MB +0.04% (22.01kB)
infer_definition_types 90.11MB 90.13MB +0.02% (18.90kB)
infer_expression_type_impl 14.69MB 14.71MB +0.11% (16.29kB)
StaticClassLiteral<'db>::implicit_attribute_inner_ 10.01MB 10.02MB +0.10% (10.41kB)
UnionType<'db>::from_two_elements_::interned_arguments 2.38MB 2.37MB -0.26% (6.36kB)
all_narrowing_constraints_for_expression 7.35MB 7.35MB +0.06% (4.80kB)
Type<'db>::member_lookup_with_policy_ 16.14MB 16.14MB +0.03% (4.41kB)
UnionType<'db>::from_two_elements_ 5.17MB 5.17MB -0.08% (3.98kB)
is_redundant_with_impl 5.61MB 5.61MB +0.06% (3.35kB)
all_negative_narrowing_constraints_for_expression 2.80MB 2.81MB +0.11% (3.05kB)
StaticClassLiteral<'db>::try_mro_ 6.08MB 6.08MB +0.04% (2.63kB)
GenericAlias<'db>::variance_of_ 577.73kB 579.98kB +0.39% (2.25kB)
is_redundant_with_impl::interned_arguments 5.40MB 5.40MB +0.04% (2.23kB)
Type<'db>::class_member_with_policy_ 17.58MB 17.58MB +0.01% (2.23kB)
... 21 more

sphinx

Name Old New Diff Outcome
CallableType 946.67kB 952.40kB +0.60% (5.73kB)
UnionType<'db>::from_two_elements_::interned_arguments 744.56kB 742.93kB -0.22% (1.63kB)
UnionType<'db>::from_two_elements_ 1.36MB 1.36MB -0.07% (1.04kB)
infer_definition_types 24.54MB 24.54MB +0.00% (252.00B)
infer_deferred_types 5.60MB 5.60MB +0.00% (48.00B)
infer_scope_types_impl 15.58MB 15.58MB +0.00% (36.00B)

trio

Name Old New Diff Outcome
CallableType 490.98kB 496.54kB +1.13% (5.55kB)
UnionType<'db>::from_two_elements_::interned_arguments 156.41kB 154.86kB -0.99% (1.55kB)
UnionType<'db>::from_two_elements_ 272.69kB 271.70kB -0.36% (1008.00B)
FunctionType 1.50MB 1.50MB -0.02% (368.00B)
Specialization 474.95kB 474.62kB -0.07% (336.00B)
cached_protocol_interface 135.11kB 134.88kB -0.16% (228.00B)
GenericAlias 201.30kB 201.09kB -0.10% (216.00B)
StaticClassLiteral<'db>::try_mro_ 864.56kB 864.36kB -0.02% (212.00B)
infer_definition_types 7.54MB 7.54MB +0.00% (204.00B)
FunctionType<'db>::signature_ 1.08MB 1.08MB -0.02% (200.00B)
infer_expression_types_impl 6.10MB 6.10MB +0.00% (144.00B)
ProtocolInterface 75.35kB 75.22kB -0.17% (132.00B)
Type<'db>::apply_specialization_ 738.45kB 738.33kB -0.02% (128.00B)
infer_deferred_types 2.36MB 2.36MB +0.00% (96.00B)
is_equivalent_to_object_inner 34.10kB 34.02kB -0.24% (84.00B)
... 4 more

flake8

Name Old New Diff Outcome
CallableType 143.58kB 144.42kB +0.59% (864.00B)
UnionType<'db>::from_two_elements_::interned_arguments 48.12kB 47.87kB -0.54% (264.00B)
UnionType<'db>::from_two_elements_ 80.98kB 80.82kB -0.20% (168.00B)
infer_definition_types 1.95MB 1.95MB +0.00% (36.00B)

@dhruvmanila dhruvmanila force-pushed the dhruv/paramspec-relation-check branch from cc13839 to 24accac Compare March 13, 2026 07:50
@dhruvmanila dhruvmanila added the internal An internal refactor or improvement label Mar 16, 2026
@dhruvmanila dhruvmanila marked this pull request as ready for review March 16, 2026 10:39
@dhruvmanila dhruvmanila force-pushed the dhruv/paramspec-relation-check branch from 1854010 to 86be1f8 Compare March 16, 2026 10:55
@astral-sh-bot
Copy link

astral-sh-bot bot commented Mar 16, 2026

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-return-type 0 0 1
Total 0 0 1

Full report with detailed diff (timing results)

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG! Just a few comments on comments

@dhruvmanila
Copy link
Member Author

I'm going to go ahead and merge this but would for @dcreager to take a look at this as well.

@dhruvmanila dhruvmanila enabled auto-merge (squash) March 17, 2026 02:49
@dhruvmanila dhruvmanila merged commit cca3435 into main Mar 17, 2026
50 checks passed
@dhruvmanila dhruvmanila deleted the dhruv/paramspec-relation-check branch March 17, 2026 02:54
carljm added a commit that referenced this pull request Mar 17, 2026
* main:
  Pass through ParamSpec relation check for non-overloaded signatures (#23927)
  [ty] Narrow keyword arguments when unpacking dictionary instances (#23436)
  [ty] Implement Duboc's TDD optimization for unions of constraint sets (#23881)
  Remove the repository security policy in favor of the organization one (#24008)
  Remove the repository code of conduct in favor of the organization one (#24007)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal An internal refactor or improvement ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants