fix assert_type with metaclasses #3228#3243
fix assert_type with metaclasses #3228#3243asukaminato0721 wants to merge 2 commits intofacebook:mainfrom
Conversation
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
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_typeto explicitly treat “class object is an instance of a non-typemetaclass” as a mismatch forassert_typeequivalence. - Added a regression test covering
assert_typewith 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.
|
@kinto0 has imported this pull request. If you are a Meta employee, you can view this in D103049155. |
grievejia
left a comment
There was a problem hiding this comment.
Review automatically exported from Phabricator review in Meta.
|
from @grievejia
|
|
Diff from mypy_primer, showing the effect of this PR on open source code: comtypes (https://github.com/enthought/comtypes)
+ ERROR comtypes/safearray.py:112:19-28: No matching overload found for function `_ctypes.POINTER` called with arguments: (_PyCStructType) [no-matching-overload]
+ ERROR comtypes/safearray.py:380:27-36: No matching overload found for function `_ctypes.POINTER` called with arguments: (_PyCStructType) [no-matching-overload]
- ERROR comtypes/safearray.py:393:13-51: Expected first argument to `super` to be a class object, got `type[_Pointer[_Pointer[Unknown]]]` [invalid-argument]
+ ERROR comtypes/safearray.py:393:34-43: No matching overload found for function `_ctypes.POINTER` called with arguments: (_PyCStructType) [no-matching-overload]
manticore (https://github.com/trailofbits/manticore)
+ ERROR manticore/core/state_pb2.py:333:25-35: Argument `GeneratedProtocolMessageType` is not assignable to parameter `message` with type `Message | type[Message]` in function `google.protobuf.symbol_database.SymbolDatabase.RegisterMessage` [bad-argument-type]
+ ERROR manticore/core/state_pb2.py:344:25-30: Argument `GeneratedProtocolMessageType` is not assignable to parameter `message` with type `Message | type[Message]` in function `google.protobuf.symbol_database.SymbolDatabase.RegisterMessage` [bad-argument-type]
+ ERROR manticore/core/state_pb2.py:355:25-34: Argument `GeneratedProtocolMessageType` is not assignable to parameter `message` with type `Message | type[Message]` in function `google.protobuf.symbol_database.SymbolDatabase.RegisterMessage` [bad-argument-type]
+ ERROR manticore/core/state_pb2.py:366:25-36: Argument `GeneratedProtocolMessageType` is not assignable to parameter `message` with type `Message | type[Message]` in function `google.protobuf.symbol_database.SymbolDatabase.RegisterMessage` [bad-argument-type]
streamlit (https://github.com/streamlit/streamlit)
+ ERROR lib/streamlit/elements/lib/options_selector_utils.py:162:36-49: Expected class object, got `EnumMeta & type[E2]` [invalid-argument]
+ ERROR lib/streamlit/elements/lib/options_selector_utils.py:198:12-49: Cannot index into `EnumMeta` [bad-index]
+ ERROR lib/streamlit/elements/lib/options_selector_utils.py:254:52-64: Argument `EnumMeta` is not assignable to parameter `to_enum_class` with type `type[@_]` in function `_coerce_enum` [bad-argument-type]
+ ERROR lib/streamlit/elements/lib/options_selector_utils.py:303:31-43: Argument `EnumMeta` is not assignable to parameter `to_enum_class` with type `type[@_]` in function `_coerce_enum` [bad-argument-type]
pandera (https://github.com/pandera-dev/pandera)
+ ERROR tests/pandas/test_decorators.py:1801:29-38: Argument `type[test_coroutines.Meta]` is not assignable to parameter `mcs` with type `type[type[test_coroutines.SomeClass]]` in function `Meta.class_meta_coroutine` [bad-argument-type]
+ ERROR tests/pandas/test_decorators.py:1805:27-35: Argument `type[test_coroutines.Meta]` is not assignable to parameter `mcs` with type `type[type[test_coroutines.SomeClass]]` in function `Meta.class_meta_coroutine` [bad-argument-type]
ibis (https://github.com/ibis-project/ibis)
+ ERROR ibis/common/tests/test_grounds.py:250:19-21: Expected 0 positional arguments, got 1 in function `Between.__init__` [bad-argument-count]
+ ERROR ibis/common/tests/test_grounds.py:250:23-28: Unexpected keyword argument `lower` in function `Between.__init__` [unexpected-keyword]
+ ERROR ibis/common/tests/test_grounds.py:264:20-22: Expected 0 positional arguments, got 1 in function `Between.__init__` [bad-argument-count]
+ ERROR ibis/common/tests/test_grounds.py:264:24-29: Unexpected keyword argument `lower` in function `Between.__init__` [unexpected-keyword]
strawberry (https://github.com/strawberry-graphql/strawberry)
+ ERROR strawberry/schema/schema_converter.py:178:32-66: No matching overload found for function `enum.EnumMeta.__call__` called with arguments: (Any) [no-matching-overload]
+ ERROR strawberry/schema/schema_converter.py:183:32-79: No matching overload found for function `enum.EnumMeta.__call__` called with arguments: (Any) [no-matching-overload]
zope.interface (https://github.com/zopefoundation/zope.interface)
+ ERROR src/zope/interface/common/collections.py:131:5-8: Class member `IReversible.abc` overrides parent class `IIterable` in an inconsistent manner [bad-override-mutable-attribute]
+ ERROR src/zope/interface/common/collections.py:144:5-8: Class member `IGenerator.abc` overrides parent class `IIterator` in an inconsistent manner [bad-override-mutable-attribute]
+ ERROR src/zope/interface/common/collections.py:157:5-8: Class member `ICollection.abc` overrides parent class `ISized` in an inconsistent manner [bad-override-mutable-attribute]
+ ERROR src/zope/interface/common/collections.py:157:5-8: Class member `ICollection.abc` overrides parent class `IIterable` in an inconsistent manner [bad-override-mutable-attribute]
+ ERROR src/zope/interface/common/collections.py:157:5-8: Class member `ICollection.abc` overrides parent class `IContainer` in an inconsistent manner [bad-override-mutable-attribute]
+ ERROR src/zope/interface/common/collections.py:199:9-12: Class member `IByteString.abc` overrides parent class `ISequence` in an inconsistent manner [bad-override-mutable-attribute]
+ ERROR src/zope/interface/tests/odd.py:98:13-105:2: `MetaMetaClass` is not assignable to variable `MetaClass` with type `type[MetaClass]` [bad-assignment]
+ ERROR src/zope/interface/tests/test_odd_declarations.py:60:7-46: `MetaClass` is not assignable to variable `Odd` with type `type[Odd]` [bad-assignment]
- ERROR src/zope/interface/tests/test_odd_declarations.py:151:17-20: Invalid base class: `Odd | Unknown` [invalid-inheritance]
- ERROR src/zope/interface/tests/test_odd_declarations.py:155:17-20: Invalid base class: `Odd | Unknown` [invalid-inheritance]
- ERROR src/zope/interface/tests/test_odd_declarations.py:172:17-20: Invalid base class: `Odd | Unknown` [invalid-inheritance]
- ERROR src/zope/interface/tests/test_odd_declarations.py:176:17-20: Invalid base class: `Odd | Unknown` [invalid-inheritance]
- ERROR src/zope/interface/tests/test_odd_declarations.py:200:17-20: Invalid base class: `Odd | Unknown` [invalid-inheritance]
- ERROR src/zope/interface/tests/test_odd_declarations.py:204:17-20: Invalid base class: `Odd | Unknown` [invalid-inheritance]
- ERROR src/zope/interface/tests/test_odd_declarations.py:245:18-21: Invalid base class: `Odd | Unknown` [invalid-inheritance]
+ ERROR src/zope/interface/tests/test_odd_declarations.py:269:13-56: `MetaClass` is not assignable to variable `A` with type `type[Test.test_odd_metaclass_that_doesnt_subclass_type.A]` [bad-assignment]
+ ERROR src/zope/interface/tests/test_odd_declarations.py:274:13-56: `MetaClass` is not assignable to variable `B` with type `type[Test.test_odd_metaclass_that_doesnt_subclass_type.B]` [bad-assignment]
+ ERROR src/zope/interface/tests/test_odd_declarations.py:298:26-29: Object of class `C` has no attribute `c` [missing-attribute]
AutoSplit (https://github.com/Toufool/AutoSplit)
+ ERROR src/capture_method/__init__.py:57:16-23: No matching overload found for function `enum.EnumMeta.__call__` called with arguments: (object) [no-matching-overload]
kornia (https://github.com/kornia/kornia)
+ ERROR kornia/constants.py:36:32-34: Argument `Self@_KORNIA_EnumMeta` is not assignable to parameter `self` with type `type[@_]` in function `enum.EnumMeta.__iter__` [bad-argument-type]
|
Primer Diff Classification❌ 7 regression(s) | ✅ 1 improvement(s) | ❓ 1 needs review | 9 project(s) total | +30, -8 errors 7 regression(s) across comtypes, manticore, streamlit, pandera, strawberry, AutoSplit, kornia. error kinds:
Detailed analysis❌ Regression (7)comtypes (+3, -1)
Per-category reasoning:
manticore (+4)
streamlit (+4)
pandera (+2)
strawberry (+2)
AutoSplit (+1)
kornia (+1)
✅ Improvement (1)zope.interface (+9, -7)
❓ Needs Review (1)ibis (+4)
Suggested fixesSummary: The new metaclass subset rules in subset.rs are too broad — they reject ALL metaclass instances from matching type[X], but should allow matching when the metaclass instance is actually a subclass of X (i.e., when the metaclass created a class that inherits from X). 1. In the first new match arm in
Was this helpful? React with 👍 or 👎 Classification by primer-classifier (9 LLM) |
Summary
Fixes #3228
assert_type no longer accepts a class object as exactly equal to its non-type metaclass.
Test Plan
add test