@@ -556,12 +556,18 @@ export class Compiler extends DiagnosticEmitter {
556
556
for ( let _keys = Map_keys ( this . pendingInstanceOf ) , i = 0 , k = _keys . length ; i < k ; ++ i ) {
557
557
let elem = _keys [ i ] ;
558
558
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 ) ;
565
571
}
566
572
}
567
573
@@ -6569,19 +6575,25 @@ export class Compiler extends DiagnosticEmitter {
6569
6575
}
6570
6576
let classInstance = assert ( overrideInstance . getBoundClassOrInterface ( ) ) ;
6571
6577
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
+ }
6577
6589
}
6578
6590
}
6579
6591
}
6580
6592
6581
6593
// Call the original function if no other id matches and the method is not
6582
6594
// abstract or part of an interface. Note that doing so will not catch an
6583
6595
// 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.
6585
6597
let body : ExpressionRef ;
6586
6598
let instanceClass = instance . getBoundClassOrInterface ( ) ;
6587
6599
if ( ! instance . is ( CommonFlags . Abstract ) && ! ( instanceClass && instanceClass . kind == ElementKind . Interface ) ) {
@@ -7432,7 +7444,7 @@ export class Compiler extends DiagnosticEmitter {
7432
7444
// <nullable> instanceof <nonNullable> - LHS must be != 0
7433
7445
if ( actualType . isNullableReference && ! expectedType . isNullableReference ) {
7434
7446
7435
- // upcast - check statically
7447
+ // same or upcast - check statically
7436
7448
if ( actualType . nonNullableType . isAssignableTo ( expectedType ) ) {
7437
7449
return module . binary (
7438
7450
sizeTypeRef == TypeRef . I64
@@ -7443,8 +7455,8 @@ export class Compiler extends DiagnosticEmitter {
7443
7455
) ;
7444
7456
}
7445
7457
7446
- // downcast - check dynamically
7447
- if ( expectedType . isAssignableTo ( actualType ) ) {
7458
+ // potential downcast - check dynamically
7459
+ if ( actualType . nonNullableType . hasSubtypeAssignableTo ( expectedType ) ) {
7448
7460
if ( ! ( actualType . isUnmanaged || expectedType . isUnmanaged ) ) {
7449
7461
if ( this . options . pedantic ) {
7450
7462
this . pedantic (
@@ -7477,12 +7489,13 @@ export class Compiler extends DiagnosticEmitter {
7477
7489
// either none or both nullable
7478
7490
} else {
7479
7491
7480
- // upcast - check statically
7492
+ // same or upcast - check statically
7481
7493
if ( actualType . isAssignableTo ( expectedType ) ) {
7482
7494
return module . maybeDropCondition ( expr , module . i32 ( 1 ) ) ;
7495
+ }
7483
7496
7484
- // downcast - check dynamically
7485
- } else if ( expectedType . isAssignableTo ( actualType ) ) {
7497
+ // potential downcast - check dynamically
7498
+ if ( actualType . hasSubtypeAssignableTo ( expectedType ) ) {
7486
7499
if ( ! ( actualType . isUnmanaged || expectedType . isUnmanaged ) ) {
7487
7500
let temp = flow . getTempLocal ( actualType ) ;
7488
7501
let tempIndex = temp . index ;
@@ -7558,19 +7571,32 @@ export class Compiler extends DiagnosticEmitter {
7558
7571
) , false // managedness is irrelevant here, isn't interrupted
7559
7572
)
7560
7573
) ;
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
+ )
7571
7597
)
7572
- )
7573
- ) ;
7598
+ ) ;
7599
+ }
7574
7600
}
7575
7601
stmts . push (
7576
7602
module . return (
@@ -7599,7 +7625,7 @@ export class Compiler extends DiagnosticEmitter {
7599
7625
if ( classReference ) {
7600
7626
7601
7627
// static check
7602
- if ( classReference . extends ( prototype ) ) {
7628
+ if ( classReference . extendsPrototype ( prototype ) ) {
7603
7629
7604
7630
// <nullable> instanceof <PROTOTYPE> - LHS must be != 0
7605
7631
if ( actualType . isNullableReference ) {
@@ -7688,8 +7714,24 @@ export class Compiler extends DiagnosticEmitter {
7688
7714
let allInstances = new Set < Class > ( ) ;
7689
7715
for ( let _values = Map_values ( instances ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
7690
7716
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
+ }
7693
7735
}
7694
7736
for ( let _values = Set_values ( allInstances ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
7695
7737
let instance = _values [ i ] ;
@@ -7946,7 +7988,7 @@ export class Compiler extends DiagnosticEmitter {
7946
7988
let parameterTypes = instance . signature . parameterTypes ;
7947
7989
if ( parameterTypes . length ) {
7948
7990
let first = parameterTypes [ 0 ] . getClass ( ) ;
7949
- if ( first && ! first . extends ( tsaArrayInstance . prototype ) ) {
7991
+ if ( first && ! first . extendsPrototype ( tsaArrayInstance . prototype ) ) {
7950
7992
arrayInstance = assert ( this . resolver . resolveClass ( this . program . arrayPrototype , [ stringType ] ) ) ;
7951
7993
}
7952
7994
}
@@ -8014,7 +8056,7 @@ export class Compiler extends DiagnosticEmitter {
8014
8056
8015
8057
// handle static arrays
8016
8058
let contextualClass = contextualType . getClass ( ) ;
8017
- if ( contextualClass && contextualClass . extends ( program . staticArrayPrototype ) ) {
8059
+ if ( contextualClass && contextualClass . extendsPrototype ( program . staticArrayPrototype ) ) {
8018
8060
return this . compileStaticArrayLiteral ( expression , contextualType , constraints ) ;
8019
8061
}
8020
8062
@@ -8147,7 +8189,7 @@ export class Compiler extends DiagnosticEmitter {
8147
8189
) : ExpressionRef {
8148
8190
let program = this . program ;
8149
8191
let module = this . module ;
8150
- assert ( ! arrayInstance . extends ( program . staticArrayPrototype ) ) ;
8192
+ assert ( ! arrayInstance . extendsPrototype ( program . staticArrayPrototype ) ) ;
8151
8193
let elementType = arrayInstance . getArrayValueType ( ) ; // asserts
8152
8194
8153
8195
// __newArray(length, alignLog2, classId, staticBuffer)
0 commit comments