@@ -11,6 +11,7 @@ import 'dart:core' hide Type;
1111
1212import 'package:_fe_analyzer_shared/src/type_inference/nullability_suffix.dart' ;
1313import 'package:_fe_analyzer_shared/src/types/shared_type.dart' ;
14+ import 'package:collection/collection.dart' ;
1415
1516/// Surrounds [s] with parentheses if [condition] is `true` , otherwise returns
1617/// [s] unchanged.
@@ -62,6 +63,14 @@ class FunctionType extends Type
6263 }
6364 }
6465
66+ @override
67+ int get hashCode => Object .hash (
68+ returnType,
69+ const ListEquality ().hash (positionalParameters),
70+ requiredPositionalParameterCount,
71+ const ListEquality ().hash (namedParameters),
72+ nullabilitySuffix);
73+
6574 @override
6675 List <Type > get positionalParameterTypes => positionalParameters;
6776
@@ -71,6 +80,17 @@ class FunctionType extends Type
7180 @override
7281 List <Never > get typeFormals => const [];
7382
83+ @override
84+ bool operator == (Object other) =>
85+ other is FunctionType &&
86+ returnType == other.returnType &&
87+ const ListEquality ()
88+ .equals (positionalParameters, other.positionalParameters) &&
89+ requiredPositionalParameterCount ==
90+ other.requiredPositionalParameterCount &&
91+ const ListEquality ().equals (namedParameters, other.namedParameters) &&
92+ nullabilitySuffix == other.nullabilitySuffix;
93+
7494 @override
7595 Type ? closureWithRespectToUnknown ({required bool covariant }) {
7696 Type ? newReturnType =
@@ -197,6 +217,16 @@ class NamedFunctionParameter
197217 NamedFunctionParameter (
198218 {required this .isRequired, required this .name, required this .type});
199219
220+ @override
221+ int get hashCode => Object .hash (name, type, isRequired);
222+
223+ @override
224+ bool operator == (Object other) =>
225+ other is NamedFunctionParameter &&
226+ name == other.name &&
227+ type == other.type &&
228+ isRequired == other.isRequired;
229+
200230 @override
201231 String toString () => [if (isRequired) 'required' , type, name].join (' ' );
202232}
@@ -209,6 +239,13 @@ class NamedType implements SharedNamedTypeStructure<Type> {
209239 final Type type;
210240
211241 NamedType ({required this .name, required this .type});
242+
243+ @override
244+ int get hashCode => Object .hash (name, type);
245+
246+ @override
247+ bool operator == (Object other) =>
248+ other is NamedType && name == other.name && type == other.type;
212249}
213250
214251/// Representation of the type `Never` suitable for unit testing of code in the
@@ -276,13 +313,24 @@ class PrimaryType extends Type {
276313 NullabilitySuffix nullabilitySuffix = NullabilitySuffix .none})
277314 : this ._(nameInfo, args: args, nullabilitySuffix: nullabilitySuffix);
278315
316+ @override
317+ int get hashCode => Object .hash (runtimeType, nameInfo,
318+ const ListEquality ().hash (args), nullabilitySuffix);
319+
279320 bool get isInterfaceType {
280321 return nameInfo is InterfaceTypeName ;
281322 }
282323
283324 /// The name of the type.
284325 String get name => nameInfo.name;
285326
327+ @override
328+ bool operator == (Object other) =>
329+ other is PrimaryType &&
330+ nameInfo == other.nameInfo &&
331+ const ListEquality ().equals (args, other.args) &&
332+ nullabilitySuffix == other.nullabilitySuffix;
333+
286334 @override
287335 Type ? closureWithRespectToUnknown ({required bool covariant }) {
288336 List <Type >? newArgs =
@@ -315,9 +363,6 @@ class RecordType extends Type implements SharedRecordTypeStructure<Type> {
315363
316364 final List <NamedType > namedTypes;
317365
318- @override
319- List <NamedType > get sortedNamedTypes => namedTypes;
320-
321366 RecordType ({
322367 required this .positionalTypes,
323368 required this .namedTypes,
@@ -329,6 +374,23 @@ class RecordType extends Type implements SharedRecordTypeStructure<Type> {
329374 }
330375 }
331376
377+ @override
378+ int get hashCode => Object .hash (
379+ runtimeType,
380+ const ListEquality ().hash (positionalTypes),
381+ const ListEquality ().hash (namedTypes),
382+ nullabilitySuffix);
383+
384+ @override
385+ List <NamedType > get sortedNamedTypes => namedTypes;
386+
387+ @override
388+ bool operator == (Object other) =>
389+ other is RecordType &&
390+ const ListEquality ().equals (positionalTypes, other.positionalTypes) &&
391+ const ListEquality ().equals (namedTypes, other.namedTypes) &&
392+ nullabilitySuffix == other.nullabilitySuffix;
393+
332394 @override
333395 Type ? closureWithRespectToUnknown ({required bool covariant }) {
334396 List <Type >? newPositional;
@@ -448,14 +510,8 @@ abstract class Type implements SharedTypeStructure<Type> {
448510
449511 const Type ._({this .nullabilitySuffix = NullabilitySuffix .none});
450512
451- @override
452- int get hashCode => type.hashCode;
453-
454513 String get type => toString ();
455514
456- @override
457- bool operator == (Object other) => other is Type && this .type == other.type;
458-
459515 /// Finds the nearest type that doesn't involve the unknown type (`_` ).
460516 ///
461517 /// If [covariant] is `true` , a supertype will be returned (replacing `_` with
@@ -551,6 +607,17 @@ class TypeParameter extends TypeNameInfo
551607 @override
552608 String get displayName => name;
553609
610+ @override
611+ int get hashCode {
612+ // To ensure that generic function types with different type formal names
613+ // have the same hash code, [FunctionType.hashCode] substitutes in a
614+ // consistently-named set of synthetic type formals in place of the type
615+ // formals. Since a fresh set of synthetic type formals will be created each
616+ // time [FunctionType.hashCode] is called, it's important that two type
617+ // formals with the same name (and bound) have the same hash code.
618+ return Object .hash (name, bound);
619+ }
620+
554621 @override
555622 String toString () => name;
556623}
@@ -575,6 +642,17 @@ class TypeParameterType extends Type {
575642 /// The type parameter's bound.
576643 Type get bound => typeParameter.bound;
577644
645+ @override
646+ int get hashCode =>
647+ Object .hash (runtimeType, typeParameter, promotion, nullabilitySuffix);
648+
649+ @override
650+ bool operator == (Object other) =>
651+ other is TypeParameterType &&
652+ typeParameter == other.typeParameter &&
653+ promotion == other.promotion &&
654+ nullabilitySuffix == other.nullabilitySuffix;
655+
578656 @override
579657 Type ? closureWithRespectToUnknown ({required bool covariant }) {
580658 var newPromotion =
@@ -1318,6 +1396,14 @@ class UnknownType extends Type implements SharedUnknownTypeStructure<Type> {
13181396 const UnknownType ({super .nullabilitySuffix = NullabilitySuffix .none})
13191397 : super ._();
13201398
1399+ @override
1400+ int get hashCode =>
1401+ Object .hash (runtimeType, nullabilitySuffix, nullabilitySuffix);
1402+
1403+ @override
1404+ bool operator == (Object other) =>
1405+ other is UnknownType && nullabilitySuffix == other.nullabilitySuffix;
1406+
13211407 @override
13221408 Type ? closureWithRespectToUnknown ({required bool covariant }) =>
13231409 covariant ? Type ('Object?' ) : NeverType .instance;
0 commit comments