Skip to content

[ty] Create fresh copies of generic callable typevars#24949

Draft
dcreager wants to merge 26 commits into
mainfrom
dcreager/alpha-renaming
Draft

[ty] Create fresh copies of generic callable typevars#24949
dcreager wants to merge 26 commits into
mainfrom
dcreager/alpha-renaming

Conversation

@dcreager
Copy link
Copy Markdown
Member

A generic callable binds new typevars. If that callable is used more than once in a particular expression, we should create separate (aka "fresh") copies of those typevars, so that the inferred types for each do not conflict with each other.

This comes up in two situations:

  • We might invoke a generic function recursively from inside of its body. In that case, the call site introduces fresh inferable copies of the function's typevars, which should not conflict with the existing non-inferable copies from the function signature.

  • We might pass the same generic callable more than once to some other call. In this case, each occurrence should have distinct copies of its typevars, that do not need to unify with each other. This can occur whenever we compare a generic callable signature for assignability with some other signature.

This PR updates these two places (call binding and signature assignability checking) to introduce fresh copies of the callable's typevars when needed. There are still some mdtests that are marked as TODOs, because they depend on combining constraint sets across multiple arguments (#24540).

@astral-sh-bot astral-sh-bot Bot added the ty Multi-file analysis & type inference label Apr 30, 2026
@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 30, 2026

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 89.34%. The percentage of expected errors that received a diagnostic held steady at 85.30%. The number of fully passing files held steady at 87/134.

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 30, 2026

Memory usage report

Summary

Project Old New Diff Outcome
prefect 678.21MB 692.72MB +2.14% (14.50MB)
sphinx 260.05MB 263.28MB +1.24% (3.23MB)
trio 117.05MB 118.02MB +0.83% (997.47kB)
flake8 47.77MB 47.95MB +0.38% (185.21kB)

Significant changes

Click to expand detailed breakdown

prefect

Name Old New Diff Outcome
FunctionType<'db>::last_definition_signature_ 812.34kB 9.22MB +1061.79% (8.42MB)
infer_expression_types_impl 56.08MB 58.80MB +4.86% (2.72MB)
infer_definition_types 85.94MB 88.08MB +2.49% (2.14MB)
infer_scope_types_impl 55.52MB 55.99MB +0.84% (479.93kB)
BoundTypeVarInstance 1.42MB 1.58MB +11.80% (171.23kB)
function_known_decorators 4.51MB 4.64MB +2.99% (138.21kB)
is_redundant_with_impl 1.89MB 1.96MB +4.15% (80.09kB)
InferableTypeVarsInner 205.41kB 255.61kB +24.44% (50.20kB)
infer_expression_type_impl 7.46MB 7.51MB +0.61% (46.73kB)
infer_deferred_types 11.00MB 11.05MB +0.39% (43.85kB)
GenericContext 298.16kB 325.30kB +9.10% (27.14kB)
when_constraint_set_assignable_to_owned_impl 1.54MB 1.56MB +1.56% (24.61kB)
Type<'db>::apply_specialization_::interned_arguments 2.99MB 3.02MB +0.79% (24.22kB)
Type<'db>::apply_specialization_ 3.62MB 3.64MB +0.58% (21.52kB)
Specialization 2.13MB 2.15MB +0.85% (18.66kB)
... 43 more

sphinx

Name Old New Diff Outcome
FunctionType<'db>::last_definition_signature_ 231.65kB 2.05MB +808.25% (1.83MB)
infer_expression_types_impl 20.47MB 21.24MB +3.73% (782.09kB)
infer_definition_types 23.90MB 24.26MB +1.51% (370.73kB)
infer_scope_types_impl 15.44MB 15.54MB +0.70% (110.33kB)
BoundTypeVarInstance 624.45kB 695.94kB +11.45% (71.49kB)
infer_expression_type_impl 2.90MB 2.92MB +0.75% (22.32kB)
when_constraint_set_assignable_to_owned_impl 941.84kB 955.70kB +1.47% (13.85kB)
InferableTypeVarsInner 84.23kB 97.44kB +15.67% (13.20kB)
GenericContext 134.34kB 143.17kB +6.57% (8.83kB)
loop_header_reachability 364.27kB 371.60kB +2.01% (7.32kB)
all_narrowing_constraints_for_expression 2.39MB 2.40MB +0.20% (4.98kB)
Type<'db>::apply_specialization_::interned_arguments 1.43MB 1.44MB +0.27% (3.91kB)
Type<'db>::apply_specialization_ 1.63MB 1.63MB +0.20% (3.25kB)
is_redundant_with_impl 925.89kB 928.94kB +0.33% (3.05kB)
Specialization 1002.39kB 1005.11kB +0.27% (2.72kB)
... 20 more

trio

