@@ -556,12 +556,18 @@ export class Compiler extends DiagnosticEmitter {
556556 for ( let _keys = Map_keys ( this . pendingInstanceOf ) , i = 0 , k = _keys . length ; i < k ; ++ i ) {
557557 let elem = _keys [ i ] ;
558558 let name = assert ( this . pendingInstanceOf . get ( elem ) ) ;
559- if ( elem . kind == ElementKind . Class ) {
560- this . finalizeInstanceOf ( < Class > elem , name ) ;
561- } else if ( elem . kind == ElementKind . ClassPrototype ) {
562- this . finalizeAnyInstanceOf ( < ClassPrototype > elem , name ) ;
563- } else {
564- assert ( false ) ;
559+ switch ( elem . kind ) {
560+ case ElementKind . Class :
561+ case ElementKind . Interface : {
562+ this . finalizeInstanceOf ( < Class > elem , name ) ;
563+ break ;
564+ }
565+ case ElementKind . ClassPrototype :
566+ case ElementKind . InterfacePrototype : {
567+ this . finalizeAnyInstanceOf ( < ClassPrototype > elem , name ) ;
568+ break ;
569+ }
570+ default : assert ( false ) ;
565571 }
566572 }
567573
@@ -6569,19 +6575,25 @@ export class Compiler extends DiagnosticEmitter {
65696575 }
65706576 let classInstance = assert ( overrideInstance . getBoundClassOrInterface ( ) ) ;
65716577 builder . addCase ( classInstance . id , stmts ) ;
6572- // Also alias each extendee inheriting this exact overload
6573- let extendees = classInstance . getAllExtendees ( instance . declaration . name . text ) ; // without get:/set:
6574- for ( let _values = Set_values ( extendees ) , a = 0 , b = _values . length ; a < b ; ++ a ) {
6575- let extendee = _values [ a ] ;
6576- builder . addCase ( extendee . id , stmts ) ;
6578+ // Also alias each extender inheriting this exact overload
6579+ let extenders = classInstance . extenders ;
6580+ if ( extenders ) {
6581+ for ( let _values = Set_values ( extenders ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
6582+ let extender = _values [ i ] ;
6583+ let instanceMembers = extender . prototype . instanceMembers ;
6584+ if ( instanceMembers && instanceMembers . has ( instance . declaration . name . text ) ) {
6585+ continue ; // skip those not inheriting
6586+ }
6587+ builder . addCase ( extender . id , stmts ) ;
6588+ }
65776589 }
65786590 }
65796591 }
65806592
65816593 // Call the original function if no other id matches and the method is not
65826594 // abstract or part of an interface. Note that doing so will not catch an
65836595 // invalid id, but can reduce code size significantly since we also don't
6584- // have to add branches for extendees inheriting the original function.
6596+ // have to add branches for extenders inheriting the original function.
65856597 let body : ExpressionRef ;
65866598 let instanceClass = instance . getBoundClassOrInterface ( ) ;
65876599 if ( ! instance . is ( CommonFlags . Abstract ) && ! ( instanceClass && instanceClass . kind == ElementKind . Interface ) ) {
@@ -7432,7 +7444,7 @@ export class Compiler extends DiagnosticEmitter {
74327444 // <nullable> instanceof <nonNullable> - LHS must be != 0
74337445 if ( actualType . isNullableReference && ! expectedType . isNullableReference ) {
74347446
7435- // upcast - check statically
7447+ // same or upcast - check statically
74367448 if ( actualType . nonNullableType . isAssignableTo ( expectedType ) ) {
74377449 return module . binary (
74387450 sizeTypeRef == TypeRef . I64
@@ -7443,8 +7455,8 @@ export class Compiler extends DiagnosticEmitter {
74437455 ) ;
74447456 }
74457457
7446- // downcast - check dynamically
7447- if ( expectedType . isAssignableTo ( actualType ) ) {
7458+ // potential downcast - check dynamically
7459+ if ( actualType . nonNullableType . hasSubtypeAssignableTo ( expectedType ) ) {
74487460 if ( ! ( actualType . isUnmanaged || expectedType . isUnmanaged ) ) {
74497461 if ( this . options . pedantic ) {
74507462 this . pedantic (
@@ -7477,12 +7489,13 @@ export class Compiler extends DiagnosticEmitter {
74777489 // either none or both nullable
74787490 } else {
74797491
7480- // upcast - check statically
7492+ // same or upcast - check statically
74817493 if ( actualType . isAssignableTo ( expectedType ) ) {
74827494 return module . maybeDropCondition ( expr , module . i32 ( 1 ) ) ;
7495+ }
74837496
7484- // downcast - check dynamically
7485- } else if ( expectedType . isAssignableTo ( actualType ) ) {
7497+ // potential downcast - check dynamically
7498+ if ( actualType . hasSubtypeAssignableTo ( expectedType ) ) {
74867499 if ( ! ( actualType . isUnmanaged || expectedType . isUnmanaged ) ) {
74877500 let temp = flow . getTempLocal ( actualType ) ;
74887501 let tempIndex = temp . index ;
@@ -7558,19 +7571,32 @@ export class Compiler extends DiagnosticEmitter {
75587571 ) , false // managedness is irrelevant here, isn't interrupted
75597572 )
75607573 ) ;
7561- let allInstances = new Set < Class > ( ) ;
7562- allInstances . add ( instance ) ;
7563- instance . getAllExtendeesAndImplementers ( allInstances ) ;
7564- for ( let _values = Set_values ( allInstances ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
7565- let instance = _values [ i ] ;
7566- stmts . push (
7567- module . br ( "is_instance" ,
7568- module . binary ( BinaryOp . EqI32 ,
7569- module . local_get ( 1 , TypeRef . I32 ) ,
7570- module . i32 ( instance . id )
7574+ let allInstances : Set < Class > | null ;
7575+ if ( instance . isInterface ) {
7576+ allInstances = instance . implementers ;
7577+ } else {
7578+ allInstances = new Set ( ) ;
7579+ allInstances . add ( instance ) ;
7580+ let extenders = instance . extenders ;
7581+ if ( extenders ) {
7582+ for ( let _values = Set_values ( extenders ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
7583+ let extender = _values [ i ] ;
7584+ allInstances . add ( extender ) ;
7585+ }
7586+ }
7587+ }
7588+ if ( allInstances ) {
7589+ for ( let _values = Set_values ( allInstances ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
7590+ let instance = _values [ i ] ;
7591+ stmts . push (
7592+ module . br ( "is_instance" ,
7593+ module . binary ( BinaryOp . EqI32 ,
7594+ module . local_get ( 1 , TypeRef . I32 ) ,
7595+ module . i32 ( instance . id )
7596+ )
75717597 )
7572- )
7573- ) ;
7598+ ) ;
7599+ }
75747600 }
75757601 stmts . push (
75767602 module . return (
@@ -7599,7 +7625,7 @@ export class Compiler extends DiagnosticEmitter {
75997625 if ( classReference ) {
76007626
76017627 // static check
7602- if ( classReference . extends ( prototype ) ) {
7628+ if ( classReference . extendsPrototype ( prototype ) ) {
76037629
76047630 // <nullable> instanceof <PROTOTYPE> - LHS must be != 0
76057631 if ( actualType . isNullableReference ) {
@@ -7688,8 +7714,24 @@ export class Compiler extends DiagnosticEmitter {
76887714 let allInstances = new Set < Class > ( ) ;
76897715 for ( let _values = Map_values ( instances ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
76907716 let instance = _values [ i ] ;
7691- allInstances . add ( instance ) ;
7692- instance . getAllExtendeesAndImplementers ( allInstances ) ;
7717+ if ( instance . isInterface ) {
7718+ let implementers = instance . implementers ;
7719+ if ( implementers ) {
7720+ for ( let _values = Set_values ( implementers ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
7721+ let implementer = _values [ i ] ;
7722+ allInstances . add ( implementer ) ;
7723+ }
7724+ }
7725+ } else {
7726+ allInstances . add ( instance ) ;
7727+ let extenders = instance . extenders ;
7728+ if ( extenders ) {
7729+ for ( let _values = Set_values ( extenders ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
7730+ let extender = _values [ i ] ;
7731+ allInstances . add ( extender ) ;
7732+ }
7733+ }
7734+ }
76937735 }
76947736 for ( let _values = Set_values ( allInstances ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
76957737 let instance = _values [ i ] ;
@@ -7946,7 +7988,7 @@ export class Compiler extends DiagnosticEmitter {
79467988 let parameterTypes = instance . signature . parameterTypes ;
79477989 if ( parameterTypes . length ) {
79487990 let first = parameterTypes [ 0 ] . getClass ( ) ;
7949- if ( first && ! first . extends ( tsaArrayInstance . prototype ) ) {
7991+ if ( first && ! first . extendsPrototype ( tsaArrayInstance . prototype ) ) {
79507992 arrayInstance = assert ( this . resolver . resolveClass ( this . program . arrayPrototype , [ stringType ] ) ) ;
79517993 }
79527994 }
@@ -8014,7 +8056,7 @@ export class Compiler extends DiagnosticEmitter {
80148056
80158057 // handle static arrays
80168058 let contextualClass = contextualType . getClass ( ) ;
8017- if ( contextualClass && contextualClass . extends ( program . staticArrayPrototype ) ) {
8059+ if ( contextualClass && contextualClass . extendsPrototype ( program . staticArrayPrototype ) ) {
80188060 return this . compileStaticArrayLiteral ( expression , contextualType , constraints ) ;
80198061 }
80208062
@@ -8147,7 +8189,7 @@ export class Compiler extends DiagnosticEmitter {
81478189 ) : ExpressionRef {
81488190 let program = this . program ;
81498191 let module = this . module ;
8150- assert ( ! arrayInstance . extends ( program . staticArrayPrototype ) ) ;
8192+ assert ( ! arrayInstance . extendsPrototype ( program . staticArrayPrototype ) ) ;
81518193 let elementType = arrayInstance . getArrayValueType ( ) ; // asserts
81528194
81538195 // __newArray(length, alignLog2, classId, staticBuffer)
0 commit comments