Skip to content

Comments

[ty] Emit diagnostic when a type variable with a default is followed by one without a default#21787

Merged
AlexWaygood merged 14 commits intoastral-sh:mainfrom
11happy:ty_typevar_invalid_order
Dec 14, 2025
Merged

[ty] Emit diagnostic when a type variable with a default is followed by one without a default#21787
AlexWaygood merged 14 commits intoastral-sh:mainfrom
11happy:ty_typevar_invalid_order

Conversation

@11happy
Copy link
Contributor

@11happy 11happy commented Dec 4, 2025

Summary

This PR fixes astral-sh/ty#1651

Test Plan

I have added mdtest

@astral-sh-bot
Copy link

astral-sh-bot bot commented Dec 4, 2025

Diagnostic diff on typing conformance tests

Changes were detected when running ty on typing conformance tests
--- old-output.txt	2025-12-14 19:31:44.194785139 +0000
+++ new-output.txt	2025-12-14 19:31:47.826806321 +0000
@@ -439,6 +439,7 @@
 generics_basic.py:171:1: error[invalid-generic-class] `Generic` base class must include all type variables used in other base classes
 generics_basic.py:172:1: error[invalid-generic-class] `Generic` base class must include all type variables used in other base classes
 generics_basic.py:199:5: error[type-assertion-failure] Type `Iterator[Any]` does not match asserted type `Unknown`
+generics_defaults.py:24:40: error[invalid-generic-class] Type parameter `T` without a default cannot follow earlier parameter `DefaultStrT` with a default
 generics_defaults.py:30:1: error[type-assertion-failure] Type `type[NoNonDefaults[str, int]]` does not match asserted type `<class 'NoNonDefaults'>`
 generics_defaults.py:31:1: error[type-assertion-failure] Type `type[NoNonDefaults[str, int]]` does not match asserted type `<class 'NoNonDefaults[str, int]'>`
 generics_defaults.py:32:1: error[type-assertion-failure] Type `type[NoNonDefaults[str, int]]` does not match asserted type `<class 'NoNonDefaults[str, int]'>`
@@ -1025,4 +1026,4 @@
 typeddicts_usage.py:28:17: error[missing-typed-dict-key] Missing required key 'name' in TypedDict `Movie` constructor
 typeddicts_usage.py:28:18: error[invalid-key] Unknown key "title" for TypedDict `Movie`: Unknown key "title"
 typeddicts_usage.py:40:24: error[invalid-type-form] The special form `typing.TypedDict` is not allowed in type expressions
-Found 1027 diagnostics
+Found 1028 diagnostics

@astral-sh-bot
Copy link

astral-sh-bot bot commented Dec 4, 2025

mypy_primer results

