blob: bf190153a7cfcdf13e8382d8405b2bb385cc6c77 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library fasta.types;
import 'package:kernel/ast.dart'
show
BottomType,
Class,
DartType,
DynamicType,
FunctionType,
InterfaceType,
InvalidType,
NamedType,
Nullability,
TypeParameter,
TypeParameterType,
TypedefType,
VoidType;
import 'package:kernel/type_algebra.dart' show Substitution;
import 'package:kernel/type_environment.dart';
import 'kernel_builder.dart' show ClassHierarchyBuilder;
class Types {
final ClassHierarchyBuilder hierarchy;
Types(this.hierarchy);
/// Returns true if [s] is a subtype of [t].
bool isSubtypeOfKernel(DartType s, DartType t, SubtypeCheckMode mode) {
if (s is InvalidType) {
// InvalidType is a bottom type.
return true;
}
if (t is InvalidType) {
return false;
}
return isSubtypeOfKernelNullability(s, s.nullability, t, t.nullability);
}
bool isSubtypeOfKernelNullability(
DartType s, Nullability sNullability, DartType t, tNullability) {
if (s is BottomType) {
return true; // Rule 3.
}
if (t is DynamicType) {
return true; // Rule 2.
}
if (t is VoidType) {
return true; // Rule 2.
}
if (t is BottomType) {
return false;
}
if (t is InterfaceType) {
Class cls = t.classNode;
if (cls == hierarchy.objectClass) {
return true; // Rule 2.
}
if (cls == hierarchy.futureOrClass) {
const IsFutureOrSubtypeOf relation = const IsFutureOrSubtypeOf();
if (s is DynamicType) {
return relation.isDynamicRelated(
s, sNullability, t, tNullability, this);
} else if (s is VoidType) {
return relation.isVoidRelated(s, sNullability, t, tNullability, this);
} else if (s is InterfaceType) {
return s.classNode == hierarchy.futureOrClass
? relation.isFutureOrRelated(
s, sNullability, t, tNullability, this)
: relation.isInterfaceRelated(
s, sNullability, t, tNullability, this);
} else if (s is FunctionType) {
return relation.isFunctionRelated(
s, sNullability, t, tNullability, this);
} else if (s is TypeParameterType) {
return s.promotedBound == null
? relation.isTypeParameterRelated(
s, sNullability, t, tNullability, this)
: relation.isIntersectionRelated(
s, sNullability, t, tNullability, this);
} else if (s is TypedefType) {
return relation.isTypedefRelated(
s, sNullability, t, tNullability, this);
}
} else {
const IsInterfaceSubtypeOf relation = const IsInterfaceSubtypeOf();
if (s is DynamicType) {
return relation.isDynamicRelated(
s, sNullability, t, tNullability, this);
} else if (s is VoidType) {
return relation.isVoidRelated(s, sNullability, t, tNullability, this);
} else if (s is InterfaceType) {
return s.classNode == hierarchy.futureOrClass
? relation.isFutureOrRelated(
s, sNullability, t, tNullability, this)
: relation.isInterfaceRelated(
s, sNullability, t, tNullability, this);
} else if (s is FunctionType) {
return relation.isFunctionRelated(
s, sNullability, t, tNullability, this);
} else if (s is TypeParameterType) {
return s.promotedBound == null
? relation.isTypeParameterRelated(
s, sNullability, t, tNullability, this)
: relation.isIntersectionRelated(
s, sNullability, t, tNullability, this);
} else if (s is TypedefType) {
return relation.isTypedefRelated(
s, sNullability, t, tNullability, this);
}
}
} else if (t is FunctionType) {
const IsFunctionSubtypeOf relation = const IsFunctionSubtypeOf();
if (s is DynamicType) {
return relation.isDynamicRelated(
s, sNullability, t, tNullability, this);
} else if (s is VoidType) {
return relation.isVoidRelated(s, sNullability, t, tNullability, this);
} else if (s is InterfaceType) {
return s.classNode == hierarchy.futureOrClass
? relation.isFutureOrRelated(s, sNullability, t, tNullability, this)
: relation.isInterfaceRelated(
s, sNullability, t, tNullability, this);
} else if (s is FunctionType) {
return relation.isFunctionRelated(
s, sNullability, t, tNullability, this);
} else if (s is TypeParameterType) {
return s.promotedBound == null
? relation.isTypeParameterRelated(
s, sNullability, t, tNullability, this)
: relation.isIntersectionRelated(
s, sNullability, t, tNullability, this);
} else if (s is TypedefType) {
return relation.isTypedefRelated(
s, sNullability, t, tNullability, this);
}
} else if (t is TypeParameterType) {
if (t.promotedBound == null) {
const IsTypeParameterSubtypeOf relation =
const IsTypeParameterSubtypeOf();
if (s is DynamicType) {
return relation.isDynamicRelated(
s, sNullability, t, tNullability, this);
} else if (s is VoidType) {
return relation.isVoidRelated(s, sNullability, t, tNullability, this);
} else if (s is InterfaceType) {
return s.classNode == hierarchy.futureOrClass
? relation.isFutureOrRelated(
s, sNullability, t, tNullability, this)
: relation.isInterfaceRelated(
s, sNullability, t, tNullability, this);
} else if (s is FunctionType) {
return relation.isFunctionRelated(
s, sNullability, t, tNullability, this);
} else if (s is TypeParameterType) {
return s.promotedBound == null
? relation.isTypeParameterRelated(
s, sNullability, t, tNullability, this)
: relation.isIntersectionRelated(
s, sNullability, t, tNullability, this);
} else if (s is TypedefType) {
return relation.isTypedefRelated(
s, sNullability, t, tNullability, this);
}
} else {
const IsIntersectionSubtypeOf relation =
const IsIntersectionSubtypeOf();
if (s is DynamicType) {
return relation.isDynamicRelated(
s, sNullability, t, tNullability, this);
} else if (s is VoidType) {
return relation.isVoidRelated(s, sNullability, t, tNullability, this);
} else if (s is InterfaceType) {
return s.classNode == hierarchy.futureOrClass
? relation.isFutureOrRelated(
s, sNullability, t, tNullability, this)
: relation.isInterfaceRelated(
s, sNullability, t, tNullability, this);
} else if (s is FunctionType) {
return relation.isFunctionRelated(
s, sNullability, t, tNullability, this);
} else if (s is TypeParameterType) {
return s.promotedBound == null
? relation.isTypeParameterRelated(
s, sNullability, t, tNullability, this)
: relation.isIntersectionRelated(
s, sNullability, t, tNullability, this);
} else if (s is TypedefType) {
return relation.isTypedefRelated(
s, sNullability, t, tNullability, this);
}
}
} else if (t is TypedefType) {
const IsTypedefSubtypeOf relation = const IsTypedefSubtypeOf();
if (s is DynamicType) {
return relation.isDynamicRelated(
s, sNullability, t, tNullability, this);
} else if (s is VoidType) {
return relation.isVoidRelated(s, sNullability, t, tNullability, this);
} else if (s is InterfaceType) {
return s.classNode == hierarchy.futureOrClass
? relation.isFutureOrRelated(s, sNullability, t, tNullability, this)
: relation.isInterfaceRelated(
s, sNullability, t, tNullability, this);
} else if (s is FunctionType) {
return relation.isFunctionRelated(
s, sNullability, t, tNullability, this);
} else if (s is TypeParameterType) {
return s.promotedBound == null
? relation.isTypeParameterRelated(
s, sNullability, t, tNullability, this)
: relation.isIntersectionRelated(
s, sNullability, t, tNullability, this);
} else if (s is TypedefType) {
return relation.isTypedefRelated(
s, sNullability, t, tNullability, this);
}
} else {
throw "Unhandled type: ${t.runtimeType}";
}
throw "Unhandled type combination: ${t.runtimeType} ${s.runtimeType}";
}
/// Returns true if all types in [s] and [t] pairwise are subtypes.
bool areSubtypesOfKernel(List<DartType> s, List<DartType> t) {
if (s.length != t.length) {
throw "Numbers of type arguments don't match $s $t.";
}
for (int i = 0; i < s.length; i++) {
if (!isSubtypeOfKernel(
s[i], t[i], SubtypeCheckMode.ignoringNullabilities)) return false;
}
return true;
}
bool isSameTypeKernel(DartType s, DartType t) {
return isSubtypeOfKernel(s, t, SubtypeCheckMode.ignoringNullabilities) &&
isSubtypeOfKernel(t, s, SubtypeCheckMode.ignoringNullabilities);
}
}
abstract class TypeRelation<T extends DartType> {
const TypeRelation();
bool isDynamicRelated(DynamicType s, Nullability sNullability, T t,
Nullability tNullability, Types types);
bool isVoidRelated(VoidType s, Nullability sNullability, T t,
Nullability tNullability, Types types);
bool isInterfaceRelated(InterfaceType s, Nullability sNullability, T t,
Nullability tNullability, Types types);
bool isIntersectionRelated(
TypeParameterType intersection,
Nullability intersectionNullability,
T t,
Nullability tNullability,
Types types);
bool isFunctionRelated(FunctionType s, Nullability sNullability, T t,
Nullability tNullability, Types types);
bool isFutureOrRelated(
InterfaceType futureOr,
Nullability futureOrNullability,
T t,
Nullability tNullability,
Types types);
bool isTypeParameterRelated(TypeParameterType s, Nullability sNullability,
T t, Nullability tNullability, Types types);
bool isTypedefRelated(TypedefType s, Nullability sNullability, T t,
Nullability tNullability, Types types);
}
class IsInterfaceSubtypeOf extends TypeRelation<InterfaceType> {
const IsInterfaceSubtypeOf();
@override
bool isInterfaceRelated(InterfaceType s, Nullability sNullability,
InterfaceType t, Nullability tNullability, Types types) {
if (s.classNode == types.hierarchy.nullClass) {
// This is an optimization, to avoid instantiating unnecessary type
// arguments in getKernelTypeAsInstanceOf.
return true;
}
InterfaceType asSupertype =
types.hierarchy.getKernelTypeAsInstanceOf(s, t.classNode);
if (asSupertype == null) {
return false;
} else {
return types.areSubtypesOfKernel(
asSupertype.typeArguments, t.typeArguments);
}
}
@override
bool isTypeParameterRelated(TypeParameterType s, Nullability sNullability,
InterfaceType t, Nullability tNullability, Types types) {
return types.isSubtypeOfKernel(
s.parameter.bound, t, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isFutureOrRelated(
InterfaceType futureOr,
Nullability futureOrNullability,
InterfaceType t,
Nullability tNullability,
Types types) {
List<DartType> arguments = futureOr.typeArguments;
if (!types.isSubtypeOfKernel(
arguments.single, t, SubtypeCheckMode.ignoringNullabilities)) {
return false; // Rule 7.1
}
if (!types.isSubtypeOfKernel(
new InterfaceType(types.hierarchy.futureClass, arguments),
t,
SubtypeCheckMode.ignoringNullabilities)) {
return false; // Rule 7.2
}
return true;
}
@override
bool isIntersectionRelated(
TypeParameterType intersection,
Nullability intersectionNullability,
InterfaceType t,
Nullability tNullability,
Types types) {
return types.isSubtypeOfKernel(intersection.promotedBound, t,
SubtypeCheckMode.ignoringNullabilities); // Rule 12.
}
@override
bool isDynamicRelated(DynamicType s, Nullability sNullability,
InterfaceType t, Nullability tNullability, Types types) {
return false;
}
@override
bool isFunctionRelated(FunctionType s, Nullability sNullability,
InterfaceType t, Nullability tNullability, Types types) {
return t.classNode == types.hierarchy.functionClass; // Rule 14.
}
@override
bool isTypedefRelated(TypedefType s, Nullability sNullability,
InterfaceType t, Nullability tNullability, Types types) {
// Rule 5.
return types.isSubtypeOfKernel(
s.unalias, t, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isVoidRelated(VoidType s, Nullability sNullability, InterfaceType t,
Nullability tNullability, Types types) {
return false;
}
}
class IsFunctionSubtypeOf extends TypeRelation<FunctionType> {
const IsFunctionSubtypeOf();
@override
bool isFunctionRelated(FunctionType s, Nullability sNullability,
FunctionType t, Nullability tNullability, Types types) {
List<TypeParameter> sTypeVariables = s.typeParameters;
List<TypeParameter> tTypeVariables = t.typeParameters;
if (sTypeVariables.length != tTypeVariables.length) return false;
if (sTypeVariables.isNotEmpty) {
// If the function types have type variables, we alpha-rename the type
// variables of [s] to use those of [t].
List<DartType> typeVariableSubstitution = <DartType>[];
bool secondBoundsCheckNeeded = false;
for (int i = 0; i < sTypeVariables.length; i++) {
TypeParameter sTypeVariable = sTypeVariables[i];
TypeParameter tTypeVariable = tTypeVariables[i];
if (!types.isSameTypeKernel(sTypeVariable.bound, tTypeVariable.bound)) {
// If the bounds aren't the same, we need to try again after
// computing the substitution of type variables.
secondBoundsCheckNeeded = true;
}
typeVariableSubstitution.add(new TypeParameterType(tTypeVariable));
}
Substitution substitution =
Substitution.fromPairs(sTypeVariables, typeVariableSubstitution);
if (secondBoundsCheckNeeded) {
for (int i = 0; i < sTypeVariables.length; i++) {
TypeParameter sTypeVariable = sTypeVariables[i];
TypeParameter tTypeVariable = tTypeVariables[i];
if (!types.isSameTypeKernel(
substitution.substituteType(sTypeVariable.bound),
tTypeVariable.bound)) {
return false;
}
}
}
s = substitution.substituteType(s.withoutTypeParameters);
}
if (!types.isSubtypeOfKernel(
s.returnType, t.returnType, SubtypeCheckMode.ignoringNullabilities)) {
return false;
}
List<DartType> sPositional = s.positionalParameters;
List<DartType> tPositional = t.positionalParameters;
if (s.requiredParameterCount > t.requiredParameterCount) {
// Rule 15, n1 <= n2.
return false;
}
if (sPositional.length < tPositional.length) {
// Rule 15, n1 + k1 >= n2 + k2.
return false;
}
for (int i = 0; i < tPositional.length; i++) {
if (!types.isSubtypeOfKernel(tPositional[i], sPositional[i],
SubtypeCheckMode.ignoringNullabilities)) {
// Rule 15, Tj <: Sj.
return false;
}
}
List<NamedType> sNamed = s.namedParameters;
List<NamedType> tNamed = t.namedParameters;
if (sNamed.isNotEmpty || tNamed.isNotEmpty) {
// Rule 16, the number of positional parameters must be the same.
if (sPositional.length != tPositional.length) return false;
if (s.requiredParameterCount != t.requiredParameterCount) return false;
// Rule 16, the parameter names of [t] must be a subset of those of
// [s]. Also, for the intersection, the type of the parameter of [t] must
// be a subtype of the type of the parameter of [s].
int sCount = 0;
for (int tCount = 0; tCount < tNamed.length; tCount++) {
String name = tNamed[tCount].name;
for (; sCount < sNamed.length; sCount++) {
if (sNamed[sCount].name == name) break;
}
if (sCount == sNamed.length) return false;
if (!types.isSubtypeOfKernel(tNamed[tCount].type, sNamed[sCount].type,
SubtypeCheckMode.ignoringNullabilities)) {
return false;
}
}
}
return true;
}
@override
bool isInterfaceRelated(InterfaceType s, Nullability sNullability,
FunctionType t, Nullability tNullability, Types types) {
return s.classNode == types.hierarchy.nullClass; // Rule 4.
}
@override
bool isDynamicRelated(DynamicType s, Nullability sNullability, FunctionType t,
Nullability tNullability, Types types) {
return false;
}
@override
bool isFutureOrRelated(
InterfaceType futureOr,
Nullability futureOrNullability,
FunctionType t,
Nullability tNullability,
Types types) {
return false;
}
@override
bool isIntersectionRelated(
TypeParameterType intersection,
Nullability intersectionNullability,
FunctionType t,
Nullability tNullability,
Types types) {
// Rule 12.
return types.isSubtypeOfKernel(
intersection.promotedBound, t, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isTypeParameterRelated(TypeParameterType s, Nullability sNullability,
FunctionType t, Nullability tNullability, Types types) {
// Rule 13.
return types.isSubtypeOfKernel(
s.parameter.bound, t, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isTypedefRelated(TypedefType s, Nullability sNullability, FunctionType t,
Nullability tNullability, Types types) {
// Rule 5.
return types.isSubtypeOfKernel(
s.unalias, t, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isVoidRelated(VoidType s, Nullability sNullability, FunctionType t,
Nullability tNullability, Types types) {
return false;
}
}
class IsTypeParameterSubtypeOf extends TypeRelation<TypeParameterType> {
const IsTypeParameterSubtypeOf();
@override
bool isTypeParameterRelated(TypeParameterType s, Nullability sNullability,
TypeParameterType t, Nullability tNullability, Types types) {
return s.parameter == t.parameter ||
// Rule 13.
types.isSubtypeOfKernel(
s.bound, t, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isIntersectionRelated(
TypeParameterType intersection,
Nullability intersectionNullability,
TypeParameterType t,
Nullability tNullability,
Types types) {
return intersection.parameter == t.parameter; // Rule 8.
}
@override
bool isInterfaceRelated(InterfaceType s, Nullability sNullability,
TypeParameterType t, Nullability tNullability, Types types) {
return s.classNode == types.hierarchy.nullClass; // Rule 4.
}
@override
bool isDynamicRelated(DynamicType s, Nullability sNullability,
TypeParameterType t, Nullability tNullability, Types types) {
return false;
}
@override
bool isFunctionRelated(FunctionType s, Nullability sNullability,
TypeParameterType t, Nullability tNullability, Types types) {
return false;
}
@override
bool isFutureOrRelated(
InterfaceType futureOr,
Nullability futureOrNullability,
TypeParameterType t,
Nullability tNullability,
Types types) {
return false;
}
@override
bool isTypedefRelated(TypedefType s, Nullability sNullability,
TypeParameterType t, Nullability tNullability, Types types) {
return types.isSubtypeOfKernel(
s.unalias, t, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isVoidRelated(VoidType s, Nullability sNullability, TypeParameterType t,
Nullability tNullability, Types types) {
return false;
}
}
class IsTypedefSubtypeOf extends TypeRelation<TypedefType> {
const IsTypedefSubtypeOf();
@override
bool isInterfaceRelated(InterfaceType s, Nullability sNullability,
TypedefType t, Nullability tNullability, Types types) {
return types.isSubtypeOfKernel(
s, t.unalias, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isDynamicRelated(DynamicType s, Nullability sNullability, TypedefType t,
Nullability tNullability, Types types) {
return types.isSubtypeOfKernel(
s, t.unalias, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isFunctionRelated(FunctionType s, Nullability sNullability,
TypedefType t, Nullability tNullability, Types types) {
return types.isSubtypeOfKernel(
s, t.unalias, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isFutureOrRelated(
InterfaceType futureOr,
Nullability futureOrNullability,
TypedefType t,
Nullability tNullability,
Types types) {
return types.isSubtypeOfKernel(
futureOr, t.unalias, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isIntersectionRelated(
TypeParameterType intersection,
Nullability intersectionNullability,
TypedefType t,
Nullability tNullability,
Types types) {
return types.isSubtypeOfKernel(
intersection, t.unalias, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isTypeParameterRelated(TypeParameterType s, Nullability sNullability,
TypedefType t, Nullability tNullability, Types types) {
return types.isSubtypeOfKernel(
s, t.unalias, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isTypedefRelated(TypedefType s, Nullability sNullability, TypedefType t,
Nullability tNullability, Types types) {
return types.isSubtypeOfKernel(
s.unalias, t.unalias, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isVoidRelated(VoidType s, Nullability sNullability, TypedefType t,
Nullability tNullability, Types types) {
return types.isSubtypeOfKernel(
s, t.unalias, SubtypeCheckMode.ignoringNullabilities);
}
}
class IsFutureOrSubtypeOf extends TypeRelation<InterfaceType> {
const IsFutureOrSubtypeOf();
@override
bool isInterfaceRelated(InterfaceType s, Nullability sNullability,
InterfaceType futureOr, Nullability futureOrNullability, Types types) {
List<DartType> arguments = futureOr.typeArguments;
if (types.isSubtypeOfKernel(
s, arguments.single, SubtypeCheckMode.ignoringNullabilities)) {
return true; // Rule 11.
}
// Rule 10.
return types.isSubtypeOfKernel(
s,
new InterfaceType(types.hierarchy.futureClass, arguments),
SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isFutureOrRelated(
InterfaceType sFutureOr,
Nullability sFutureOrNullability,
InterfaceType tFutureOr,
Nullability tFutureOrNullability,
Types types) {
// This follows from combining rules 7, 10, and 11.
return types.isSubtypeOfKernel(sFutureOr.typeArguments.single,
tFutureOr.typeArguments.single, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isDynamicRelated(DynamicType s, Nullability sNullability,
InterfaceType futureOr, Nullability futureOrNullability, Types types) {
// Rule 11.
return types.isSubtypeOfKernel(s, futureOr.typeArguments.single,
SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isVoidRelated(VoidType s, Nullability sNullability,
InterfaceType futureOr, Nullability futureOrNullability, Types types) {
// Rule 11.
return types.isSubtypeOfKernel(s, futureOr.typeArguments.single,
SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isTypeParameterRelated(TypeParameterType s, Nullability sNullability,
InterfaceType futureOr, Nullability futureOrNullability, Types types) {
List<DartType> arguments = futureOr.typeArguments;
if (types.isSubtypeOfKernel(
s, arguments.single, SubtypeCheckMode.ignoringNullabilities)) {
// Rule 11.
return true;
}
if (types.isSubtypeOfKernel(
s.parameter.bound, futureOr, SubtypeCheckMode.ignoringNullabilities)) {
// Rule 13.
return true;
}
// Rule 10.
return types.isSubtypeOfKernel(
s,
new InterfaceType(types.hierarchy.futureClass, arguments),
SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isFunctionRelated(FunctionType s, Nullability sNullability,
InterfaceType futureOr, Nullability futureOrNullability, Types types) {
// Rule 11.
return types.isSubtypeOfKernel(s, futureOr.typeArguments.single,
SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isIntersectionRelated(
TypeParameterType intersection,
Nullability intersectionNullability,
InterfaceType futureOr,
Nullability futureOrNullability,
Types types) {
if (isTypeParameterRelated(intersection, intersectionNullability, futureOr,
futureOrNullability, types)) {
// Rule 8.
return true;
}
// Rule 12.
return types.isSubtypeOfKernel(intersection.promotedBound, futureOr,
SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isTypedefRelated(TypedefType s, Nullability sNullability,
InterfaceType futureOr, Nullability futureOrNullability, Types types) {
return types.isSubtypeOfKernel(
s.unalias, futureOr, SubtypeCheckMode.ignoringNullabilities);
}
}
class IsIntersectionSubtypeOf extends TypeRelation<TypeParameterType> {
const IsIntersectionSubtypeOf();
@override
bool isIntersectionRelated(
TypeParameterType sIntersection,
Nullability sIntersectionNullability,
TypeParameterType tIntersection,
Nullability tIntersectionNullability,
Types types) {
// Rule 9.
return const IsTypeParameterSubtypeOf().isIntersectionRelated(
sIntersection,
sIntersectionNullability,
tIntersection,
tIntersectionNullability,
types) &&
types.isSubtypeOfKernel(sIntersection, tIntersection.promotedBound,
SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isTypeParameterRelated(
TypeParameterType s,
Nullability sNullability,
TypeParameterType intersection,
Nullability intersectionNullability,
Types types) {
// Rule 9.
return const IsTypeParameterSubtypeOf().isTypeParameterRelated(
s, sNullability, intersection, intersectionNullability, types) &&
types.isSubtypeOfKernel(s, intersection.promotedBound,
SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isInterfaceRelated(
InterfaceType s,
Nullability sNullability,
TypeParameterType intersection,
Nullability intersectionNullability,
Types types) {
return s.classNode == types.hierarchy.nullClass; // Rule 4.
}
@override
bool isDynamicRelated(
DynamicType s,
Nullability sNullability,
TypeParameterType intersection,
Nullability intersectionNullability,
Types types) {
return false;
}
@override
bool isFunctionRelated(
FunctionType s,
Nullability sNullability,
TypeParameterType intersection,
Nullability intersectionNullability,
Types types) {
return false;
}
@override
bool isFutureOrRelated(
InterfaceType futureOr,
Nullability futureOrNullability,
TypeParameterType intersection,
Nullability intersectionNullability,
Types types) {
return false;
}
@override
bool isTypedefRelated(
TypedefType s,
Nullability sNullability,
TypeParameterType intersection,
Nullability intersectionNullability,
Types types) {
// Rule 5.
return types.isSubtypeOfKernel(
s.unalias, intersection, SubtypeCheckMode.ignoringNullabilities);
}
@override
bool isVoidRelated(
VoidType s,
Nullability sNullability,
TypeParameterType intersection,
Nullability intersectionNullability,
Types types) {
return false;
}
}