7272from mypyc .ir .pprint import generate_names_for_ir
7373from mypyc .ir .rtypes import (
7474 RArray ,
75+ RInstance ,
7576 RStruct ,
7677 RTuple ,
7778 RType ,
@@ -362,20 +363,23 @@ def visit_get_attr(self, op: GetAttr) -> None:
362363 prefer_method = cl .is_trait and attr_rtype .error_overlap
363364 if cl .get_method (op .attr , prefer_method = prefer_method ):
364365 # Properties are essentially methods, so use vtable access for them.
365- version = "_TRAIT" if cl .is_trait else ""
366- self .emit_line (
367- "%s = CPY_GET_ATTR%s(%s, %s, %d, %s, %s); /* %s */"
368- % (
369- dest ,
370- version ,
371- obj ,
372- self .emitter .type_struct_name (rtype .class_ir ),
373- rtype .getter_index (op .attr ),
374- rtype .struct_name (self .names ),
375- self .ctype (rtype .attr_type (op .attr )),
376- op .attr ,
366+ if cl .is_method_final (op .attr ):
367+ self .emit_method_call (f"{ dest } = " , op .obj , op .attr , [])
368+ else :
369+ version = "_TRAIT" if cl .is_trait else ""
370+ self .emit_line (
371+ "%s = CPY_GET_ATTR%s(%s, %s, %d, %s, %s); /* %s */"
372+ % (
373+ dest ,
374+ version ,
375+ obj ,
376+ self .emitter .type_struct_name (rtype .class_ir ),
377+ rtype .getter_index (op .attr ),
378+ rtype .struct_name (self .names ),
379+ self .ctype (rtype .attr_type (op .attr )),
380+ op .attr ,
381+ )
377382 )
378- )
379383 else :
380384 # Otherwise, use direct or offset struct access.
381385 attr_expr = self .get_attr_expr (obj , op , decl_cl )
@@ -529,11 +533,13 @@ def visit_call(self, op: Call) -> None:
529533 def visit_method_call (self , op : MethodCall ) -> None :
530534 """Call native method."""
531535 dest = self .get_dest_assign (op )
532- obj = self .reg ( op .obj )
536+ self .emit_method_call ( dest , op .obj , op . method , op . args )
533537
534- rtype = op .receiver_type
538+ def emit_method_call (self , dest : str , op_obj : Value , name : str , op_args : list [Value ]) -> None :
539+ obj = self .reg (op_obj )
540+ rtype = op_obj .type
541+ assert isinstance (rtype , RInstance )
535542 class_ir = rtype .class_ir
536- name = op .method
537543 method = rtype .class_ir .get_method (name )
538544 assert method is not None
539545
@@ -547,7 +553,7 @@ def visit_method_call(self, op: MethodCall) -> None:
547553 if method .decl .kind == FUNC_STATICMETHOD
548554 else [f"(PyObject *)Py_TYPE({ obj } )" ] if method .decl .kind == FUNC_CLASSMETHOD else [obj ]
549555 )
550- args = ", " .join (obj_args + [self .reg (arg ) for arg in op . args ])
556+ args = ", " .join (obj_args + [self .reg (arg ) for arg in op_args ])
551557 mtype = native_function_type (method , self .emitter )
552558 version = "_TRAIT" if rtype .class_ir .is_trait else ""
553559 if is_direct :
@@ -567,7 +573,7 @@ def visit_method_call(self, op: MethodCall) -> None:
567573 rtype .struct_name (self .names ),
568574 mtype ,
569575 args ,
570- op . method ,
576+ name ,
571577 )
572578 )
573579
0 commit comments