@@ -303,7 +303,7 @@ def __init__(
303303 # Whether the current top-level expression contains a suspension point
304304 # (await, yield or yield from). A whole-expression borrow can't span such a
305305 # point, since the borrowed value (and its root) live in registers that are
306- # not spilled into the generator environment across the suspend.
306+ # not spilled into the generator frame across the suspend.
307307 self .expr_has_suspend = False
308308 # Saved expression state for enclosing functions (see enter()/leave()).
309309 self .expression_depth_stack : list [int ] = []
@@ -1046,22 +1046,26 @@ def pop_loop_stack(self) -> None:
10461046 self .nonlocal_control .pop ()
10471047
10481048 def make_spill_target (self , type : RType ) -> AssignmentTarget :
1049- """Moves a given Value instance into the generator class' environment class."""
1050- name = f"{ TEMP_ATTR_NAME } { self .temp_counter } "
1049+ """Moves a given Value instance into the private generator frame."""
1050+ frame = self .fn_info .generator_class
1051+ # Generator classes for overriding methods can inherit from one another. Include the
1052+ # module-qualified owning class name so unrelated helper spills don't alias an inherited
1053+ # struct field.
1054+ name = f"{ TEMP_ATTR_NAME } 1_{ exported_name (frame .ir .fullname )} _{ self .temp_counter } "
10511055 self .temp_counter += 1
1052- target = self .add_var_to_env_class (Var (name ), type , self . fn_info . generator_class )
1056+ target = self .add_var_to_class (Var (name ), type , frame . ir , frame . self_reg )
10531057 return target
10541058
10551059 def spill (self , value : Value ) -> AssignmentTarget :
1056- """Moves a given Value instance into the generator class' environment class ."""
1060+ """Moves a given Value instance into the private generator frame ."""
10571061 target = self .make_spill_target (value .type )
10581062 # Shouldn't be able to fail
10591063 self .assign (target , value , NO_TRACEBACK_LINE_NO )
10601064 return target
10611065
10621066 def maybe_spill (self , value : Value ) -> Value | AssignmentTarget :
10631067 """
1064- Moves a given Value instance into the environment class for generator functions. For
1068+ Moves a given Value instance into the private frame for generator functions. For
10651069 non-generator functions, leaves the Value instance as it is.
10661070
10671071 Returns an AssignmentTarget associated with the Value for generator functions and the
@@ -1073,7 +1077,7 @@ def maybe_spill(self, value: Value) -> Value | AssignmentTarget:
10731077
10741078 def maybe_spill_assignable (self , value : Value ) -> Register | AssignmentTarget :
10751079 """
1076- Moves a given Value instance into the environment class for generator functions. For
1080+ Moves a given Value instance into the private frame for generator functions. For
10771081 non-generator functions, allocate a temporary Register.
10781082
10791083 Returns an AssignmentTarget associated with the Value for generator functions and an
@@ -1633,24 +1637,45 @@ def add_var_to_env_class(
16331637 keep_alive_on_completion : bool = False ,
16341638 prefix : str = "" ,
16351639 ) -> AssignmentTarget :
1636- # First, define the variable name as an attribute of the environment class, and then
1637- # construct a target for that attribute.
1640+ return self .add_var_to_class (
1641+ var ,
1642+ rtype ,
1643+ self .fn_info .env_class ,
1644+ base .curr_env_reg ,
1645+ reassign = reassign ,
1646+ always_defined = always_defined ,
1647+ keep_alive_on_completion = keep_alive_on_completion ,
1648+ prefix = prefix ,
1649+ )
1650+
1651+ def add_var_to_class (
1652+ self ,
1653+ var : SymbolNode ,
1654+ rtype : RType ,
1655+ cls : ClassIR ,
1656+ base : Value ,
1657+ reassign : bool = False ,
1658+ always_defined : bool = False ,
1659+ keep_alive_on_completion : bool = False ,
1660+ prefix : str = "" ,
1661+ ) -> AssignmentTarget :
1662+ """Declare an attribute on a class and construct a target using an explicit base."""
16381663 name = prefix + remangle_redefinition_name (var .name )
1639- self . fn_info . env_class .attributes [name ] = rtype
1664+ cls .attributes [name ] = rtype
16401665 if keep_alive_on_completion :
1641- self . fn_info . env_class .attrs_to_keep_alive_on_completion .add (name )
1666+ cls .attrs_to_keep_alive_on_completion .add (name )
16421667 if always_defined :
1643- self . fn_info . env_class .attrs_with_defaults .add (name )
1644- attr_target = AssignmentTargetAttr (base . curr_env_reg , name )
1668+ cls .attrs_with_defaults .add (name )
1669+ attr_target = AssignmentTargetAttr (base , name )
16451670
16461671 if reassign :
16471672 # Read the local definition of the variable, and set the corresponding attribute of
1648- # the environment class' variable to be that value.
1673+ # the class' variable to be that value.
16491674 reg = self .read (self .lookup (var ), self .fn_info .fitem .line )
1650- self .add (SetAttr (base . curr_env_reg , name , reg , self .fn_info .fitem .line ))
1675+ self .add (SetAttr (base , name , reg , self .fn_info .fitem .line ))
16511676
16521677 # Override the local definition of the variable to instead point at the variable in
1653- # the environment class.
1678+ # the class.
16541679 return self .add_target (var , attr_target )
16551680
16561681 def is_builtin_ref_expr (self , expr : RefExpr ) -> bool :
0 commit comments