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
9 changes: 8 additions & 1 deletion mypyc/irbuild/callable_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ class for the nested function.
# this is a toplevel lambda), don't set up an environment.
if builder.fn_infos[-2].contains_nested:
callable_class_ir.attributes[ENV_ATTR_NAME] = RInstance(builder.fn_infos[-2].env_class)
# The link is initialized before the callable is published and is never rebound.
# Treating it as Final permits plain loads on free-threaded builds.
callable_class_ir.final_attributes.add(ENV_ATTR_NAME)
callable_class_ir.mro = [callable_class_ir]
builder.fn_info.callable_class = ImplicitClass(callable_class_ir)
builder.classes.append(callable_class_ir)
Expand Down Expand Up @@ -235,7 +238,11 @@ def instantiate_callable_class(builder: IRBuilder, fn_info: FuncInfo) -> Value:
elif builder.fn_info.contains_nested:
curr_env_reg = builder.fn_info.curr_env_reg
if curr_env_reg:
builder.add(SetAttr(func_reg, ENV_ATTR_NAME, curr_env_reg, fitem.line))
set_env = SetAttr(func_reg, ENV_ATTR_NAME, curr_env_reg, fitem.line)
# A new or freelist-reused callable has had all of its fields cleared, and this store
# happens before the callable can escape.
set_env.mark_as_initializer()
builder.add(set_env)
# Initialize function wrapper for callable classes. As opposed to regular functions,
# each instance of a callable class needs its own wrapper because they might be instantiated
# inside other functions.
Expand Down
127 changes: 59 additions & 68 deletions mypyc/test-data/irbuild-basic.test
Original file line number Diff line number Diff line change
Expand Up @@ -2475,13 +2475,12 @@ def a(f):
r0 :: __main__.a_env
r1 :: bool
r2 :: __main__.g_a_obj
r3 :: bool
g :: object
L0:
r0 = a_env()
r0.f = f; r1 = is_error
r2 = g_a_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r2.__mypyc_env__ = r0
g = r2
return g
def g_b_obj.__get__(__mypyc_self__, instance, owner):
Expand Down Expand Up @@ -2540,13 +2539,12 @@ def b(f):
r0 :: __main__.b_env
r1 :: bool
r2 :: __main__.g_b_obj
r3 :: bool
g :: object
L0:
r0 = b_env()
r0.f = f; r1 = is_error
r2 = g_b_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r2.__mypyc_env__ = r0
g = r2
return g
def d_c_obj.__get__(__mypyc_self__, instance, owner):
Expand Down Expand Up @@ -2586,62 +2584,61 @@ L0:
def c():
r0 :: __main__.c_env
r1 :: __main__.d_c_obj
r2 :: bool
r3 :: dict
r4 :: str
r5 :: object
r6 :: object[1]
r7 :: object_ptr
r8 :: object
r9 :: dict
r10 :: str
r11 :: object
r12 :: object[1]
r13 :: object_ptr
r14, d :: object
r15 :: dict
r16 :: str
r17 :: i32
r18 :: bit
r19 :: str
r20 :: object
r21 :: str
r22 :: object
r23 :: object[1]
r24 :: object_ptr
r25, r26 :: object
r2 :: dict
r3 :: str
r4 :: object
r5 :: object[1]
r6 :: object_ptr
r7 :: object
r8 :: dict
r9 :: str
r10 :: object
r11 :: object[1]
r12 :: object_ptr
r13, d :: object
r14 :: dict
r15 :: str
r16 :: i32
r17 :: bit
r18 :: str
r19 :: object
r20 :: str
r21 :: object
r22 :: object[1]
r23 :: object_ptr
r24, r25 :: object
L0:
r0 = c_env()
r1 = d_c_obj()
r1.__mypyc_env__ = r0; r2 = is_error
r3 = __main__.globals :: static
r4 = 'b'
r5 = CPyDict_GetItem(r3, r4)
r6 = [r1]
r7 = load_address r6
r8 = PyObject_Vectorcall(r5, r7, 1, 0)
r1.__mypyc_env__ = r0
r2 = __main__.globals :: static
r3 = 'b'
r4 = CPyDict_GetItem(r2, r3)
r5 = [r1]
r6 = load_address r5
r7 = PyObject_Vectorcall(r4, r6, 1, 0)
keep_alive r1
r9 = __main__.globals :: static
r10 = 'a'
r11 = CPyDict_GetItem(r9, r10)
r12 = [r8]
r13 = load_address r12
r14 = PyObject_Vectorcall(r11, r13, 1, 0)
keep_alive r8
d = r14
r15 = __main__.globals :: static
r16 = 'd'
r17 = PyDict_SetItem(r15, r16, r14)
r18 = r17 >= 0 :: signed
r19 = 'c'
r20 = builtins :: module
r21 = 'print'
r22 = CPyObject_GetAttr(r20, r21)
r23 = [r19]
r24 = load_address r23
r25 = PyObject_Vectorcall(r22, r24, 1, 0)
keep_alive r19
r26 = PyObject_Vectorcall(d, 0, 0, 0)
r8 = __main__.globals :: static
r9 = 'a'
r10 = CPyDict_GetItem(r8, r9)
r11 = [r7]
r12 = load_address r11
r13 = PyObject_Vectorcall(r10, r12, 1, 0)
keep_alive r7
d = r13
r14 = __main__.globals :: static
r15 = 'd'
r16 = PyDict_SetItem(r14, r15, r13)
r17 = r16 >= 0 :: signed
r18 = 'c'
r19 = builtins :: module
r20 = 'print'
r21 = CPyObject_GetAttr(r19, r20)
r22 = [r18]
r23 = load_address r22
r24 = PyObject_Vectorcall(r21, r23, 1, 0)
keep_alive r18
r25 = PyObject_Vectorcall(d, 0, 0, 0)
return 1
def __top_level__():
r0, r1 :: object
Expand Down Expand Up @@ -2775,13 +2772,12 @@ def a(f):
r0 :: __main__.a_env
r1 :: bool
r2 :: __main__.g_a_obj
r3 :: bool
g :: object
L0:
r0 = a_env()
r0.f = f; r1 = is_error
r2 = g_a_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r2.__mypyc_env__ = r0
g = r2
return g
def __top_level__():
Expand Down Expand Up @@ -3588,13 +3584,12 @@ def deco(fn):
r0 :: __main__.deco_env
r1 :: bool
r2 :: __main__.wrapper_deco_obj
r3 :: bool
wrapper :: object
L0:
r0 = deco_env()
r0.fn = fn; r1 = is_error
r2 = wrapper_deco_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r2.__mypyc_env__ = r0
wrapper = r2
return wrapper

