Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 0 additions & 4 deletions mypyc/codegen/emitclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,6 @@ def generate_class_reuse(
TODO: Generalize to support a free list with up to N objects.
"""
assert cl.reuse_freed_instance

# The free list implementation doesn't support class hierarchies
assert cl.is_final_class or cl.children == []

context = c_emitter.context
name = cl.name_prefix(c_emitter.names) + "_free_instance"
struct_name = cl.struct_name(c_emitter.names)
Expand Down
6 changes: 6 additions & 0 deletions mypyc/irbuild/prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,12 @@ def prepare_class_def(
line = attrs_lines["free_list_len"]
if ir.is_trait:
errors.error('"free_list_len" can\'t be used with traits', path, line)
if ir.allow_interpreted_subclasses:
errors.error(
'"free_list_len" can\'t be used in a class that allows interpreted subclasses',
path,
line,
)
if free_list_len == 1:
ir.reuse_freed_instance = True
else:
Expand Down
4 changes: 4 additions & 0 deletions mypyc/test-data/irbuild-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -1754,3 +1754,7 @@ class FreeListError:
@mypyc_attr(free_list_len=1) # E: "free_list_len" can't be used with traits
class NonNative:
pass

@mypyc_attr(free_list_len=1, allow_interpreted_subclasses=True) # E: "free_list_len" can't be used in a class that allows interpreted subclasses
class InterpSub:
pass
63 changes: 62 additions & 1 deletion mypyc/test-data/run-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -3802,7 +3802,7 @@ from mypy_extensions import mypyc_attr

a = []

@mypyc_attr(free_list=1)
@mypyc_attr(free_list_len=1)
class Foo:
def __init__(self, x: int) -> None:
self.x = x
Expand Down Expand Up @@ -3830,3 +3830,64 @@ def test_alloc() -> None:
y = Foo(5)
assert x.x == 4
assert y.x == 5

@mypyc_attr(free_list_len=1)
class Base:
def __init__(self, x: str) -> None:
self.x = x

class Deriv(Base):
def __init__(self, x: str, y: str) -> None:
super().__init__(x)
self.y = y

@mypyc_attr(free_list_len=1)
class Deriv2(Base):
def __init__(self, x: str, y: str) -> None:
super().__init__(x)
self.y = y

def test_inheritance() -> None:
x: Base | None
y: Base | None
x = Base('x' + str())
y = Base('y' + str())
y = None
d = Deriv('a' + str(), 'b' + str())
assert type(d) is Deriv
assert d.x == 'a'
assert d.y == 'b'
assert x.x == 'x'
y = Base('z' + str())
assert d.x == 'a'
assert d.y == 'b'
assert y.x == 'z'
x = None
y = None

def test_inheritance_2() -> None:
x: Base | None
y: Base | None
d: Deriv2 | None
x = Base('x' + str())
y = Base('y' + str())
y = None
d = Deriv2('a' + str(), 'b' + str())
assert type(d) is Deriv2
assert d.x == 'a'
assert d.y == 'b'
assert x.x == 'x'
d = None
d = Deriv2('c' + str(), 'd' + str())
assert type(d) is Deriv2
assert d.x == 'c'
assert d.y == 'd'
assert x.x == 'x'
y = Base('z' + str())
assert type(y) is Base
assert d.x == 'c'
assert d.y == 'd'
assert y.x == 'z'
x = None
y = None
d = None
Loading