Skip to content

Use TypeVar defaults when inferring from a type object - #22044

Open
Dextheking1 wants to merge 1 commit into
python:masterfrom
Dextheking1:fix-typevar-default-from-type-object-21608
Open

Dextheking1 wants to merge 1 commit into
python:masterfrom
Dextheking1:fix-typevar-default-from-type-object-21608

Conversation

@Dextheking1

Copy link
Copy Markdown

Fixes #21608.

When a generic class with TypeVar defaults is passed where type[S] is expected, mypy inferred Any for the defaulted parameters instead of using the defaults. For example, with def f(x: type[S]) -> S, f(Box) gave Box[Any] instead of Box[int | None].

The class object type was erased with erase_typevars, which replaces every type variable with Any. I added erase_typevars_with_defaults in erasetype.py, which substitutes each type variable's default when it has one (defaults referencing earlier type variables are expanded gradually, like typeanal does) and falls back to Any otherwise. It is now used in the two places where a type object gets erased for a type[...] context: analyze_ref_expr in checkexpr.py and visit_type_type in constraints.py.

This matches how a bare generic already behaves in annotations: x: type[Box] = Box reveals type[Box[int | None]].

Added a regression test in check-typevar-defaults.test. It fails on master and passes with the fix. Full testcheck suite passes (8227 passed, 27 skipped, 7 xfailed). Self check on the touched files is clean.

@github-actions

Copy link
Copy Markdown
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

