Skip to content

Commit aaed0ce

Browse files
rakudramaCommit Queue
authored andcommitted
[dart2js] Add subtyping of record types against Record interface
- Fix bug with nullable record type, e.g. `(int,int)?`. Change-Id: Ie8006e8ec3a9ffd675519df2ab7b4d101d8d5dcd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/262843 Reviewed-by: Mayank Patke <fishythefish@google.com> Commit-Queue: Stephen Adams <sra@google.com>
1 parent ca709d0 commit aaed0ce

File tree

4 files changed

+20
-9
lines changed

4 files changed

+20
-9
lines changed

pkg/compiler/lib/src/common/elements.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ abstract class CommonElements {
5050
/// The `Function` class defined in 'dart:core'.
5151
late final ClassEntity functionClass = _findClass(coreLibrary, 'Function');
5252

53+
/// The `Record` class defined in 'dart:core'.
54+
late final ClassEntity recordClass = _findClass(coreLibrary, 'Record');
55+
5356
/// The `Resource` class defined in 'dart:core'.
5457
late final ClassEntity resourceClass = _findClass(coreLibrary, 'Resource');
5558

@@ -239,6 +242,9 @@ abstract class CommonElements {
239242
/// The `Null` type defined in 'dart:core'.
240243
InterfaceType get nullType => _getRawType(nullClass);
241244

245+
/// The `Record` type defined in 'dart:core'.
246+
InterfaceType get recordType => _getRawType(recordClass);
247+
242248
/// The `Type` type defined in 'dart:core'.
243249
InterfaceType get typeType => _getRawType(typeClass);
244250

pkg/compiler/lib/src/elements/types.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2308,10 +2308,12 @@ abstract class DartTypes {
23082308
//
23092309
// TODO(50081): Reference rules to updated specification
23102310
// https://github.com/dart-lang/language/blob/master/resources/type-system/subtyping.md#rules
2311-
//
2312-
// TODO(50081): record is subtype of interface `Record`.
2313-
if (s is RecordType) {
2314-
if (t is! RecordType) return false;
2311+
2312+
// Record Type/Record:
2313+
if (s is RecordType && t == commonElements.recordType) return true;
2314+
2315+
// Record Type/Record Type:
2316+
if (s is RecordType && t is RecordType) {
23152317
if (s.shape != t.shape) return false;
23162318
List<DartType> sFields = s.fields;
23172319
List<DartType> tFields = t.fields;

pkg/compiler/lib/src/ir/visitors.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
179179
for (final type in positional) visitType(type),
180180
for (final namedType in named) visitType(namedType.type)
181181
].toList(growable: false);
182-
return _dartTypes.recordType(shape, fields);
182+
return _convertNullability(_dartTypes.recordType(shape, fields), node);
183183
}
184184

185185
@override

sdk/lib/_internal/js_shared/lib/rti.dart

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3003,10 +3003,12 @@ bool _isSubtype(Object? universe, Rti s, Object? sEnv, Rti t, Object? tEnv) {
30033003
//
30043004
// TODO(50081): Reference rules to updated specification
30053005
// https://github.com/dart-lang/language/blob/master/resources/type-system/subtyping.md#rules
3006-
//
3007-
// TODO(50081): record is subtype of interface `Record`.
3008-
if (sKind == Rti.kindRecord) {
3009-
if (tKind != Rti.kindRecord) return false;
3006+
3007+
// Record Type/Record:
3008+
if (sKind == Rti.kindRecord && isRecordInterfaceType(t)) return true;
3009+
3010+
// Record Type/Record Type:
3011+
if (sKind == Rti.kindRecord && tKind == Rti.kindRecord) {
30103012
return _isRecordSubtype(universe, s, sEnv, t, tEnv);
30113013
}
30123014

@@ -3267,6 +3269,7 @@ bool isNullType(Rti t) =>
32673269
bool isFunctionType(Rti t) => _Utils.isIdentical(t, TYPE_REF<Function>());
32683270
bool isJsFunctionType(Rti t) =>
32693271
_Utils.isIdentical(t, TYPE_REF<JavaScriptFunction>());
3272+
bool isRecordInterfaceType(Rti t) => _Utils.isIdentical(t, TYPE_REF<Record>());
32703273

32713274
class _Utils {
32723275
static bool asBool(Object? o) => JS('bool', '#', o);

0 commit comments

Comments
 (0)