@@ -812,26 +812,6 @@ def report_poverride(sup, inf, obj_specs):
812812 else :
813813 report (POVERRIDE_IMPORT (sup_obj .site , inf .desc .text ))
814814
815- def sort_method_declarations (declarations , obj_specs ):
816- if dml .globals .dml_version == (1 , 2 ):
817- # Backward compatibility: If there is exactly one default and
818- # one non-default implementation, then disregard template
819- # instantiation relations.
820- implementations = [impl for impl in declarations if not impl .abstract ]
821- if len (implementations ) == 2 :
822- [m1 , m2 ] = implementations
823- # create fake ranks to make sure methods end up in the right order
824- if m1 .overridable and not m2 .overridable :
825- if logging .show_porting :
826- report_poverride (m2 .obj_spec .rank , m1 .obj_spec .rank ,
827- obj_specs )
828- m2 .rank = Rank ({m1 .rank }, m2 .rank .desc )
829- elif not m1 .overridable and m2 .overridable :
830- if logging .show_porting :
831- report_poverride (m1 .rank , m2 .rank , obj_specs )
832- m1 .rank = Rank ({m2 .rank }, m1 .rank .desc )
833- return traits .sort_method_declarations (declarations )
834-
835815def merge_subobj_defs (def1 , def2 , parent ):
836816 (objtype , name , arrayinfo , obj_specs1 ) = def1
837817 (objtype2 , name2 , arrayinfo2 , obj_specs2 ) = def2
@@ -1460,14 +1440,12 @@ def __init__(self, name, vtable_trait):
14601440 super (AbstractTraitMethodHandle , self ).__init__ (
14611441 site , name , obj_spec , True , True , None , * sig )
14621442
1463-
1464-
14651443def process_method_declarations (obj , name , declarations ,
14661444 shared_impl_traits , shared_absdecl_traits ,
14671445 obj_specs , vtable_nothrow_dml14 ):
14681446 # A method can have both shared and non-shared declarations.
14691447 # We will create a MethodHandle object for either, which
1470- # sort_method_declarations () uses to resolve override order.
1448+ # sort_method_implementations () uses to resolve override order.
14711449 unshared_methods = [
14721450 ObjMethodHandle (method_ast , obj_spec )
14731451 for (obj_spec , method_ast ) in declarations ]
@@ -1480,9 +1458,55 @@ def process_method_declarations(obj, name, declarations,
14801458 AbstractTraitMethodHandle (name , vtable_trait )
14811459 for vtable_trait in shared_absdecl_traits ]
14821460
1483- (default_map , decl_ancestry_map , method_order ,
1484- abstract_decls ) = sort_method_declarations (
1485- unshared_methods + shared_methods + shared_abstract_methods , obj_specs )
1461+ methods = unshared_methods + shared_methods + shared_abstract_methods
1462+ impls = [meth for meth in methods if not meth .abstract ]
1463+
1464+ if dml .globals .dml_version == (1 , 2 ) and len (impls ) == 2 :
1465+ # Backward compatibility: If there is exactly one default and
1466+ # one non-default implementation, then disregard template
1467+ # instantiation relations.
1468+ [m1 , m2 ] = impls
1469+ # create fake ranks to make sure methods end up in the right order
1470+ if m1 .overridable and not m2 .overridable :
1471+ if logging .show_porting :
1472+ report_poverride (m2 .obj_spec .rank , m1 .obj_spec .rank , obj_specs )
1473+ m2 .rank = Rank ({m1 .rank }, m2 .rank .desc )
1474+ elif not m1 .overridable and m2 .overridable :
1475+ if logging .show_porting :
1476+ report_poverride (m1 .rank , m2 .rank , obj_specs )
1477+ m1 .rank = Rank ({m2 .rank }, m1 .rank .desc )
1478+
1479+ rank_to_methods = {}
1480+ for meth in methods :
1481+ rank_to_methods .setdefault (meth .rank , []).append (meth )
1482+
1483+ minimal_ancestry = traits .calc_minimal_ancestry (frozenset (rank_to_methods ))
1484+
1485+ for (r , meths ) in rank_to_methods .items ():
1486+ [impl , * others ] = sorted (meths , key = lambda meth : meth .abstract )
1487+ if impl .abstract :
1488+ continue
1489+
1490+ for other in others :
1491+ if not other .abstract :
1492+ # two conflicting method definitions in the same block
1493+ raise ENAMECOLL (other .site , impl .site , other .name )
1494+
1495+ if (not impl .shared # Handled separately
1496+ and impl .site .provisional_enabled (
1497+ provisional .explicit_method_decls )):
1498+ existing = others or [m for anc in minimal_ancestry [r ]
1499+ for m in rank_to_methods [anc ]]
1500+ if impl .explicit_decl :
1501+ if existing :
1502+ report (EOVERRIDEMETH (impl .site , existing [0 ].site ,
1503+ impl .name ,
1504+ 'default ' * impl .overridable ))
1505+ elif not existing :
1506+ report (ENOVERRIDEMETH (impl .site , impl .name ,
1507+ 'default ' * impl .overridable ))
1508+
1509+ (default_map , method_order ) = traits .sort_method_implementations (impls )
14861510
14871511 location = Location (obj , static_indices (obj ))
14881512
@@ -1497,29 +1521,39 @@ def process_method_declarations(obj, name, declarations,
14971521 else :
14981522 nonshared_impls .append (impl )
14991523
1500- if not nonshared_impls :
1501- if shared_methods :
1502- shared_impl_sig = shared_methods [0 ].signature
1503- for decl in abstract_decls :
1504- if decl .shared :
1505- # handled separately
1506- continue
1507-
1508- try :
1509- traits .typecheck_method_override (shared_impl_sig ,
1510- decl .signature )
1511- except DMLError as e :
1512- report (e )
1513- return None
1524+ abstract_decls = [meth for meth in methods
1525+ if meth .abstract and not meth .shared ]
1526+
1527+ # Typecheck nonshared abstract decls against each other
1528+ for (meth0 , meth1 ) in itertools .pairwise (abstract_decls ):
1529+ typecheck_method_override (meth0 .method_ast , meth1 .method_ast ,
1530+ location )
1531+
1532+ # Then typecheck any shared abstract declaration -- or, failing that,
1533+ # the highest ranking implementation -- against some arbitrary abstract
1534+ # decl
1535+ # This prioritization is because we consider the trait authorative for what
1536+ # the type should be.
1537+ if abstract_decls :
1538+ if shared_abstract_methods :
1539+ traits .typecheck_method_override (
1540+ abstract_decls [0 ].signature ,
1541+ shared_abstract_methods [0 ].signature )
1542+ elif method_order :
1543+ impl = method_order [0 ]
1544+ if impl .shared :
1545+ traits .typecheck_method_override (
1546+ impl .signature , abstract_decls [0 ].signature )
1547+ else :
1548+ typecheck_method_override (
1549+ impl .method_ast , abstract_decls [0 ].method_ast , location )
15141550 else :
1515- assert abstract_decls
1516- for decl in abstract_decls :
1517- # We favor reporting EABSTEMPLATE (done by the caller)
1518- # over EABSMETH
1519- if not decl .shared :
1520- report (EABSMETH (decl .site , name ))
1551+ # This only done in this path because we favor reporting
1552+ # EABSTEMPLATE (done by the caller) over EABSMETH
1553+ report (EABSMETH (abstract_decls [0 ].site , name ))
15211554
1522- return None
1555+ if not nonshared_impls :
1556+ return None
15231557
15241558 impl_to_method = {}
15251559 for (default_level , impl ) in reversed (list (enumerate (nonshared_impls ))):
@@ -1553,11 +1587,20 @@ def process_method_declarations(obj, name, declarations,
15531587 impl .site , vtable_nothrow_dml14 ,
15541588 obj , name , body , rbrace_site )
15551589 throws = False
1556-
1557- for ancestor_decl in decl_ancestry_map [impl ]:
1590+ for overridden in default_map [impl ]:
1591+ if not overridden .overridable :
1592+ raise EDMETH (impl .site , overridden .site , name )
1593+ # the override of trait ASTs is checked later, by
1594+ # traits.typecheck_method_override
1595+ if not overridden .shared :
1596+ # captured with ETMETH above
1597+ assert not impl .shared
1598+ typecheck_method_override (impl .method_ast ,
1599+ overridden .method_ast ,
1600+ location )
15581601 if (impl .site .dml_version () == (1 , 2 ) and throws
1559- and not ancestor_decl .throws
1560- and ancestor_decl .site .dml_version () == (1 , 4 )):
1602+ and not overridden .throws
1603+ and overridden .site .dml_version () == (1 , 4 )):
15611604 # If a 1.4 library file defines an overrideable
15621605 # non-throwing method, and a 1.2 device overrides
15631606 # this, then assume that the method was never
@@ -1566,11 +1609,12 @@ def process_method_declarations(obj, name, declarations,
15661609 # We modify the override to nothrow, and patch it
15671610 # to catch any exceptions.
15681611 body = wrap_method_body_in_try (
1569- impl .site , ancestor_decl .site ,
1612+ impl .site , overridden .site ,
15701613 obj , name , body , rbrace_site )
15711614 throws = False
1572- elif throws != ancestor_decl .throws :
1573- if dml .globals .dml_version == (1 , 2 ) and not throws :
1615+ elif throws != overridden .throws :
1616+ if (dml .globals .dml_version == (1 , 2 )
1617+ and not throws ):
15741618 # Permit a nonthrowing method to override
15751619 # a throwing 1.2 method, with no warning.
15761620 # This is needed for some common standard
@@ -1581,45 +1625,12 @@ def process_method_declarations(obj, name, declarations,
15811625 else :
15821626 annotation = ("no" * (dml .globals .dml_version != (1 , 4 ))
15831627 + "throw" )
1584- raise EMETH (impl .site , ancestor_decl .site ,
1628+ raise EMETH (impl .site , overridden .site ,
15851629 f"different { annotation } annotations" )
15861630
1587- for overridden in default_map [impl ]:
1588- if not overridden .overridable :
1589- raise EDMETH (impl .site , overridden .site , name )
1590- # the override of trait ASTs is checked later, by
1591- # traits.typecheck_method_override
1592- if not overridden .shared :
1593- # captured with ETMETH above
1594- assert not impl .shared
1595- typecheck_method_override (impl .method_ast ,
1596- overridden .method_ast ,
1597- location )
1598-
1599- # Check compatibility with all non-shared abstract declarations against
1600- # the highest-ranked implementation
1601- if default_level == 0 :
1602- for decl in abstract_decls :
1603- if decl .shared :
1604- # handled separately
1605- continue
1606-
1607- typecheck_method_override (impl .method_ast ,
1608- decl .method_ast ,
1609- location )
1610-
1611- if (not decl .throws and throws
1612- and impl .dml_version () != (1 , 4 )):
1613-
1614- body = wrap_method_body_in_try (
1615- impl .site , decl .site , obj , name , body , rbrace_site )
1616- throws = False
1617-
16181631 template = (impl .obj_spec .parent_template
16191632 if isinstance (impl .obj_spec , InstantiatedTemplateSpec )
16201633 else None )
1621- if isinstance (body , bool ):
1622- report (ICE (impl .site , f"wut: { repr (impl )} " ))
16231634 method = mkmethod (impl .site , rbrace_site ,
16241635 location ,
16251636 obj , name , inp_ast ,
0 commit comments