Skip to content

Commit 5c904c1

Browse files
stereotype441Commit Queue
authored andcommitted
[mini_types] Add an assertion to verify the runtime type of PrimaryType-derived objects.
The class hierarchy for `PrimaryType` has several subtypes to represent special types in Dart: - DynamicType (for `dynamic`) - FutureOrType (for `FutureOr<...>`) - InvalidType (for the invalid type) - NeverType (for `Never`) - NullType (for `Null`) - VoidType (for `Void`) When constructing a `PrimaryType` for one of these special types, we need to make sure that the type that's being ultimately constructed is the proper subtype, otherwise algorithms that do `is` tests on the `Type` hierarchy will behave incorrectly. This change adds an assertion to the `PrimaryType` constructor to verify that the appropriate subtype of `Type` is being constructed. Change-Id: I347cc4893da265b35e97636479700a92a8e61541 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/395560 Reviewed-by: Kallen Tu <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent 052c985 commit 5c904c1

File tree

1 file changed

+39
-11
lines changed

1 file changed

+39
-11
lines changed

pkg/_fe_analyzer_shared/test/mini_types.dart

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
// but light weight enough to be suitable for unit testing of code in the
77
// `_fe_analyzer_shared` package.
88

9+
import 'dart:core' as core show Type;
10+
import 'dart:core' hide Type;
11+
912
import 'package:_fe_analyzer_shared/src/type_inference/nullability_suffix.dart';
1013
import 'package:_fe_analyzer_shared/src/types/shared_type.dart';
1114

@@ -163,7 +166,7 @@ class FutureOrType extends PrimaryType {
163166

164167
/// A type name that represents an ordinary interface type.
165168
class InterfaceTypeName extends TypeNameInfo {
166-
InterfaceTypeName._(super.name);
169+
InterfaceTypeName._(super.name) : super(expectedRuntimeType: PrimaryType);
167170
}
168171

169172
/// Representation of an invalid type suitable for unit testing of code in the
@@ -261,7 +264,12 @@ class PrimaryType extends Type {
261264

262265
PrimaryType._(this.nameInfo,
263266
{this.args = const [], super.nullabilitySuffix = NullabilitySuffix.none})
264-
: super._();
267+
: super._() {
268+
assert(
269+
runtimeType == nameInfo._expectedRuntimeType,
270+
'${nameInfo.name} should use ${nameInfo._expectedRuntimeType}, but '
271+
'constructed $runtimeType instead');
272+
}
265273

266274
PrimaryType._special(SpecialTypeName nameInfo,
267275
{List<Type> args = const [],
@@ -427,7 +435,7 @@ class RecordType extends Type implements SharedRecordTypeStructure<Type> {
427435
/// - `Null`
428436
/// - `void`
429437
class SpecialTypeName extends TypeNameInfo {
430-
SpecialTypeName._(super.name);
438+
SpecialTypeName._(super.name, {required super.expectedRuntimeType});
431439
}
432440

433441
/// Representation of a type suitable for unit testing of code in the
@@ -512,7 +520,21 @@ abstract class Type implements SharedTypeStructure<Type> {
512520
sealed class TypeNameInfo {
513521
final String name;
514522

515-
TypeNameInfo(this.name);
523+
/// The runtime type that should be used for [Type] objects that refer to
524+
/// `this`.
525+
///
526+
/// An assertion in the [PrimaryType] constructor verifies this.
527+
///
528+
/// This ensures that the methods [Type.closureWithRespectToUnknown],
529+
/// [Type.recursivelyDemote], and [Type.withNullability] (which create new
530+
/// instances of [Type] based on old ones) create the appropriate subtype of
531+
/// [Type]. It also ensures that when [Type] objects are directly constructed
532+
/// (as they are in this file and in `mini_ast.dart`), the appropriate subtype
533+
/// of [Type] is used.
534+
final core.Type _expectedRuntimeType;
535+
536+
TypeNameInfo(this.name, {required core.Type expectedRuntimeType})
537+
: _expectedRuntimeType = expectedRuntimeType;
516538
}
517539

518540
/// A type name that represents a type variable.
@@ -522,7 +544,9 @@ class TypeParameter extends TypeNameInfo
522544
@override
523545
Type bound;
524546

525-
TypeParameter._(super.name) : bound = Type('Object?');
547+
TypeParameter._(super.name)
548+
: bound = Type('Object?'),
549+
super(expectedRuntimeType: TypeParameterType);
526550

527551
@override
528552
String get displayName => name;
@@ -607,16 +631,19 @@ abstract final class TypeRegistry {
607631
static Map<String, TypeNameInfo>? _typeNameInfoMap;
608632

609633
/// The [TypeNameInfo] object representing the special type `dynamic`.
610-
static final dynamic_ = SpecialTypeName._('dynamic');
634+
static final dynamic_ =
635+
SpecialTypeName._('dynamic', expectedRuntimeType: DynamicType);
611636

612637
/// The [TypeNameInfo] object representing the special type `error`.
613-
static final error_ = SpecialTypeName._('error');
638+
static final error_ =
639+
SpecialTypeName._('error', expectedRuntimeType: InvalidType);
614640

615641
/// The [TypeNameInfo] object representing the interface type `Future`.
616642
static final future = InterfaceTypeName._('Future');
617643

618644
/// The [TypeNameInfo] object representing the special type `FutureOr`.
619-
static final futureOr = SpecialTypeName._('FutureOr');
645+
static final futureOr =
646+
SpecialTypeName._('FutureOr', expectedRuntimeType: FutureOrType);
620647

621648
/// The [TypeNameInfo] object representing the interface type `Iterable`.
622649
static final iterable = InterfaceTypeName._('Iterable');
@@ -628,16 +655,17 @@ abstract final class TypeRegistry {
628655
static final map = InterfaceTypeName._('Map');
629656

630657
/// The [TypeNameInfo] object representing the special type `Never`.
631-
static final never = SpecialTypeName._('Never');
658+
static final never =
659+
SpecialTypeName._('Never', expectedRuntimeType: NeverType);
632660

633661
/// The [TypeNameInfo] object representing the special type `Null`.
634-
static final null_ = SpecialTypeName._('Null');
662+
static final null_ = SpecialTypeName._('Null', expectedRuntimeType: NullType);
635663

636664
/// The [TypeNameInfo] object representing the interface type `Stream`.
637665
static final stream = InterfaceTypeName._('Stream');
638666

639667
/// The [TypeNameInfo] object representing the special type `void`.
640-
static final void_ = SpecialTypeName._('void');
668+
static final void_ = SpecialTypeName._('void', expectedRuntimeType: VoidType);
641669

642670
/// Gets [_typeNameInfoMap], throwing an exception if it has not been
643671
/// initialized.

0 commit comments

Comments
 (0)