in lib/src/util/dart_type_utilities.dart [478:542]
static bool unrelatedTypes(
TypeSystem typeSystem, DartType? leftType, DartType? rightType) {
// If we don't have enough information, or can't really compare the types,
// return false as they _might_ be related.
if (leftType == null ||
leftType.isBottom ||
leftType.isDynamic ||
rightType == null ||
rightType.isBottom ||
rightType.isDynamic) {
return false;
}
var promotedLeftType = typeSystem.promoteToNonNull(leftType);
var promotedRightType = typeSystem.promoteToNonNull(rightType);
if (promotedLeftType == promotedRightType ||
typeSystem.isSubtypeOf(promotedLeftType, promotedRightType) ||
typeSystem.isSubtypeOf(promotedRightType, promotedLeftType)) {
return false;
}
if (promotedLeftType is InterfaceType &&
promotedRightType is InterfaceType) {
// In this case, [leftElement] and [rightElement] each represent
// the same class, like `int`, or `Iterable<String>`.
var leftElement = promotedLeftType.element;
var rightElement = promotedRightType.element;
if (leftElement == rightElement) {
// In this case, [leftElement] and [rightElement] represent the same
// class, modulo generics, e.g. `List<int>` and `List<dynamic>`. Now we
// need to check type arguments.
var leftTypeArguments = promotedLeftType.typeArguments;
var rightTypeArguments = promotedRightType.typeArguments;
if (leftTypeArguments.length != rightTypeArguments.length) {
// I cannot think of how we would enter this block, but it guards
// against RangeError below.
return false;
}
for (var i = 0; i < leftTypeArguments.length; i++) {
// If any of the pair-wise type arguments are unrelated, then
// [leftType] and [rightType] are unrelated.
if (unrelatedTypes(
typeSystem, leftTypeArguments[i], rightTypeArguments[i])) {
return true;
}
}
// Otherwise, they might be related.
return false;
} else {
return (leftElement.supertype?.isDartCoreObject ?? false) ||
leftElement.supertype != rightElement.supertype;
}
} else if (promotedLeftType is TypeParameterType &&
promotedRightType is TypeParameterType) {
return unrelatedTypes(typeSystem, promotedLeftType.element.bound,
promotedRightType.element.bound);
} else if (promotedLeftType is FunctionType) {
if (_isFunctionTypeUnrelatedToType(promotedLeftType, promotedRightType)) {
return true;
}
} else if (promotedRightType is FunctionType) {
if (_isFunctionTypeUnrelatedToType(promotedRightType, promotedLeftType)) {
return true;
}
}
return false;
}