Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9a358fc
[mypyc] fix: isinstance_native fast path conflict w/ subclasses
BobTheBuidler Sep 30, 2025
8446150
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 30, 2025
f84f576
handle non-native final
BobTheBuidler Sep 30, 2025
376356b
Update class_ir.py
BobTheBuidler Oct 1, 2025
c22e6a4
Update ll_builder.py
BobTheBuidler Oct 1, 2025
70cdff9
Update class_ir.py
BobTheBuidler Oct 1, 2025
9a50f54
Merge branch 'master' into fix-isinstance-native-interpreted-subclass
BobTheBuidler Oct 1, 2025
7459701
Update irbuild-classes.test
BobTheBuidler Oct 3, 2025
86e5b00
refactor
BobTheBuidler Oct 3, 2025
d8602a0
Update irbuild-classes.test
BobTheBuidler Oct 4, 2025
9fce629
Update irbuild-classes.test
BobTheBuidler Oct 4, 2025
b90961e
Update irbuild-classes.test
BobTheBuidler Oct 4, 2025
a554654
Update irbuild-classes.test
BobTheBuidler Oct 4, 2025
f514765
Update class_ir.py
BobTheBuidler Oct 4, 2025
bee44dc
Update class_ir.py
BobTheBuidler Oct 4, 2025
3158d15
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 4, 2025
71a3c96
Update class_ir.py
BobTheBuidler Oct 4, 2025
89b2e8f
Merge branch 'master' into fix-isinstance-native-interpreted-subclass
BobTheBuidler Oct 7, 2025
da41e3f
Merge branch 'master' into fix-isinstance-native-interpreted-subclass
BobTheBuidler Nov 13, 2025
997364e
Update class_ir.py
BobTheBuidler Nov 15, 2025
726e36e
Update class_ir.py
BobTheBuidler Nov 15, 2025
d8b2f2b
fix: change :: to =
BobTheBuidler Nov 16, 2025
40876a8
fix: non-native class
BobTheBuidler Nov 17, 2025
ec59e5b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 17, 2025
cfac061
Update class_ir.py
BobTheBuidler Nov 17, 2025
9dbc600
Update ll_builder.py
BobTheBuidler Nov 17, 2025
a379621
Merge branch 'master' into fix-isinstance-native-interpreted-subclass
BobTheBuidler Nov 17, 2025
b617fed
Update class_ir.py
BobTheBuidler Nov 17, 2025
b8aadd6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 17, 2025
f06e6b6
Update class_ir.py
BobTheBuidler Nov 17, 2025
e47b5f9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions mypyc/ir/class_ir.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,23 +333,30 @@ def has_method_decl(self, name: str) -> bool:
return any(name in ir.method_decls for ir in self.mro)

def has_no_subclasses(self) -> bool:
return self.children == [] and not self.allow_interpreted_subclasses
return (
self.children == []
and not self.allow_interpreted_subclasses
and (self.is_ext_class or self.is_final_class)
)

def subclasses(self) -> set[ClassIR] | None:
"""Return all subclasses of this class, both direct and indirect.

Return None if it is impossible to identify all subclasses, for example
because we are performing separate compilation.
"""
if self.children is None or self.allow_interpreted_subclasses:
if (
(not self.is_ext_class and not self.is_final_class)
or self.allow_interpreted_subclasses
or self.children is None
):
return None
result = set(self.children)
for child in self.children:
if child.children:
child_subs = child.subclasses()
if child_subs is None:
return None
result.update(child_subs)
child_subs = child.subclasses()
if child_subs is None:
return None
result.update(child_subs)
return result

def concrete_subclasses(self) -> list[ClassIR] | None:
Expand Down
4 changes: 2 additions & 2 deletions mypyc/irbuild/ll_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,8 +697,8 @@ def isinstance_native(self, obj: Value, class_ir: ClassIR, line: int) -> Value:
"""Fast isinstance() check for a native class.

If there are three or fewer concrete (non-trait) classes among the class
and all its children, use even faster type comparison checks `type(obj)
is typ`.
and all its children, and none of them allow interpreted subclasses, use
even faster type comparison checks `type(obj) is typ`.
"""
concrete = all_concrete_classes(class_ir)
if concrete is None or len(concrete) > FAST_ISINSTANCE_MAX_SUBCLASSES + 1:
Expand Down
37 changes: 37 additions & 0 deletions mypyc/test-data/irbuild-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -2865,3 +2865,40 @@ class InvalidKwarg:
@mypyc_attr(str()) # E: All "mypyc_attr" positional arguments must be string literals.
class InvalidLiteral:
pass

[case testIsInstanceInterpretedSubclasses]
from typing import Any
from mypy_extensions import mypyc_attr

@mypyc_attr(native_class=False)
class NonNative:
pass

@mypyc_attr(allow_interpreted_subclasses=True)
class InterpSubclasses:
pass

def isinstance_nonnative(x: Any) -> bool:
return isinstance(x, NonNative)
def isinstance_interpreted_subclasses(x: Any) -> bool:
return isinstance(x, InterpSubclasses)
[out]
def isinstance_nonnative(x):
x, r0 :: object
r1 :: ptr
r2 :: object
r3 :: bit
L0:
r0 = __main__.NonNative :: type
r1 = get_element_ptr x ob_type :: PyObject
r2 = borrow load_mem r1 :: builtins.object*
keep_alive x
r3 = r2 == r0
Copy link
Collaborator

Choose a reason for hiding this comment

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

Non-native classes implicitly allow interpreted subclasses, so this should also use CPy_TypeCheck. Can you also add a run test for these that defines the subclasses and uses them with isinstance?

return r3
def isinstance_interpreted_subclasses(x):
x, r0 :: object
r1 :: bool
L0:
r0 = __main__.InterpSubclasses :: type
r1 = CPy_TypeCheck(x, r0)
return r1
Loading