Name Old New Diff Outcome
FunctionType<'db>::last_definition_signature_ 250.32kB 833.43kB +232.95% (583.12kB)
infer_expression_types_impl 6.96MB 7.22MB +3.63% (258.56kB)
infer_definition_types 7.80MB 7.86MB +0.76% (61.02kB)
infer_scope_types_impl 4.73MB 4.76MB +0.65% (31.59kB)
BoundTypeVarInstance 162.49kB 181.09kB +11.45% (18.60kB)
InferableTypeVarsInner 75.48kB 83.88kB +11.14% (8.41kB)
infer_expression_type_impl 1.30MB 1.31MB +0.59% (7.86kB)
GenericContext 124.44kB 129.80kB +4.30% (5.36kB)
FunctionType 1.52MB 1.53MB +0.21% (3.33kB)
when_constraint_set_assignable_to_owned_impl 200.46kB 203.63kB +1.58% (3.17kB)
CallableType 607.44kB 609.52kB +0.34% (2.08kB)
loop_header_reachability 128.87kB 130.93kB +1.60% (2.06kB)
FunctionType<'db>::signature_ 1.11MB 1.11MB +0.18% (2.01kB)
all_narrowing_constraints_for_expression 595.31kB 597.15kB +0.31% (1.84kB)
StaticClassLiteral<'db>::try_mro_ 793.45kB 794.52kB +0.13% (1.06kB)
... 22 more

flake8

Name Old New Diff Outcome
FunctionType<'db>::last_definition_signature_ 61.17kB 180.46kB +195.03% (119.29kB)
infer_expression_types_impl 1.02MB 1.06MB +3.29% (34.49kB)
infer_definition_types 1.87MB 1.89MB +0.79% (15.16kB)
infer_scope_types_impl 976.70kB 982.56kB +0.60% (5.86kB)
BoundTypeVarInstance 44.65kB 49.61kB +11.11% (4.96kB)
InferableTypeVarsInner 26.07kB 27.98kB +7.33% (1.91kB)
GenericContext 43.61kB 45.11kB +3.43% (1.50kB)
when_constraint_set_assignable_to_owned_impl 79.04kB 80.32kB +1.62% (1.28kB)
infer_expression_type_impl 118.44kB 118.69kB +0.21% (252.00B)
infer_statement_types_impl 4.96kB 5.07kB +2.36% (120.00B)
Type<'db>::member_lookup_with_policy_ 551.42kB 551.52kB +0.02% (96.00B)
StaticClassLiteral<'db>::implicit_attribute_inner_ 309.80kB 309.89kB +0.03% (96.00B)
loop_header_reachability 12.73kB 12.80kB +0.55% (72.00B)
all_narrowing_constraints_for_expression 86.89kB 86.96kB +0.08% (72.00B)
all_negative_narrowing_constraints_for_expression 40.65kB 40.70kB +0.12% (48.00B)
... 1 more

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 30, 2026

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-argument-type 4 0 0
invalid-assignment 0 1 0
Total 4 1 0

Raw diff:

Expression (https://github.com/cognitedata/Expression)
+ expression/collections/maptree.py:176:36 error[invalid-argument-type] Argument to function `try_find` is incorrect: Expected `Option[MapTreeLeaf[Key@try_find, Never]]`, found `Option[MapTreeLeaf[Never, Never]]`

setuptools (https://github.com/pypa/setuptools)
- setuptools/glob.py:76:34 error[invalid-assignment] Object of type `Iterator[str]` is not assignable to `Iterable[AnyStr@_iglob]`
+ setuptools/glob.py:76:41 error[invalid-argument-type] Argument to function `_iglob` is incorrect: Argument type `AnyStr@_iglob & ~AlwaysFalsy` does not satisfy constraints (`str`, `bytes`) of type variable `AnyStr`

xarray (https://github.com/pydata/xarray)
+ xarray/backends/api.py:1363:42 error[invalid-argument-type] Argument to function `_remove_path` is incorrect: Expected `NestedSequence[_FLike@_remove_path]`, found `(_FLike@_remove_path & Top[list[Unknown]]) | (NestedSequence[_FLike@_remove_path] & Top[list[Unknown]])`
+ xarray/core/utils.py:356:35 error[invalid-argument-type] Argument to function `flat_items` is incorrect: Expected `Mapping[str, dict[str, Divergent] | Unknown]`, found `dict[str, Divergent] | (T@flat_items & Top[dict[Unknown, Unknown]])`

Full report with detailed diff (timing results)

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 30, 2026

Merging this PR will degrade performance by 5.31%

❌ 1 regressed benchmark
✅ 56 untouched benchmarks
⏩ 60 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
WallTime pydantic 8 s 8.4 s -5.31%

Comparing dcreager/alpha-renaming (8a690e5) with main (e990dfd)

Open in CodSpeed

Footnotes

  1. 60 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant