@@ -11,8 +11,6 @@ import '../analyzer.dart';
11
11
import '../ast.dart' ;
12
12
import '../extensions.dart' ;
13
13
14
- typedef AstNodePredicate = bool Function (AstNode node);
15
-
16
14
bool argumentsMatchParameters (
17
15
NodeList <Expression > arguments, NodeList <FormalParameter > parameters) {
18
16
var namedParameters = < String , Element ? > {};
@@ -145,7 +143,9 @@ bool canonicalElementsFromIdentifiersAreEqual(
145
143
/// * are related if their supertypes are equal, e.g. `List<dynamic>` and
146
144
/// `Set<dynamic>`.
147
145
/// * Two type variables are related if their bounds are related.
148
- /// * Otherwise, the types are related.
146
+ /// * A record type is unrelated to any other type except a record type of
147
+ /// the same shape.
148
+ /// * Otherwise, any two types are related.
149
149
// TODO(srawlins): typedefs and functions in general.
150
150
bool typesAreUnrelated (
151
151
TypeSystem typeSystem, DartType ? leftType, DartType ? rightType) {
@@ -167,35 +167,8 @@ bool typesAreUnrelated(
167
167
return false ;
168
168
}
169
169
if (promotedLeftType is InterfaceType && promotedRightType is InterfaceType ) {
170
- // In this case, [leftElement] and [rightElement] each represent
171
- // the same class, like `int`, or `Iterable<String>`.
172
- var leftElement = promotedLeftType.element;
173
- var rightElement = promotedRightType.element;
174
- if (leftElement == rightElement) {
175
- // In this case, [leftElement] and [rightElement] represent the same
176
- // class, modulo generics, e.g. `List<int>` and `List<dynamic>`. Now we
177
- // need to check type arguments.
178
- var leftTypeArguments = promotedLeftType.typeArguments;
179
- var rightTypeArguments = promotedRightType.typeArguments;
180
- if (leftTypeArguments.length != rightTypeArguments.length) {
181
- // I cannot think of how we would enter this block, but it guards
182
- // against RangeError below.
183
- return false ;
184
- }
185
- for (var i = 0 ; i < leftTypeArguments.length; i++ ) {
186
- // If any of the pair-wise type arguments are unrelated, then
187
- // [leftType] and [rightType] are unrelated.
188
- if (typesAreUnrelated (
189
- typeSystem, leftTypeArguments[i], rightTypeArguments[i])) {
190
- return true ;
191
- }
192
- }
193
- // Otherwise, they might be related.
194
- return false ;
195
- } else {
196
- return (leftElement.supertype? .isDartCoreObject ?? false ) ||
197
- leftElement.supertype != rightElement.supertype;
198
- }
170
+ return typeSystem.interfaceTypesAreUnrelated (
171
+ promotedLeftType, promotedRightType);
199
172
} else if (promotedLeftType is TypeParameterType &&
200
173
promotedRightType is TypeParameterType ) {
201
174
return typesAreUnrelated (typeSystem, promotedLeftType.element.bound,
@@ -208,6 +181,10 @@ bool typesAreUnrelated(
208
181
if (_isFunctionTypeUnrelatedToType (promotedRightType, promotedLeftType)) {
209
182
return true ;
210
183
}
184
+ } else if (promotedLeftType is RecordType ||
185
+ promotedRightType is RecordType ) {
186
+ return ! typeSystem.isAssignableTo (promotedLeftType, promotedRightType) &&
187
+ ! typeSystem.isAssignableTo (promotedRightType, promotedLeftType);
211
188
}
212
189
return false ;
213
190
}
@@ -226,6 +203,8 @@ bool _isFunctionTypeUnrelatedToType(FunctionType type1, DartType type2) {
226
203
return true ;
227
204
}
228
205
206
+ typedef AstNodePredicate = bool Function (AstNode node);
207
+
229
208
class DartTypeUtilities {
230
209
@Deprecated ('Replace with `type.extendsClass`' )
231
210
static bool extendsClass (
@@ -282,6 +261,39 @@ class InterfaceTypeDefinition {
282
261
}
283
262
}
284
263
264
+ extension on TypeSystem {
265
+ bool interfaceTypesAreUnrelated (
266
+ InterfaceType leftType, InterfaceType rightType) {
267
+ var leftElement = leftType.element;
268
+ var rightElement = rightType.element;
269
+ if (leftElement == rightElement) {
270
+ // In this case, [leftElement] and [rightElement] represent the same
271
+ // class, modulo generics, e.g. `List<int>` and `List<dynamic>`. Now we
272
+ // need to check type arguments.
273
+ var leftTypeArguments = leftType.typeArguments;
274
+ var rightTypeArguments = rightType.typeArguments;
275
+ if (leftTypeArguments.length != rightTypeArguments.length) {
276
+ // I cannot think of how we would enter this block, but it guards
277
+ // against RangeError below.
278
+ return false ;
279
+ }
280
+ for (var i = 0 ; i < leftTypeArguments.length; i++ ) {
281
+ // If any of the pair-wise type arguments are unrelated, then
282
+ // [leftType] and [rightType] are unrelated.
283
+ if (typesAreUnrelated (
284
+ this , leftTypeArguments[i], rightTypeArguments[i])) {
285
+ return true ;
286
+ }
287
+ }
288
+ // Otherwise, they might be related.
289
+ return false ;
290
+ } else {
291
+ return (leftElement.supertype? .isDartCoreObject ?? false ) ||
292
+ leftElement.supertype != rightElement.supertype;
293
+ }
294
+ }
295
+ }
296
+
285
297
extension DartTypeExtensions on DartType {
286
298
/// Returns the type which should be used when conducting "interface checks"
287
299
/// on `this` .
0 commit comments