Skip to content

[ty] support super() in metaclass methods#24483

Merged
carljm merged 7 commits intomainfrom
cjm/metacallsuper
Apr 9, 2026
Merged

[ty] support super() in metaclass methods#24483
carljm merged 7 commits intomainfrom
cjm/metacallsuper

Conversation

@carljm
Copy link
Copy Markdown
Contributor

@carljm carljm commented Apr 8, 2026

Summary

Fixes astral-sh/ty#3231.

Explicit super() calls come in two varieties (zero-argument super() is just syntactic sugar for the two explicit forms, with the arguments automatically derived from context):

  • super(ThisClass, instance), where instance must be an instance of ThisClass; this is typically found in instance methods as e.g. super(ThisClass, self), or
  • super(ThisClass, SubClass), where SubClass must be a subclass of ThisClass; this is typically found in classmethods, as e.g. super(ThisClass, cls).

The two cases are handled distinctly at runtime. In the first case we look for ThisClass (the "pivot class") in the MRO of type(instance) to decide where to start our MRO walk; in the second case we look for the pivot in the MRO of SubClass itself (not its type).

We previously distinguished these cases by checking whether the second argument (owner) was a class or not. This fails in the case of super() calls in a metaclass, where the second argument can be a class, but we may still have the "instance" form of super, because the first argument is a metaclass. For example, we have super(ThisMetaClass, cls), where cls is a class, but it is an instance of ThisMetaClass, not a subclass of it.

This PR refactors our representation of bound super objects to more clearly represent these two varieties, and more closely match the runtime representation, while eliminating some distinctions we previously tracked as variants of SuperOwnerKind that aren't actually necessary to correctly implementing the semantics.

Test Plan

Passes all existing tests, plus newly added mdtests for metaclass super() which fail on main.

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

astral-sh-bot Bot commented Apr 8, 2026

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 87.72%. The percentage of expected errors that received a diagnostic held steady at 82.85%. The number of fully passing files held steady at 74/132.

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 8, 2026

Memory usage report

Memory usage unchanged ✅

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 8, 2026

ecosystem-analyzer results

No diagnostic changes detected ✅

Full report with detailed diff (timing results)

@carljm carljm marked this pull request as ready for review April 8, 2026 05:47
@astral-sh-bot astral-sh-bot Bot requested a review from oconnor663 April 8, 2026 05:47
Comment thread crates/ty_python_semantic/src/types/bound_super.rs Outdated
Comment thread crates/ty_python_semantic/src/types/bound_super.rs Outdated
Comment thread crates/ty_python_semantic/src/types/bound_super.rs Outdated
Comment thread crates/ty_python_semantic/src/types/bound_super.rs Outdated
Comment thread crates/ty_python_semantic/src/types/bound_super.rs Outdated
Comment thread crates/ty_python_semantic/src/types/bound_super.rs Outdated
@carljm carljm requested a review from AlexWaygood April 9, 2026 00:45
@carljm carljm assigned AlexWaygood and unassigned oconnor663 Apr 9, 2026
Copy link
Copy Markdown
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.

thanks!

Comment on lines +1382 to +1387
pub(crate) fn as_type(self, db: &'db dyn Db) -> Type<'db> {
match self {
TypeVarBoundOrConstraints::UpperBound(bound) => bound,
TypeVarBoundOrConstraints::Constraints(constraints) => constraints.as_type(db),
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I worry that this method will be a bit of a performance footgun, because it's a very convenient API, but TypeVarConstraints::as_type (which invokes the UnionBuilder) seems unnecessarily expensive for lots of operations where you can get the same result by explicitly mapping over the typevar constraints

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that, but I'm not sure it justifies not providing the method, when we have valid use cases for it. What would you suggest? I can add a doc comment to it.

Comment thread crates/ty_python_semantic/src/types/bound_super.rs Outdated
@carljm carljm force-pushed the cjm/metacallsuper branch from 636988c to 317c37d Compare April 9, 2026 19:23
@carljm carljm enabled auto-merge (squash) April 9, 2026 19:24
@carljm carljm merged commit ac79009 into main Apr 9, 2026
55 checks passed
@carljm carljm deleted the cjm/metacallsuper branch April 9, 2026 19:28
carljm added a commit that referenced this pull request Apr 10, 2026
* main:
  [ty] Fix bad diagnostic range for incorrect implicit `__init_subclass__` calls (#24541)
  [ty] Add a `SupportedPythonVersion` enum (#24412)
  [ty] Ignore unsupported editor-selected Python versions (#24498)
  [ty] Add snapshots for `__init_subclass__` diagnostics (#24539)
  [ty] Minor fix in tests (#24538)
  [ty] Allow `Final` variable assignments in `__post_init__` (#24529)
  [ty] Expand test suite for assignment errors (#24537)
  [ty] Use `map`, not `__map`, as the name of the mapping parameter in `TypedDict` `__init__` methods (#24535)
  [ty] Rework logic for synthesizing `TypedDict` methods (#24534)
  [flake8-bandit] Fix S103 false positives and negatives in mask analysis (#24424)
  [ty] mdtest.py: update dependencies (#24533)
  Rename patterns and arguments source order iterator method (#24532)
  [ty] Omit invalid keyword arguments from `TypedDict` signature (#24522)
  [ty] support super() in metaclass methods (#24483)
  [ty] Synthesize `__init__` for `TypedDict` (#24476)
carljm added a commit that referenced this pull request Apr 10, 2026
* main:
  Bump typing conformance suite commit to latest upstream (#24553)
  [ty] Reject deleting`Final` attributes (#24508)
  [ty] Respect property deleters in attribute deletion checks (#24500)
  [ty] stop unioning Unknown into types of un-annotated attributes (#24531)
  [ty] Fix bad diagnostic range for incorrect implicit `__init_subclass__` calls (#24541)
  [ty] Add a `SupportedPythonVersion` enum (#24412)
  [ty] Ignore unsupported editor-selected Python versions (#24498)
  [ty] Add snapshots for `__init_subclass__` diagnostics (#24539)
  [ty] Minor fix in tests (#24538)
  [ty] Allow `Final` variable assignments in `__post_init__` (#24529)
  [ty] Expand test suite for assignment errors (#24537)
  [ty] Use `map`, not `__map`, as the name of the mapping parameter in `TypedDict` `__init__` methods (#24535)
  [ty] Rework logic for synthesizing `TypedDict` methods (#24534)
  [flake8-bandit] Fix S103 false positives and negatives in mask analysis (#24424)
  [ty] mdtest.py: update dependencies (#24533)
  Rename patterns and arguments source order iterator method (#24532)
  [ty] Omit invalid keyword arguments from `TypedDict` signature (#24522)
  [ty] support super() in metaclass methods (#24483)
  [ty] Synthesize `__init__` for `TypedDict` (#24476)
ibraheemdev pushed a commit that referenced this pull request Apr 15, 2026
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
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.

False positive invalid-super-argument in metaclass __call__ with TypeVar-typed cls

4 participants