Skip to content

Conversation

@ilevkivskyi
Copy link
Member

@ilevkivskyi ilevkivskyi commented Sep 8, 2025

This makes self-check almost 2% faster on my desktop (Python 3.12, compiled -O2). Inspired by a slight regression in #19798 I decided to re-think how we detect/label the recursive types.

The new algorithm is not 100% equivalent to old one, but should be much faster. The main semantic difference is this:

A = list[B1]
B1 = list[B2]
B2 = list[B1]

previously all three aliases where labeled as recursive, now only last two are. Which is kind of correct if you think about it for some time, there is nothing genuinely recursive in A by itself. As a result:

  • We have somewhat more verbose reveal_type() for recursive types after fine-grained increments. Excessive use of get_proper_type() in the daemon code is a known issue. I will take a look at it when I will have a chance.
  • I cleaned up some of relevant visitors to be more consistent with recursive aliases.
  • I also do couple cleanups/speedups in the type queries while I am at it.

If there are no comments/objections, I will merge it later today. Then I will merge #19798, and then maybe an equivalent optimization for recursive instances like class str(Sequence[str]): ...

@ilevkivskyi ilevkivskyi requested a review from JukkaL September 8, 2025 13:05
@ilevkivskyi
Copy link
Member Author

Hm, looking at primer this makes a bunch of projects visibly slower actually, at least with interpreted mypy. And one of them (https://github.com/vega/altair) is still running after 30 minutes. Not sure what is going on there, will look into it.

@github-actions

This comment has been minimized.

@ilevkivskyi
Copy link
Member Author

Interesting, it looks like altair has a bunch of aliases like ColorScheme_T: TypeAlias = Literal[<dozens/hundreds items>]. So previously, seen_aliases worked as a cache for those huge unions. I guess the point all huge literal unions are originally type aliases, not proper types. So we should try to find some balance between people for whom most aliases are tiny, and those sets are only slowing things down, and people who have large type aliases.

New errors in mypy_primer are correct, we used to skip error in previously seen aliases, even if those aliases are on different lines, I will try to clean up that part a bit more.

@ilevkivskyi
Copy link
Member Author

OK, here is take two, I still see ~same 2% boost for self-check, let's see how this will work for other projects.

@github-actions

This comment has been minimized.

@ilevkivskyi
Copy link
Member Author

Hm, altair is still slow (almost 30% slower), I think this exposes my concern from #19111, but I think I have an idea how to fix this.

@ilevkivskyi
Copy link
Member Author

Btw the reveal_type() verbosity with new logic is specific to mutually recursive tuples in fine-grained mode. I am quite sure this exposes an existing issue (daemon code known for being excessive with get_proper_type()), I updated PR description to mention this.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 8, 2025

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

altair (https://github.com/vega/altair)
+ altair/datasets/_reader.py:153: error: Type argument "IntoFrameT" of "BaseImpl" must be a subtype of "NativeDataFrame | DataFrameLike | NativeLazyFrame"  [type-var]

core (https://github.com/home-assistant/core)
- homeassistant/components/openai_conversation/__init__.py:105: error: Returning Any from function declared to return "JsonObjectType | None"  [no-any-return]
+ homeassistant/components/openai_conversation/__init__.py:105: error: Returning Any from function declared to return "dict[str, JsonValueType] | None"  [no-any-return]
- homeassistant/components/habitica/services.py:835: error: Returning Any from function declared to return "JsonObjectType | None"  [no-any-return]
+ homeassistant/components/habitica/services.py:835: error: Returning Any from function declared to return "dict[str, JsonValueType] | None"  [no-any-return]
- homeassistant/components/webostv/media_player.py:406: error: Returning Any from function declared to return "JsonObjectType | None"  [no-any-return]
+ homeassistant/components/webostv/media_player.py:406: error: Returning Any from function declared to return "dict[str, JsonValueType] | None"  [no-any-return]
- homeassistant/components/webostv/media_player.py:511: error: Returning Any from function declared to return "JsonObjectType | None"  [no-any-return]
+ homeassistant/components/webostv/media_player.py:511: error: Returning Any from function declared to return "dict[str, JsonValueType] | None"  [no-any-return]

Tanjun (https://github.com/FasterSpeeding/Tanjun)
+ tanjun/commands/slash.py:1543: error: Type argument "_SlashCallbackSigT" of "MenuCommand" must be a subtype of "Callable[[MenuContext, Any, VarArg(Any), KwArg(Any)], Coroutine[Any, Any, None]]"  [type-var]
+ tanjun/commands/slash.py:1543: error: Type argument "_SlashCallbackSigT" of "MessageCommand" must be a subtype of "Callable[[MessageContext, VarArg(Any), KwArg(Any)], Coroutine[Any, Any, None]]"  [type-var]
+ tanjun/commands/message.py:162: error: Type argument "_MessageCallbackSigT" of "MenuCommand" must be a subtype of "Callable[[MenuContext, Any, VarArg(Any), KwArg(Any)], Coroutine[Any, Any, None]]"  [type-var]
+ tanjun/commands/message.py:162: error: Type argument "_MessageCallbackSigT" of "SlashCommand" must be a subtype of "Callable[[SlashContext, VarArg(Any), KwArg(Any)], Coroutine[Any, Any, None]]"  [type-var]
+ tanjun/commands/message.py:209: error: Type argument "_MessageCallbackSigT" of "MenuCommand" must be a subtype of "Callable[[MenuContext, Any, VarArg(Any), KwArg(Any)], Coroutine[Any, Any, None]]"  [type-var]
+ tanjun/commands/message.py:209: error: Type argument "_MessageCallbackSigT" of "SlashCommand" must be a subtype of "Callable[[SlashContext, VarArg(Any), KwArg(Any)], Coroutine[Any, Any, None]]"  [type-var]
+ tanjun/commands/message.py:406: error: Type argument "_MessageCallbackSigT" of "MenuCommand" must be a subtype of "Callable[[MenuContext, Any, VarArg(Any), KwArg(Any)], Coroutine[Any, Any, None]]"  [type-var]
+ tanjun/commands/message.py:406: error: Type argument "_MessageCallbackSigT" of "SlashCommand" must be a subtype of "Callable[[SlashContext, VarArg(Any), KwArg(Any)], Coroutine[Any, Any, None]]"  [type-var]
+ tanjun/commands/message.py:516: error: Type argument "_OtherCallbackSigT" of "MenuCommand" must be a subtype of "Callable[[MenuContext, Any, VarArg(Any), KwArg(Any)], Coroutine[Any, Any, None]]"  [type-var]
+ tanjun/commands/message.py:516: error: Type argument "_OtherCallbackSigT" of "SlashCommand" must be a subtype of "Callable[[SlashContext, VarArg(Any), KwArg(Any)], Coroutine[Any, Any, None]]"  [type-var]
+ tanjun/commands/message.py:543: error: Type argument "_OtherCallbackSigT" of "MenuCommand" must be a subtype of "Callable[[MenuContext, Any, VarArg(Any), KwArg(Any)], Coroutine[Any, Any, None]]"  [type-var]
+ tanjun/commands/message.py:543: error: Type argument "_OtherCallbackSigT" of "SlashCommand" must be a subtype of "Callable[[SlashContext, VarArg(Any), KwArg(Any)], Coroutine[Any, Any, None]]"  [type-var]

static-frame (https://github.com/static-frame/static-frame)
+ static_frame/core/node_re.py:59: error: Invalid type argument value for "ToContainerType"  [type-var]
+ static_frame/core/node_dt.py:124: error: Invalid type argument value for "ToContainerType"  [type-var]
+ static_frame/core/node_str.py:98: error: Invalid type argument value for "ToContainerType"  [type-var]

@ilevkivskyi
Copy link
Member Author

OK, I double-checked again with the latest version of this PR:

  • The mypy_primer changes are correct
  • No project has visible slow-down
  • There is still 2% speed-up on self-check (and on some other projects)

It looks like this is a clear overall win: most projects will likely get few percent speed-up, and only few projects may get few percent slower.

@ilevkivskyi
Copy link
Member Author

Also opened #19812 for the fine-grained issue.

@ilevkivskyi ilevkivskyi merged commit f09aa57 into python:master Sep 8, 2025
20 checks passed
@ilevkivskyi ilevkivskyi deleted the speed-up-aliases branch September 8, 2025 22:46
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.

1 participant