@@ -334,7 +334,7 @@ class Rti {
334
334
}
335
335
336
336
static Rti allocate () {
337
- return new Rti ();
337
+ return Rti ();
338
338
}
339
339
340
340
Object ? _canonicalRecipe;
@@ -2974,86 +2974,94 @@ bool _isInterfaceSubtype(
2974
2974
String sName = Rti ._getInterfaceName (s);
2975
2975
String tName = Rti ._getInterfaceName (t);
2976
2976
2977
- // Interface Compositionality:
2978
- if (sName == tName) {
2979
- var sArgs = Rti ._getInterfaceTypeArguments (s);
2980
- var tArgs = Rti ._getInterfaceTypeArguments (t);
2981
- int length = _Utils .arrayLength (sArgs);
2982
- assert (length == _Utils .arrayLength (tArgs));
2983
-
2984
- var sVariances;
2985
- bool ? hasVariances;
2986
- if (JS_GET_FLAG ("VARIANCE" )) {
2987
- sVariances = _Universe .findTypeParameterVariances (universe, sName);
2988
- hasVariances = sVariances != null ;
2989
- assert (! hasVariances || length == _Utils .arrayLength (sVariances));
2990
- }
2991
-
2977
+ while (sName != tName) {
2978
+ // The Super-Interface rule says that if [s] has superinterfaces C0,...,Cn,
2979
+ // then we need to check if for some i, Ci <: [t]. However, this requires us
2980
+ // to iterate over the superinterfaces. Instead, we can perform case
2981
+ // analysis on [t]. By this point, [t] can only be Never, a type variable,
2982
+ // or an interface type. (Bindings do not participate in subtype checks and
2983
+ // all other cases have been eliminated.) If [t] is not an interface, then
2984
+ // [s] </: [t]. Therefore, the only remaining case is that [t] is an
2985
+ // interface, so rather than iterating over the Ci, we can instead look up
2986
+ // [t] in our ruleset.
2987
+ // TODO(fishythefish): Handle variance correctly.
2988
+
2989
+ var rule = _Universe ._findRule (universe, sName);
2990
+ if (rule == null ) return false ;
2991
+ if (_Utils .isString (rule)) {
2992
+ sName = _Utils .asString (rule);
2993
+ continue ;
2994
+ }
2995
+
2996
+ var recipes = TypeRule .lookupSupertype (rule, tName);
2997
+ if (recipes == null ) return false ;
2998
+ int length = _Utils .arrayLength (recipes);
2999
+ Object ? supertypeArgs = length > 0 ? JS ('' , 'new Array(#)' , length) : null ;
2992
3000
for (int i = 0 ; i < length; i++ ) {
2993
- Rti sArg = _Utils .asRti (_Utils .arrayAt (sArgs, i));
2994
- Rti tArg = _Utils .asRti (_Utils .arrayAt (tArgs, i));
2995
- if (JS_GET_FLAG ("VARIANCE" )) {
2996
- int sVariance = hasVariances != null
2997
- ? _Utils .asInt (_Utils .arrayAt (sVariances, i))
2998
- : Variance .legacyCovariant;
2999
- switch (sVariance) {
3000
- case Variance .legacyCovariant:
3001
- case Variance .covariant :
3002
- if (! _isSubtype (universe, sArg, sEnv, tArg, tEnv)) {
3003
- return false ;
3004
- }
3005
- break ;
3006
- case Variance .contravariant:
3007
- if (! _isSubtype (universe, tArg, tEnv, sArg, sEnv)) {
3008
- return false ;
3009
- }
3010
- break ;
3011
- case Variance .invariant:
3012
- if (! _isSubtype (universe, sArg, sEnv, tArg, tEnv) ||
3013
- ! _isSubtype (universe, tArg, tEnv, sArg, sEnv)) {
3014
- return false ;
3015
- }
3016
- break ;
3017
- default :
3018
- throw StateError (
3019
- "Unknown variance given for subtype check: $sVariance " );
3020
- }
3021
- } else {
3022
- if (! _isSubtype (universe, sArg, sEnv, tArg, tEnv)) {
3023
- return false ;
3024
- }
3025
- }
3001
+ String recipe = _Utils .asString (_Utils .arrayAt (recipes, i));
3002
+ Rti supertypeArg = _Universe .evalInEnvironment (universe, s, recipe);
3003
+ _Utils .arraySetAt (supertypeArgs, i, supertypeArg);
3026
3004
}
3027
- return true ;
3005
+ var tArgs = Rti ._getInterfaceTypeArguments (t);
3006
+ return _areArgumentsSubtypes (
3007
+ universe, supertypeArgs, null , sEnv, tArgs, tEnv);
3028
3008
}
3029
3009
3030
- // The Super-Interface rule says that if [s] has superinterfaces C0,...,Cn,
3031
- // then we need to check if for some i, Ci <: [t]. However, this requires us
3032
- // to iterate over the superinterfaces. Instead, we can perform case
3033
- // analysis on [t]. By this point, [t] can only be Never, a type variable,
3034
- // or an interface type. (Bindings do not participate in subtype checks and
3035
- // all other cases have been eliminated.) If [t] is not an interface, then
3036
- // [s] </: [t]. Therefore, the only remaining case is that [t] is an
3037
- // interface, so rather than iterating over the Ci, we can instead look up
3038
- // [t] in our ruleset.
3039
- // TODO(fishythefish): Handle variance correctly.
3040
-
3041
- // We don't list Object explicitly as a supertype of each interface, so check
3042
- // this trivial case first.
3043
- if (isObjectType (t)) return true ;
3044
- var rule = _Universe .findRule (universe, sName);
3045
- if (rule == null ) return false ;
3046
- var supertypeArgs = TypeRule .lookupSupertype (rule, tName);
3047
- if (supertypeArgs == null ) return false ;
3048
- int length = _Utils .arrayLength (supertypeArgs);
3010
+ // Interface Compositionality:
3011
+ assert (sName == tName);
3012
+ var sArgs = Rti ._getInterfaceTypeArguments (s);
3049
3013
var tArgs = Rti ._getInterfaceTypeArguments (t);
3014
+ var sVariances;
3015
+ if (JS_GET_FLAG ("VARIANCE" )) {
3016
+ sVariances = _Universe .findTypeParameterVariances (universe, sName);
3017
+ }
3018
+ return _areArgumentsSubtypes (universe, sArgs, sVariances, sEnv, tArgs, tEnv);
3019
+ }
3020
+
3021
+ bool _areArgumentsSubtypes (Object ? universe, Object ? sArgs, Object ? sVariances,
3022
+ Object ? sEnv, Object ? tArgs, Object ? tEnv) {
3023
+ int length = sArgs != null ? _Utils .arrayLength (sArgs) : 0 ;
3050
3024
assert (length == _Utils .arrayLength (tArgs));
3025
+ bool hasVariances = sVariances != null ;
3026
+ if (JS_GET_FLAG ("VARIANCE" )) {
3027
+ assert (! hasVariances || length == _Utils .arrayLength (sVariances));
3028
+ } else {
3029
+ assert (! hasVariances);
3030
+ }
3031
+
3051
3032
for (int i = 0 ; i < length; i++ ) {
3052
- String recipe = _Utils .asString (_Utils .arrayAt (supertypeArgs, i));
3053
- Rti supertypeArg = _Universe .evalInEnvironment (universe, s, recipe);
3033
+ Rti sArg = _Utils .asRti (_Utils .arrayAt (sArgs, i));
3054
3034
Rti tArg = _Utils .asRti (_Utils .arrayAt (tArgs, i));
3055
- if (! _isSubtype (universe, supertypeArg, sEnv, tArg, tEnv)) {
3056
- return false ;
3035
+ if (JS_GET_FLAG ("VARIANCE" )) {
3036
+ int sVariance = hasVariances
3037
+ ? _Utils .asInt (_Utils .arrayAt (sVariances, i))
3038
+ : Variance .legacyCovariant;
3039
+ switch (sVariance) {
3040
+ case Variance .legacyCovariant:
3041
+ case Variance .covariant :
3042
+ if (! _isSubtype (universe, sArg, sEnv, tArg, tEnv)) {
3043
+ return false ;
3044
+ }
3045
+ break ;
3046
+ case Variance .contravariant:
3047
+ if (! _isSubtype (universe, tArg, tEnv, sArg, sEnv)) {
3048
+ return false ;
3049
+ }
3050
+ break ;
3051
+ case Variance .invariant:
3052
+ if (! _isSubtype (universe, sArg, sEnv, tArg, tEnv) ||
3053
+ ! _isSubtype (universe, tArg, tEnv, sArg, sEnv)) {
3054
+ return false ;
3055
+ }
3056
+ break ;
3057
+ default :
3058
+ throw StateError (
3059
+ "Unknown variance given for subtype check: $sVariance " );
3060
+ }
3061
+ } else {
3062
+ if (! _isSubtype (universe, sArg, sEnv, tArg, tEnv)) {
3063
+ return false ;
3064
+ }
3057
3065
}
3058
3066
}
3059
3067
return true ;
0 commit comments