Skip to content

Commit 2f00ebd

Browse files
committed
Better is/as check handling. With this CL, the subtype function in
the DDC runtime returns null when a difference from the spec mode result is possible. Fixes dart-archive/dev_compiler#524 . BUG= [email protected], [email protected] Review URL: https://codereview.chromium.org/1945113003 .
1 parent be0d779 commit 2f00ebd

File tree

7 files changed

+363
-149
lines changed

7 files changed

+363
-149
lines changed

pkg/dev_compiler/lib/runtime/dart_sdk.js

Lines changed: 66 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ dart_library.library('dart_sdk', null, /* Imports */[
257257
derived.prototype.__proto__ = base.prototype;
258258
};
259259
dart.throwCastError = function(actual, type) {
260-
dart.throw(new _js_helper.CastErrorImplementation(actual, type));
260+
dart.throw(new _js_helper.CastErrorImplementation(dart.typeName(actual), dart.typeName(type)));
261261
};
262262
dart.throwAssertionError = function() {
263263
dart.throw(new core.AssertionError());
@@ -520,35 +520,36 @@ dart_library.library('dart_sdk', null, /* Imports */[
520520
return dart._callMethod(obj, 'set', null, [index, value], '[]=');
521521
};
522522
dart._ignoreTypeFailure = function(actual, type) {
523-
if (dart.isSubtype(type, core.Iterable) && dart.isSubtype(actual, core.Iterable) || dart.isSubtype(type, async.Future) && dart.isSubtype(actual, async.Future) || dart.isSubtype(type, core.Map) && dart.isSubtype(actual, core.Map) || dart.isSubtype(type, core.Function) && dart.isSubtype(actual, core.Function) || dart.isSubtype(type, async.Stream) && dart.isSubtype(actual, async.Stream) || dart.isSubtype(type, async.StreamSubscription) && dart.isSubtype(actual, async.StreamSubscription)) {
523+
if (!!dart.isSubtype(type, core.Iterable) && !!dart.isSubtype(actual, core.Iterable) || !!dart.isSubtype(type, async.Future) && !!dart.isSubtype(actual, async.Future) || !!dart.isSubtype(type, core.Map) && !!dart.isSubtype(actual, core.Map) || !!dart.isSubtype(type, core.Function) && !!dart.isSubtype(actual, core.Function) || !!dart.isSubtype(type, async.Stream) && !!dart.isSubtype(actual, async.Stream) || !!dart.isSubtype(type, async.StreamSubscription) && !!dart.isSubtype(actual, async.StreamSubscription)) {
524524
console.warn('Ignoring cast fail from ' + dart.typeName(actual) + ' to ' + dart.typeName(type));
525525
return true;
526526
}
527527
return false;
528528
};
529529
dart.strongInstanceOf = function(obj, type, ignoreFromWhiteList) {
530530
let actual = dart.getReifiedType(obj);
531-
if (dart.isSubtype(actual, type) || actual == dart.jsobject || actual == core.int && type == core.double) return true;
532-
if (ignoreFromWhiteList == void 0) return false;
533-
if (dart.isGroundType(type)) return false;
531+
let result = dart.isSubtype(actual, type);
532+
if (result || actual == dart.jsobject || actual == core.int && type == core.double) return true;
533+
if (ignoreFromWhiteList == void 0) return result;
534534
if (dart._ignoreTypeFailure(actual, type)) return true;
535-
return false;
535+
return result;
536536
};
537537
dart.instanceOfOrNull = function(obj, type) {
538538
if (obj == null || dart.strongInstanceOf(obj, type, true)) return true;
539539
return false;
540540
};
541541
dart.is = function(obj, type) {
542-
if (dart.strongInstanceOf(obj, type)) return true;
543-
if (dart.isGroundType(type)) return false;
542+
let result = dart.strongInstanceOf(obj, type);
543+
if (result !== null) return result;
544544
let actual = dart.getReifiedType(obj);
545545
dart.throwStrongModeError('Strong mode is check failure: ' + dart.typeName(actual) + ' does not soundly subtype ' + dart.typeName(type));
546546
};
547547
dart.as = function(obj, type) {
548-
if (dart.instanceOfOrNull(obj, type)) return obj;
548+
if (obj == null) return obj;
549+
let result = dart.strongInstanceOf(obj, type, true);
550+
if (result) return obj;
549551
let actual = dart.getReifiedType(obj);
550-
if (dart.isGroundType(type)) dart.throwCastError(actual, type);
551-
if (dart._ignoreTypeFailure(actual, type)) return obj;
552+
if (result === false) dart.throwCastError(actual, type);
552553
dart.throwStrongModeError('Strong mode cast failure from ' + dart.typeName(actual) + ' to ' + dart.typeName(type));
553554
};
554555
dart.asInt = function(obj) {
@@ -990,7 +991,12 @@ dart_library.library('dart_sdk', null, /* Imports */[
990991
return dart._getRuntimeType(type) === core.Type;
991992
};
992993
dart.typeName = function(type) {
993-
if (type instanceof dart.TypeRep) return type.toString();
994+
if (type instanceof dart.TypeRep) {
995+
if (type instanceof dart.Typedef) {
996+
return type.name + "(" + type.functionType.toString() + ")";
997+
}
998+
return type.toString();
999+
}
9941000
let tag = dart._getRuntimeType(type);
9951001
if (tag === core.Type) {
9961002
let name = type.name;
@@ -1019,41 +1025,36 @@ dart_library.library('dart_sdk', null, /* Imports */[
10191025
dart.isFunctionType = function(type) {
10201026
return type instanceof dart.AbstractFunctionType || type === core.Function;
10211027
};
1022-
dart.isFunctionSubType = function(ft1, ft2) {
1023-
if (ft2 == core.Function) {
1028+
dart.isFunctionSubtype = function(ft1, ft2, covariant) {
1029+
if (ft2 === core.Function) {
10241030
return true;
10251031
}
10261032
let ret1 = ft1.returnType;
10271033
let ret2 = ft2.returnType;
1028-
if (!dart.isSubtype_(ret1, ret2)) {
1029-
if (ret2 != dart.void) {
1030-
return false;
1031-
}
1032-
}
10331034
let args1 = ft1.args;
10341035
let args2 = ft2.args;
10351036
if (args1.length > args2.length) {
1036-
return false;
1037+
return covariant ? false : null;
10371038
}
10381039
for (let i = 0; i < args1.length; ++i) {
1039-
if (!dart.isSubtype_(args2[i], args1[i])) {
1040-
return false;
1040+
if (!dart.isSubtype_(args2[i], args1[i], !covariant)) {
1041+
return null;
10411042
}
10421043
}
10431044
let optionals1 = ft1.optionals;
10441045
let optionals2 = ft2.optionals;
10451046
if (args1.length + optionals1.length < args2.length + optionals2.length) {
1046-
return false;
1047+
return covariant ? false : null;
10471048
}
10481049
let j = 0;
10491050
for (let i = args1.length; i < args2.length; ++i, ++j) {
1050-
if (!dart.isSubtype_(args2[i], optionals1[j])) {
1051-
return false;
1051+
if (!dart.isSubtype_(args2[i], optionals1[j], !covariant)) {
1052+
return null;
10521053
}
10531054
}
10541055
for (let i = 0; i < optionals2.length; ++i, ++j) {
1055-
if (!dart.isSubtype_(optionals2[i], optionals1[j])) {
1056-
return false;
1056+
if (!dart.isSubtype_(optionals2[i], optionals1[j], !covariant)) {
1057+
return null;
10571058
}
10581059
}
10591060
let named1 = ft1.named;
@@ -1064,10 +1065,17 @@ dart_library.library('dart_sdk', null, /* Imports */[
10641065
let n1 = named1[name];
10651066
let n2 = named2[name];
10661067
if (n1 === void 0) {
1067-
return false;
1068+
return covariant ? false : null;
10681069
}
1069-
if (!dart.isSubtype_(n2, n1)) {
1070-
return false;
1070+
if (!dart.isSubtype_(n2, n1, !covariant)) {
1071+
return null;
1072+
}
1073+
}
1074+
let result = dart.isSubtype_(ret1, ret2, covariant);
1075+
if (result === null) return result;
1076+
if (!result) {
1077+
if (ret2 !== dart.void) {
1078+
return null;
10711079
}
10721080
}
10731081
return true;
@@ -1091,7 +1099,7 @@ dart_library.library('dart_sdk', null, /* Imports */[
10911099
} else {
10921100
dart.subtypeMap.set(t1, map = new Map());
10931101
}
1094-
result = dart.isSubtype_(t1, t2);
1102+
result = dart.isSubtype_(t1, t2, true);
10951103
map.set(t2, result);
10961104
return result;
10971105
};
@@ -1101,27 +1109,28 @@ dart_library.library('dart_sdk', null, /* Imports */[
11011109
dart._isTop = function(type) {
11021110
return type == core.Object || type == dart.dynamic;
11031111
};
1104-
dart.isSubtype_ = function(t1, t2) {
1112+
dart.isSubtype_ = function(t1, t2, covariant) {
11051113
t1 = dart.canonicalType(t1);
11061114
t2 = dart.canonicalType(t2);
1107-
if (t1 == t2) return true;
1115+
if (t1 === t2) return true;
11081116
if (dart._isTop(t2) || dart._isBottom(t1)) {
11091117
return true;
11101118
}
1111-
if (dart._isTop(t1) || dart._isBottom(t2)) {
1119+
if (dart._isBottom(t2)) return null;
1120+
if (dart._isTop(t1)) {
1121+
if (t1 === dart.dynamic) return null;
11121122
return false;
11131123
}
1114-
if (dart.isClassSubType(t1, t2)) {
1115-
return true;
1116-
}
1124+
let result = dart.isClassSubType(t1, t2, covariant);
1125+
if (result === true || result === null) return result;
11171126
t1 = dart.getImplicitFunctionType(t1);
11181127
if (!t1) return false;
11191128
if (dart.isFunctionType(t1) && dart.isFunctionType(t2)) {
1120-
return dart.isFunctionSubType(t1, t2);
1129+
return dart.isFunctionSubtype(t1, t2, covariant);
11211130
}
11221131
return false;
11231132
};
1124-
dart.isClassSubType = function(t1, t2) {
1133+
dart.isClassSubType = function(t1, t2, covariant) {
11251134
t1 = dart.canonicalType(t1);
11261135
dart.assert(t2 == dart.canonicalType(t2));
11271136
if (t1 == t2) return true;
@@ -1136,29 +1145,41 @@ dart_library.library('dart_sdk', null, /* Imports */[
11361145
if (typeArguments2.length == 0) {
11371146
return true;
11381147
} else if (length == 0) {
1139-
return false;
1148+
if (typeArguments2.every(dart._isTop)) return true;
1149+
return null;
11401150
}
11411151
dart.assert(length == typeArguments2.length);
11421152
for (let i = 0; i < length; ++i) {
1143-
if (!dart.isSubtype(typeArguments1[i], typeArguments2[i])) {
1144-
return false;
1153+
let result = dart.isSubtype_(typeArguments1[i], typeArguments2[i], covariant);
1154+
if (!result) {
1155+
return result;
11451156
}
11461157
}
11471158
return true;
11481159
}
1149-
if (dart.isClassSubType(t1.__proto__, t2)) return true;
1160+
let indefinite = false;
1161+
function definitive(t1, t2) {
1162+
let result = dart.isClassSubType(t1, t2, covariant);
1163+
if (result == null) {
1164+
indefinite = true;
1165+
return false;
1166+
}
1167+
return result;
1168+
}
1169+
if (definitive(t1.__proto__, t2)) return true;
11501170
let mixins = dart.getMixins(t1);
11511171
if (mixins) {
11521172
for (let m1 of mixins) {
1153-
if (m1 != null && dart.isClassSubType(m1, t2)) return true;
1173+
if (m1 != null && definitive(m1, t2)) return true;
11541174
}
11551175
}
11561176
let getInterfaces = dart.getImplements(t1);
11571177
if (getInterfaces) {
11581178
for (let i1 of getInterfaces()) {
1159-
if (i1 != null && dart.isClassSubType(i1, t2)) return true;
1179+
if (i1 != null && definitive(i1, t2)) return true;
11601180
}
11611181
}
1182+
if (indefinite) return null;
11621183
return false;
11631184
};
11641185
dart.isGroundType = function(type) {

pkg/dev_compiler/test/browser/language_tests.js

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -425,30 +425,21 @@
425425
'iterable_return_type_test_02_multi': fail,
426426
'iterable_return_type_test_none_multi': fail,
427427
'json_map_test': fail,
428-
'linked_hash_map_from_iterables_test': fail,
429428
'list_fill_range_test': fail,
430-
'list_filled_type_argument_test': fail,
431429
'list_get_range_test': fail,
432430
'list_replace_range_test': fail,
433431
'list_set_all_test': fail,
434432
'list_to_string2_test': fail,
435433
'list_to_string_test': fail,
436434
'main_test': fail,
437-
'map_from_iterable_test': fail,
438-
'map_from_iterables_test': fail,
439435
'map_keys2_test': fail,
440436
'map_to_string_test': fail,
441-
'map_values2_test': fail,
442-
'map_values3_test': fail,
443-
'map_values4_test': fail,
444437
'nan_infinity_test_01_multi': fail,
445438
'null_nosuchmethod_test': fail,
446439
'null_test': fail,
447440
'num_sign_test': fail,
448441
'queue_test': fail,
449442
'regress_r21715_test': fail,
450-
'splay_tree_from_iterable_test': fail,
451-
'splay_tree_from_iterables_test': fail,
452443
'throw_half_surrogate_pair_test_02_multi': fail,
453444
'stacktrace_current_test': fail,
454445
'stacktrace_fromstring_test': fail,

0 commit comments

Comments
 (0)