Skip to content

fix assert_type with metaclasses #3228#3243

Open
asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
asukaminato0721:3228
Open

fix assert_type with metaclasses #3228#3243
asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
asukaminato0721:3228

Conversation

@asukaminato0721
Copy link
Copy Markdown
Contributor

@asukaminato0721 asukaminato0721 commented Apr 25, 2026

Summary

Fixes #3228

assert_type no longer accepts a class object as exactly equal to its non-type metaclass.

Test Plan

add test

@github-actions
Copy link
Copy Markdown

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

@asukaminato0721 asukaminato0721 marked this pull request as ready for review April 25, 2026 19:00
Copilot AI review requested due to automatic review settings April 25, 2026 19:00
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes typing.assert_type behavior for classes with custom metaclasses so that asserting a class object against its metaclass (e.g., assert_type(A, Meta)) correctly fails, aligning with the typing spec and other type checkers.

Changes:

  • Updated call_assert_type to explicitly treat “class object is an instance of a non-type metaclass” as a mismatch for assert_type equivalence.
  • Added a regression test covering assert_type with a custom metaclass.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
pyrefly/lib/test/simple.rs Adds a regression testcase ensuring assert_type(A, Meta) produces an error for metaclass instances.
pyrefly/lib/alt/special_calls.rs Adjusts assert_type checking logic to reject metaclass-instance matches (except for builtin type) even if prior equivalence logic allowed them.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +63 to +73
let matches_metaclass_instance = match (&a, &b) {
(Type::ClassDef(got), Type::ClassType(want)) => {
!want.is_builtin("type") && self.type_order().has_metaclass(got, want)
}
(Type::Type(box Type::ClassType(got)), Type::ClassType(want)) => {
!want.is_builtin("type")
&& self.type_order().has_metaclass(got.class_object(), want)
}
_ => false,
};
if matches_metaclass_instance || !self.is_equivalent(&a, &b) {
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

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

matches_metaclass_instance is a boolean that triggers the error path when true, so the name reads as if it's a success condition even though it represents a mismatch case. Consider renaming it (e.g., is_metaclass_assert_mismatch / metaclass_instance_mismatch) or inverting the boolean so the if condition reads more directly.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

assert_type with metaclasses

2 participants