Expand Down Expand Up @@ -3637,13 +3632,12 @@ def deco(fn):
r0 :: __main__.deco_env
r1 :: bool
r2 :: __main__.wrapper_deco_obj
r3 :: bool
wrapper :: object
L0:
r0 = deco_env()
r0.fn = fn; r1 = is_error
r2 = wrapper_deco_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r2.__mypyc_env__ = r0
wrapper = r2
return wrapper

Expand Down Expand Up @@ -3689,13 +3683,12 @@ def deco(fn):
r0 :: __main__.deco_env
r1 :: bool
r2 :: __main__.wrapper_deco_obj
r3 :: bool
wrapper :: object
L0:
r0 = deco_env()
r0.fn = fn; r1 = is_error
r2 = wrapper_deco_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r2.__mypyc_env__ = r0
wrapper = r2
return wrapper

Expand Down Expand Up @@ -3738,13 +3731,12 @@ def deco(fn):
r0 :: __main__.deco_env
r1 :: bool
r2 :: __main__.wrapper_deco_obj
r3 :: bool
wrapper :: object
L0:
r0 = deco_env()
r0.fn = fn; r1 = is_error
r2 = wrapper_deco_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r2.__mypyc_env__ = r0
wrapper = r2
return wrapper

Expand Down Expand Up @@ -3790,13 +3782,12 @@ def deco(fn):
r0 :: __main__.deco_env
r1 :: bool
r2 :: __main__.wrapper_deco_obj
r3 :: bool
wrapper :: object
L0:
r0 = deco_env()
r0.fn = fn; r1 = is_error
r2 = wrapper_deco_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r2.__mypyc_env__ = r0
wrapper = r2
return wrapper

Expand Down
4 changes: 1 addition & 3 deletions mypyc/test-data/irbuild-generics.test
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ def f(x):
x :: int
L0:
return x

[case testTypeVarMappingBound]
# Dicts are special-cased for efficient iteration.
from typing import Dict, TypedDict, TypeVar, Union
Expand Down Expand Up @@ -760,13 +759,12 @@ def deco(func):
r0 :: __main__.deco_env
r1 :: bool
r2 :: __main__.inner_deco_obj
r3 :: bool
inner :: object
L0:
r0 = deco_env()
r0.func = func; r1 = is_error
r2 = inner_deco_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r2.__mypyc_env__ = r0
inner = r2
return inner
def f(x):
Expand Down
Loading
Loading