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+
912import 'package:_fe_analyzer_shared/src/type_inference/nullability_suffix.dart' ;
1013import '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.
165168class 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`
429437class 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> {
512520sealed 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