psycopg (https://github.com/psycopg/psycopg)
+ psycopg/psycopg/connection_async.py:82: error: Incompatible types in assignment (expression has type "type[AsyncCursor[tuple[Any, ...]]]", variable has type "type[AsyncCursor[Row]]")  [assignment]
+ psycopg/psycopg/connection_async.py:83: error: Incompatible types in assignment (expression has type "type[AsyncServerCursor[tuple[Any, ...]]]", variable has type "type[AsyncServerCursor[Row]]")  [assignment]
+ psycopg/psycopg/connection.py:78: error: Incompatible types in assignment (expression has type "type[Cursor[tuple[Any, ...]]]", variable has type "type[Cursor[Row]]")  [assignment]
+ psycopg/psycopg/connection.py:79: error: Incompatible types in assignment (expression has type "type[ServerCursor[tuple[Any, ...]]]", variable has type "type[ServerCursor[Row]]")  [assignment]

steam.py (https://github.com/Gobot1234/steam.py)
+ steam/profile.py:157: error: Argument 1 to "dataclass" has incompatible type "type[OwnedProfileItems[UserT]]"; expected "type[OwnedProfileItems[User]]"  [arg-type]
+ steam/profile.py:173: error: Argument 1 to "dataclass" has incompatible type "type[EquippedProfileItems[UserT]]"; expected "type[EquippedProfileItems[User]]"  [arg-type]
+ steam/profile.py:189: error: Argument 1 has incompatible type "type[ProfileShowcaseSlot[UserT]]"; expected "type[ProfileShowcaseSlot[User]]"  [arg-type]
+ steam/profile.py:268: error: Argument 1 has incompatible type "type[ProfileShowcase[UserT]]"; expected "type[ProfileShowcase[User]]"  [arg-type]
+ steam/leaderboard.py:72: error: Argument 1 has incompatible type "type[Leaderboard[AppT, DisplayNameT]]"; expected "type[Leaderboard[Any, None]]"  [arg-type]
+ steam/gateway.py:95: error: Argument 1 has incompatible type "type[EventListener[MsgsT]]"; expected "type[EventListener[ProtobufMessage | Message | GCProtobufMessage | GCMessage]]"  [arg-type]
+ steam/gateway.py:105: error: Argument 1 has incompatible type "type[GCEventListener[GCMsgsT]]"; expected "type[GCEventListener[GCProtobufMessage | GCMessage]]"  [arg-type]
- steam/ext/commands/commands.py:709: error: Incompatible default for parameter "cls" (default has type "type[Command[Any, Any, Any]]", parameter has type "type[C]")  [assignment]
+ steam/ext/commands/commands.py:709: error: Incompatible default for parameter "cls" (default has type "type[Command[Cog[Bot] | Bot | None, [VarArg(Any), KwArg(Any)], Any]]", parameter has type "type[C]")  [assignment]
- steam/ext/commands/commands.py:807: error: Incompatible default for parameter "cls" (default has type "type[Command[Any, Any, Any]]", parameter has type "type[C]")  [assignment]
+ steam/ext/commands/commands.py:807: error: Incompatible default for parameter "cls" (default has type "type[Command[Cog[Bot] | Bot | None, [VarArg(Any), KwArg(Any)], Any]]", parameter has type "type[C]")  [assignment]
- steam/ext/commands/commands.py:831: error: Incompatible return value type (got "C | Command[Any, Any, Any]", expected "C")  [return-value]
+ steam/ext/commands/commands.py:831: error: Incompatible return value type (got "Command[Cog[Bot] | Bot | None, [VarArg(Any), KwArg(Any)], Any]", expected "C")  [return-value]
- steam/ext/commands/bot.py:519: error: Incompatible default for parameter "cls" (default has type "type[Context[Any]]", parameter has type "type[C]")  [assignment]
+ steam/ext/commands/bot.py:519: error: Incompatible default for parameter "cls" (default has type "type[Context[Bot]]", parameter has type "type[C]")  [assignment]

pandas-stubs (https://github.com/pandas-dev/pandas-stubs)
+ tests/series/test_truediv.py:155: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_truediv.py:195: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_truediv.py:205: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_sub.py:263: error: Expression is of type "Any", not "Series[Timedelta]"  [assert-type]
+ tests/series/test_floordiv.py:135: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_floordiv.py:171: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_floordiv.py:180: error: Expression is of type "Series[Any]", not "Series[Timedelta]"  [assert-type]
+ tests/indexes/test_indexes.py:1796: error: Unused "type: ignore" comment  [unused-ignore]
+ tests/arrays/test_datetime_array.py:354: error: Expression is of type "Any", not "DatetimeArray"  [assert-type]

pytest (https://github.com/pytest-dev/pytest)
+ testing/test_runner.py:140: error: Item "Exception" of "Exception | ExceptionGroup[Exception]" has no attribute "exceptions"  [union-attr]
+ testing/test_runner.py:141: error: Item "Exception" of "Exception | ExceptionGroup[Exception]" has no attribute "exceptions"  [union-attr]

jax (https://github.com/google/jax)
- jax/experimental/pallas/ops/tpu/splash_attention/splash_attention_mask_info.py:729: error: Incompatible types in assignment (expression has type "ndarray[tuple[Any, ...], dtype[bool[Any]]]", variable has type "list[ndarray[tuple[Any, ...], dtype[Any]]] | None")  [assignment]
+ jax/experimental/pallas/ops/tpu/splash_attention/splash_attention_mask_info.py:729: error: Incompatible types in assignment (expression has type "ndarray[tuple[Any, ...], dtype[numpy.bool[builtins.bool]]]", variable has type "list[ndarray[tuple[Any, ...], dtype[Any]]] | None")  [assignment]

static-frame (https://github.com/static-frame/static-frame)
+ static_frame/core/store_zip.py:49: error: Argument 1 has incompatible type "type[PayloadBytesToFrame[TVStoreConfig]]"; expected "type[PayloadBytesToFrame[StoreConfigBase]]"  [arg-type]
+ static_frame/core/store_zip.py:60: error: Argument 1 has incompatible type "type[PayloadFrameToBytes[TVStoreConfig]]"; expected "type[PayloadFrameToBytes[StoreConfigBase]]"  [arg-type]

scipy-stubs (https://github.com/scipy/scipy-stubs)
+ scipy-stubs/stats/_resampling.pyi:38: error: Argument 1 to "dataclass" has incompatible type "type[BootstrapResult[_FloatNDT, _DistT]]"; expected "type[BootstrapResult[Any, ndarray[tuple[Any, ...], dtype[float64]]]]"  [arg-type]
+ scipy-stubs/stats/_resampling.pyi:44: error: Argument 1 to "dataclass" has incompatible type "type[PermutationTestResult[_FloatNDT, _DistT]]"; expected "type[PermutationTestResult[Any, ndarray[tuple[Any, ...], dtype[float64]]]]"  [arg-type]
+ scipy-stubs/stats/_resampling.pyi:51: error: Argument 1 to "dataclass" has incompatible type "type[MonteCarloTestResult[_FloatNDT, _DistT]]"; expected "type[MonteCarloTestResult[Any, ndarray[tuple[Any, ...], dtype[float64]]]]"  [arg-type]
+ scipy-stubs/stats/_multicomp.pyi:28: error: Argument 1 to "dataclass" has incompatible type "type[DunnettResult[_StatT_co]]"; expected "type[DunnettResult[float64]]"  [arg-type]
+ scipy-stubs/stats/_stats_py.pyi:249: error: Argument 1 to "dataclass" has incompatible type "type[AlexanderGovernResult[_FloatOrArrayT_co]]"; expected "type[AlexanderGovernResult[float | ndarray[tuple[Any, ...], dtype[float64]]]]"  [arg-type]
+ scipy-stubs/stats/_stats_py.pyi:262: error: Argument 1 to "dataclass" has incompatible type "type[QuantileTestResult[_FloatT]]"; expected "type[QuantileTestResult[float64 | Any]]"  [arg-type]
+ scipy-stubs/stats/_survival.pyi:35: error: Argument 1 to "dataclass" has incompatible type "type[EmpiricalDistributionFunction[_QuantileT_co]]"; expected "type[EmpiricalDistributionFunction[float64]]"  [arg-type]
+ scipy-stubs/stats/_survival.pyi:55: error: Argument 1 to "dataclass" has incompatible type "type[ECDFResult[_QuantileT_co]]"; expected "type[ECDFResult[float64]]"  [arg-type]

@Dextheking1
Dextheking1 marked this pull request as ready for review October 2, 2026 00:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generic default type in type revealed as Any

1 participant