Skip to content

Commit d8e8a11

Browse files
committed
Fix determination of propset in multimodule compilation
1 parent 26bd874 commit d8e8a11

3 files changed

Lines changed: 25 additions & 2 deletions

File tree

mypyc/codegen/emitfunc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ def visit_set_attr(self, op: SetAttr) -> None:
484484
rtype = op.class_type
485485
cl = rtype.class_ir
486486
attr_rtype, decl_cl = cl.attr_details(op.attr)
487-
if op.is_propset:
487+
if cl.get_method(op.attr):
488488
# Again, use vtable access for properties...
489489
assert not op.is_init and op.error_kind == ERR_FALSE, "%s %d %d %s" % (
490490
op.attr,

mypyc/ir/ops.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class to enable the new behavior. Sometimes adding a new abstract
3131

3232
from mypy_extensions import trait
3333

34+
from mypyc.common import PROPSET_PREFIX
3435
from mypyc.ir.deps import Dependency
3536
from mypyc.ir.rtypes import (
3637
RArray,
@@ -926,8 +927,14 @@ def __init__(self, obj: Value, attr: str, src: Value, line: int) -> None:
926927
self.is_init = False
927928

928929
cl = self.class_type.class_ir
930+
is_propset = False
931+
for ir in cl.mro:
932+
propset = ir.method_decls.get(PROPSET_PREFIX + attr)
933+
if propset is not None:
934+
is_propset = not propset.implicit
935+
break
929936
# If True, this op represents calling a property setter.
930-
self.is_propset = cl.get_method(self.attr) is not None
937+
self.is_propset = is_propset
931938

932939
def mark_as_initializer(self) -> None:
933940
self.is_init = True

mypyc/test-data/run-classes.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2164,6 +2164,21 @@ import gc
21642164

21652165
from native import A, B, C, D, E, F, Foo, G
21662166

2167+
def test_leaks() -> None:
2168+
a = A()
2169+
2170+
gc.collect()
2171+
before = gc.get_objects()
2172+
for _ in range(100):
2173+
a.foo = Foo()
2174+
gc.collect()
2175+
after = gc.get_objects()
2176+
2177+
diff = len(after) - len(before)
2178+
# Small difference is expected, if the property setter call was leaking objects
2179+
# we would get a difference similar to the number of iterations above.
2180+
assert diff <= 2, diff
2181+
21672182
def set_foo(foo: Foo) -> None:
21682183
a = A()
21692184
a.foo = foo
@@ -2212,6 +2227,7 @@ g = G(4)
22122227
g.x = 20
22132228
assert g.x == 20
22142229

2230+
test_leaks()
22152231
test_use_after_passing_to_prop_setter()
22162232

22172233
[file driver.py]

0 commit comments

Comments
 (0)