Changes were detected when running on open source projects
scikit-build-core (https://github.com/scikit-build/scikit-build-core)
+ src/scikit_build_core/build/wheel.py:98:20: error[no-matching-overload] No overload of bound method `__init__` matches arguments
- Found 41 diagnostics
+ Found 42 diagnostics

pydantic (https://github.com/pydantic/pydantic)
- pydantic/fields.py:943: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:943: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:983: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:983: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:1026: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:1026: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:1066: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:1066: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:1109: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:1109: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:1148: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:1148: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:1188: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:1188: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:1567:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`, found `Top[dict[Unknown, Unknown]] | (((dict[str, Divergent], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`
+ pydantic/fields.py:1567: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 `Top[dict[Unknown, Unknown]] | (((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`

No memory usage changes detected ✅

@11happy 11happy requested a review from MichaReiser as a code owner December 4, 2025 10:33
@AlexWaygood AlexWaygood changed the title [ty]: raise diagnostic when a type variable with a default is followed by one without a default [ty] Emit diagnostic when a type variable with a default is followed by one without a default Dec 4, 2025
@AlexWaygood AlexWaygood added the ty Multi-file analysis & type inference label Dec 4, 2025
@carljm
Copy link
Contributor

carljm commented Dec 5, 2025

Thanks for the PR!

This is emitting two new diagnostics on the conformance suite. The one in generics_defaults.py is correct: we should emit this diagnostic there.

The one at https://github.com/python/typing/blob/main/conformance/tests/generics_defaults_specialization.py#L42 looks wrong -- there should not be any diagnostic there, and the one we emit is clearly not right, since it references T1, a type variable from the superclass which we are specializing away with int. And it claims T1 is following some other type variable.

I haven't looked at the code here yet, but it looks like in that subclassing scenario we are checking the wrong set of type variables somehow.

There are a lot of new diagnostics in the ecosystem here. I would recommend first fixing the above issue, and then seeing if the ecosystem impact is reduced.

@sharkdp sharkdp removed their request for review December 5, 2025 08:36
@11happy
Copy link
Contributor Author

11happy commented Dec 10, 2025

Thanks for the PR!

This is emitting two new diagnostics on the conformance suite. The one in generics_defaults.py is correct: we should emit this diagnostic there.

The one at https://github.com/python/typing/blob/main/conformance/tests/generics_defaults_specialization.py#L42 looks wrong -- there should not be any diagnostic there, and the one we emit is clearly not right, since it references T1, a type variable from the superclass which we are specializing away with int. And it claims T1 is following some other type variable.

I haven't looked at the code here yet, but it looks like in that subclassing scenario we are checking the wrong set of type variables somehow.

There are a lot of new diagnostics in the ecosystem here. I would recommend first fixing the above issue, and then seeing if the ecosystem impact is reduced.

Thank you for the pointers! , I have updated the approach & added the new test as well.
Thank you : )

@11happy 11happy force-pushed the ty_typevar_invalid_order branch from 855552a to 9a83524 Compare December 10, 2025 07:08
Signed-off-by: 11happy <bhuminjaysoni@gmail.com>
Signed-off-by: 11happy <bhuminjaysoni@gmail.com>
Signed-off-by: 11happy <bhuminjaysoni@gmail.com>
Signed-off-by: 11happy <bhuminjaysoni@gmail.com>
Signed-off-by: 11happy <bhuminjaysoni@gmail.com>
Signed-off-by: 11happy <bhuminjaysoni@gmail.com>
Signed-off-by: 11happy <bhuminjaysoni@gmail.com>
Signed-off-by: 11happy <bhuminjaysoni@gmail.com>
Signed-off-by: 11happy <bhuminjaysoni@gmail.com>
Signed-off-by: 11happy <bhuminjaysoni@gmail.com>
@11happy 11happy force-pushed the ty_typevar_invalid_order branch from 9c9709c to 723b514 Compare December 14, 2025 08:31
@11happy
Copy link
Contributor Author

11happy commented Dec 14, 2025

ping! have resolved the merged conflict
would appreciate a review
Thank you : )

Signed-off-by: 11happy <soni5happy@gmail.com>
11happy and others added 3 commits December 14, 2025 14:25
Signed-off-by: 11happy <soni5happy@gmail.com>
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.

thank you

@AlexWaygood AlexWaygood enabled auto-merge (squash) December 14, 2025 19:34
@AlexWaygood AlexWaygood merged commit 04f9949 into astral-sh:main Dec 14, 2025
41 checks passed
@codspeed-hq
Copy link

codspeed-hq bot commented Dec 14, 2025

CodSpeed Performance Report

Merging #21787 will degrade performances by 5.02%

Comparing 11happy:ty_typevar_invalid_order (ceea5c5) with main (8bc753b)

Summary

❌ 1 regression
✅ 21 untouched
⏩ 30 skipped1

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

Benchmarks breakdown

Mode Benchmark BASE HEAD Change
WallTime large[pydantic] 201.8 s 212.5 s -5.02%

Footnotes

  1. 30 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.

dcreager added a commit that referenced this pull request Dec 15, 2025
* origin/main:
  Update MSRV to 1.90 (#21987)
  [ty] Improve check enforcing that an overloaded function must have an implementation (#21978)
  Update actions/checkout digest to 8e8c483 (#21982)
  [ty] Use `ParamSpec` without the attr for inferable check (#21934)
  [ty] Emit diagnostic when a type variable with a default is followed by one without a default (#21787)
  [ty] Fix callout syntax in configuration mkdocs (#1875) (#21961)
  Update debug_assert which pointed at missing method (#21969)
  [ty] Add support for `__qualname__` and other implicit class attributes (#21966)
dcreager added a commit that referenced this pull request Dec 15, 2025
* origin/main:
  Fluent formatting of method chains (#21369)
  [ty] Avoid stack overflow when calculating inferable typevars (#21971)
  [ty] Add "qualify ..." code fix for undefined references (#21968)
  [ty] Use jemalloc on linux (#21975)
  Update MSRV to 1.90 (#21987)
  [ty] Improve check enforcing that an overloaded function must have an implementation (#21978)
  Update actions/checkout digest to 8e8c483 (#21982)
  [ty] Use `ParamSpec` without the attr for inferable check (#21934)
  [ty] Emit diagnostic when a type variable with a default is followed by one without a default (#21787)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ecosystem-analyzer ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Emit diagnostic when a type variable with a default is followed by one without a default

4 participants