Skip to content

Conversation

@dcreager
Copy link
Member

@dcreager dcreager commented Nov 7, 2025

This manifested as an error when inferring the type of a PEP-695 generic class via its constructor parameters:

class D[T, U]:
    @overload
    def __init__(self: "D[str, U]", u: U) -> None: ...
    @overload
    def __init__(self, t: T, u: U) -> None: ...
    def __init__(self, *args) -> None: ...

# revealed: D[Unknown, str]
# SHOULD BE: D[str, str]
reveal_type(D("string"))

This manifested because D is inferred to be bivariant in both T and U. We weren't seeing this in the equivalent example for legacy typevars, since those default to invariant. (This issue also showed up for covariant typevars, so this issue was not limited to bivariance.)

The underlying cause was because of a heuristic that we have in our current constraint solver, which attempts to handle situations like this:

def f[T](t: T | None): ...
f(None)

Here, the None argument matches the non-typevar union element, so this argument should not add any constraints on what T can specialize to. Our previous heuristic would check for this by seeing if the argument type is a subtype of the parameter annotation as a whole — even if it isn't a union! That would cause us to erroneously ignore the self parameter in our constructor call, since bivariant classes are equivalent to each other, regardless of their specializations.

The quick fix is to move this heuristic "down a level", so that we only apply it when the parameter annotation is a union. This heuristic should go away completely 🤞 with the new constraint solver.

@dcreager dcreager added the ty Multi-file analysis & type inference label Nov 7, 2025
@dcreager dcreager requested a review from sharkdp as a code owner November 7, 2025 19:17
@github-actions
Copy link
Contributor

github-actions bot commented Nov 7, 2025

Diagnostic diff on typing conformance tests

Changes were detected when running ty on typing conformance tests
--- old-output.txt	2025-11-11 00:35:18.990083765 +0000
+++ new-output.txt	2025-11-11 00:35:22.335106572 +0000
@@ -937,7 +937,6 @@
 tuples_type_compat.py:127:13: error[type-assertion-failure] Argument does not have asserted type `@Todo(Support for `typing.TypeAlias`)`
 tuples_type_compat.py:129:13: error[type-assertion-failure] Argument does not have asserted type `tuple[int | str, int]`
 tuples_type_compat.py:130:13: error[type-assertion-failure] Argument does not have asserted type `@Todo(Support for `typing.TypeAlias`)`
-tuples_type_compat.py:153:5: error[type-assertion-failure] Argument does not have asserted type `Sequence[Never]`
 tuples_type_compat.py:157:1: error[invalid-assignment] Object of type `tuple[Literal[1], Literal[""], Literal[""]]` is not assignable to `tuple[int, str]`
 tuples_type_compat.py:162:1: error[invalid-assignment] Object of type `tuple[Literal[1], Literal[1], Literal[""]]` is not assignable to `tuple[int, *tuple[str, ...]]`
 tuples_type_compat.py:163:1: error[invalid-assignment] Object of type `tuple[Literal[1], Literal[""], Literal[1]]` is not assignable to `tuple[int, *tuple[str, ...]]`
@@ -1007,5 +1006,5 @@
 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] Invalid key 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. Did you mean to use a concrete TypedDict or `collections.abc.Mapping[str, object]` instead?
-Found 1009 diagnostics
+Found 1008 diagnostics
 WARN A fatal error occurred while checking some files. Not all project files were analyzed. See the diagnostics list above for details.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 7, 2025

mypy_primer results

No ecosystem changes detected ✅

No memory usage changes detected ✅

@github-actions
Copy link
Contributor

github-actions bot commented Nov 7, 2025

ecosystem-analyzer results

No diagnostic changes detected ✅
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.

LGTM

* origin/main: (38 commits)
  [ty] Make implicit submodule imports only occur in global scope (#21370)
  [ty] introduce local variables for `from` imports of submodules in `__init__.py(i)` (#21173)
  [`ruff`] Ignore `str()` when not used for simple conversion (`RUF065`) (#21330)
  [ty] implement `typing.NewType` by adding `Type::NewTypeInstance`
  [ty] supress inlay hints for `+1` and `-1` (#21368)
  [ty] Use type context for inference of generic constructors (#20933)
  [ty] Improve generic call expression inference (#21210)
  [ty] supress some trivial expr inlay hints (#21367)
  [`configuration`] Fix unclear error messages for line-length values exceeding `u16::MAX` (#21329)
  [ty] Fix incorrect inference of `enum.auto()` for enums with non-`int` mixins, and imprecise inference of `enum.auto()` for single-member enums (#20541)
  [`refurb`] Detect empty f-strings (`FURB105`) (#21348)
  [ty] provide `import` completion when in `from <name> <name>` statement (#21291)
  [ty] elide redundant inlay hints for function args (#21365)
  Fix syntax error false positive on alternative `match` patterns (#21362)
  Add a new "Opening a PR" section to the contribution guide (#21298)
  [`flake8-simplify`] Fix SIM222 false positive for `tuple(generator) or None` (`SIM222`) (#21187)
  Rebuild ruff binary instead of sharing it across jobs (#21361)
  [ty] Fix `--exclude` and `src.exclude` merging (#21341)
  [ty] Add support for properties that return `Self` (#21335)
  Add upstream linter URL to `ruff linter --output-format=json` (#21316)
  ...
@dcreager dcreager merged commit 33b942c into main Nov 11, 2025
41 checks passed
@dcreager dcreager deleted the dcreager/pep-self branch November 11, 2025 00:46
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.

3 participants