mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:58:32 +00:00
[cfe] Add TypeDeclarationType and asInstanceOf
This add a common sealed superclass TypeDeclarationType for ExtensionType and InterfaceType and uses it to add a common asInstanceOf method to ClassHierarchy. Change-Id: I7294e41069b063305c3bd4e384ff90614a3936a6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/331981 Reviewed-by: Chloe Stefantsova <cstefantsova@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Ömer Ağacan <omersa@google.com>
This commit is contained in:
parent
3a41ee6d8d
commit
4b2cf0744d
|
@ -165,7 +165,7 @@ class Types {
|
|||
for (InterfaceType subtype in subtypes) {
|
||||
interfaceTypeEnvironment._add(subtype);
|
||||
List<DartType>? typeArguments = translator.hierarchy
|
||||
.getTypeArgumentsAsInstanceOf(subtype, superclass)
|
||||
.getInterfaceTypeArgumentsAsInstanceOfClass(subtype, superclass)
|
||||
?.map(normalize)
|
||||
.toList();
|
||||
ClassInfo subclassInfo = translator.classInfo[subtype.classNode]!;
|
||||
|
@ -668,7 +668,7 @@ class Types {
|
|||
// arguments.
|
||||
Class cls = translator.classForType(operandType);
|
||||
InterfaceType? base = translator.hierarchy
|
||||
.getTypeAsInstanceOf(type, cls,
|
||||
.getInterfaceTypeAsInstanceOfClass(type, cls,
|
||||
isNonNullableByDefault:
|
||||
codeGen.member.enclosingLibrary.isNonNullableByDefault)
|
||||
?.withDeclaredNullability(operandType.declaredNullability);
|
||||
|
|
|
@ -4205,7 +4205,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
|
|||
.returnType;
|
||||
if (type is InterfaceType) {
|
||||
var matchArguments =
|
||||
_hierarchy.getTypeArgumentsAsInstanceOf(type, expected);
|
||||
_hierarchy.getInterfaceTypeArgumentsAsInstanceOfClass(type, expected);
|
||||
if (matchArguments != null) return matchArguments[0];
|
||||
}
|
||||
return const DynamicType();
|
||||
|
|
|
@ -270,8 +270,8 @@ abstract class CombinedMemberSignatureBase {
|
|||
return _containsNnbdTypes;
|
||||
}
|
||||
|
||||
/// Returns the [declarationBuilder] as an instance of [cls].
|
||||
InterfaceType _asInstanceOfClass(Class cls);
|
||||
/// Returns the this type of the [declarationBuilder].
|
||||
TypeDeclarationType get thisType;
|
||||
|
||||
/// Returns `true` if the canonical member is declared in
|
||||
/// [declarationBuilder].
|
||||
|
@ -726,11 +726,14 @@ abstract class CombinedMemberSignatureBase {
|
|||
unhandled("${member.runtimeType}", "$member",
|
||||
declarationBuilder.charOffset, declarationBuilder.fileUri);
|
||||
}
|
||||
if (member.enclosingClass!.typeParameters.isEmpty) {
|
||||
if (member.enclosingTypeDeclaration!.typeParameters.isEmpty) {
|
||||
return type;
|
||||
}
|
||||
InterfaceType instance = _asInstanceOfClass(member.enclosingClass!);
|
||||
return Substitution.fromInterfaceType(instance).substituteType(type);
|
||||
TypeDeclarationType instance = hierarchy.getTypeAsInstanceOf(
|
||||
thisType, member.enclosingTypeDeclaration!,
|
||||
isNonNullableByDefault:
|
||||
declarationBuilder.libraryBuilder.isNonNullableByDefault)!;
|
||||
return Substitution.fromTypeDeclarationType(instance).substituteType(type);
|
||||
}
|
||||
|
||||
bool _isMoreSpecific(DartType a, DartType b, bool forSetter) {
|
||||
|
@ -771,18 +774,12 @@ class CombinedClassMemberSignature extends CombinedMemberSignatureBase {
|
|||
DeclarationBuilder get declarationBuilder => classBuilder;
|
||||
|
||||
/// The this type of [classBuilder].
|
||||
@override
|
||||
InterfaceType get thisType {
|
||||
return _thisType ??= _coreTypes.thisInterfaceType(
|
||||
classBuilder.cls, declarationBuilder.libraryBuilder.nonNullable);
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType _asInstanceOfClass(Class cls) {
|
||||
return hierarchy.getTypeAsInstanceOf(thisType, cls,
|
||||
isNonNullableByDefault:
|
||||
declarationBuilder.libraryBuilder.isNonNullableByDefault);
|
||||
}
|
||||
|
||||
/// Returns `true` if the canonical member is declared in
|
||||
/// [declarationBuilder].
|
||||
@override
|
||||
|
@ -824,19 +821,13 @@ class CombinedExtensionTypeMemberSignature extends CombinedMemberSignatureBase {
|
|||
DeclarationBuilder get declarationBuilder => extensionTypeDeclarationBuilder;
|
||||
|
||||
/// The this type of [extensionTypeDeclarationBuilder].
|
||||
@override
|
||||
ExtensionType get thisType {
|
||||
return _thisType ??= _coreTypes.thisExtensionType(
|
||||
extensionTypeDeclarationBuilder.extensionTypeDeclaration,
|
||||
declarationBuilder.libraryBuilder.nonNullable);
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType _asInstanceOfClass(Class cls) {
|
||||
return hierarchy.getExtensionTypeAsInstanceOfClass(thisType, cls,
|
||||
isNonNullableByDefault:
|
||||
declarationBuilder.libraryBuilder.isNonNullableByDefault)!;
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isCanonicalMemberDeclared => false;
|
||||
}
|
||||
|
|
|
@ -136,8 +136,8 @@ class CfeTypeOperations implements TypeOperations<DartType> {
|
|||
Class declaringClass = member.enclosingClass!;
|
||||
if (declaringClass.typeParameters.isNotEmpty) {
|
||||
Substitution substitution = substitutions[declaringClass] ??=
|
||||
Substitution.fromInterfaceType(
|
||||
_classHierarchy.getTypeAsInstanceOf(type, declaringClass,
|
||||
Substitution.fromInterfaceType(_classHierarchy
|
||||
.getInterfaceTypeAsInstanceOfClass(type, declaringClass,
|
||||
isNonNullableByDefault: true)!);
|
||||
fieldType = substitution.substituteType(fieldType);
|
||||
}
|
||||
|
@ -188,9 +188,10 @@ class CfeTypeOperations implements TypeOperations<DartType> {
|
|||
DartType? getListElementType(DartType type) {
|
||||
type = type.resolveTypeParameterType;
|
||||
if (type is InterfaceType) {
|
||||
InterfaceType? listType = _classHierarchy.getTypeAsInstanceOf(
|
||||
type, _typeEnvironment.coreTypes.listClass,
|
||||
isNonNullableByDefault: true);
|
||||
InterfaceType? listType =
|
||||
_classHierarchy.getInterfaceTypeAsInstanceOfClass(
|
||||
type, _typeEnvironment.coreTypes.listClass,
|
||||
isNonNullableByDefault: true);
|
||||
if (listType != null) {
|
||||
return listType.typeArguments[0];
|
||||
}
|
||||
|
@ -202,7 +203,7 @@ class CfeTypeOperations implements TypeOperations<DartType> {
|
|||
DartType? getListType(DartType type) {
|
||||
type = type.resolveTypeParameterType;
|
||||
if (type is InterfaceType) {
|
||||
return _classHierarchy.getTypeAsInstanceOf(
|
||||
return _classHierarchy.getInterfaceTypeAsInstanceOfClass(
|
||||
type, _typeEnvironment.coreTypes.listClass,
|
||||
isNonNullableByDefault: true);
|
||||
}
|
||||
|
@ -213,9 +214,10 @@ class CfeTypeOperations implements TypeOperations<DartType> {
|
|||
DartType? getMapValueType(DartType type) {
|
||||
type = type.resolveTypeParameterType;
|
||||
if (type is InterfaceType) {
|
||||
InterfaceType? mapType = _classHierarchy.getTypeAsInstanceOf(
|
||||
type, _typeEnvironment.coreTypes.mapClass,
|
||||
isNonNullableByDefault: true);
|
||||
InterfaceType? mapType =
|
||||
_classHierarchy.getInterfaceTypeAsInstanceOfClass(
|
||||
type, _typeEnvironment.coreTypes.mapClass,
|
||||
isNonNullableByDefault: true);
|
||||
if (mapType != null) {
|
||||
return mapType.typeArguments[1];
|
||||
}
|
||||
|
@ -394,9 +396,9 @@ class CfeSealedClassOperations
|
|||
Class subClass, covariant InterfaceType sealedClassType) {
|
||||
InterfaceType thisType = subClass.getThisType(
|
||||
_typeEnvironment.coreTypes, Nullability.nonNullable);
|
||||
InterfaceType asSealedType = _typeEnvironment.hierarchy.getTypeAsInstanceOf(
|
||||
thisType, sealedClassType.classNode,
|
||||
isNonNullableByDefault: true)!;
|
||||
InterfaceType asSealedType = _typeEnvironment.hierarchy
|
||||
.getInterfaceTypeAsInstanceOfClass(thisType, sealedClassType.classNode,
|
||||
isNonNullableByDefault: true)!;
|
||||
if (thisType.typeArguments.isEmpty) {
|
||||
return thisType;
|
||||
}
|
||||
|
|
|
@ -112,7 +112,8 @@ class ClassHierarchyBuilder
|
|||
}
|
||||
|
||||
@override
|
||||
InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass,
|
||||
InterfaceType getInterfaceTypeAsInstanceOfClass(
|
||||
InterfaceType type, Class superclass,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
if (type.classNode == superclass) return type;
|
||||
return asSupertypeOf(type, superclass)!
|
||||
|
@ -121,7 +122,7 @@ class ClassHierarchyBuilder
|
|||
}
|
||||
|
||||
@override
|
||||
List<DartType>? getTypeArgumentsAsInstanceOf(
|
||||
List<DartType>? getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
InterfaceType type, Class superclass) {
|
||||
if (type.classReference == superclass.reference) return type.typeArguments;
|
||||
return asSupertypeOf(type, superclass)?.typeArguments;
|
||||
|
@ -133,14 +134,11 @@ class ClassHierarchyBuilder
|
|||
}
|
||||
|
||||
InterfaceType _getLegacyLeastUpperBoundInternal(
|
||||
/* InterfaceType | ExtensionType */ DartType type1,
|
||||
/* InterfaceType | ExtensionType */ DartType type2,
|
||||
TypeDeclarationType type1,
|
||||
TypeDeclarationType type2,
|
||||
List<ClassHierarchyNode> supertypeNodes1,
|
||||
List<ClassHierarchyNode> supertypeNodes2,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
assert(type1 is InterfaceType || type1 is ExtensionType);
|
||||
assert(type2 is InterfaceType || type2 is ExtensionType);
|
||||
|
||||
Set<ClassHierarchyNode> supertypeNodesSet1 = supertypeNodes1.toSet();
|
||||
List<ClassHierarchyNode> common = <ClassHierarchyNode>[];
|
||||
|
||||
|
@ -151,27 +149,10 @@ class ClassHierarchyBuilder
|
|||
continue;
|
||||
}
|
||||
if (supertypeNodesSet1.contains(node)) {
|
||||
DartType candidate1;
|
||||
if (type1 is InterfaceType) {
|
||||
candidate1 = getTypeAsInstanceOf(type1, node.classBuilder.cls,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
} else {
|
||||
type1 as ExtensionType;
|
||||
candidate1 = getExtensionTypeAsInstanceOfClass(
|
||||
type1, node.classBuilder.cls,
|
||||
isNonNullableByDefault: isNonNullableByDefault)!;
|
||||
}
|
||||
|
||||
DartType candidate2;
|
||||
if (type2 is InterfaceType) {
|
||||
candidate2 = getTypeAsInstanceOf(type2, node.classBuilder.cls,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
} else {
|
||||
type2 as ExtensionType;
|
||||
candidate2 = getExtensionTypeAsInstanceOfClass(
|
||||
type2, node.classBuilder.cls,
|
||||
isNonNullableByDefault: isNonNullableByDefault)!;
|
||||
}
|
||||
DartType candidate1 = getTypeAsInstanceOf(type1, node.classBuilder.cls,
|
||||
isNonNullableByDefault: isNonNullableByDefault)!;
|
||||
DartType candidate2 = getTypeAsInstanceOf(type2, node.classBuilder.cls,
|
||||
isNonNullableByDefault: isNonNullableByDefault)!;
|
||||
if (candidate1 == candidate2) {
|
||||
common.add(node);
|
||||
}
|
||||
|
@ -194,7 +175,7 @@ class ClassHierarchyBuilder
|
|||
ClassHierarchyNode node = common[i];
|
||||
if (node.maxInheritancePath != common[i + 1].maxInheritancePath) {
|
||||
if (type1 is InterfaceType) {
|
||||
return getTypeAsInstanceOf(type1, node.classBuilder.cls,
|
||||
return getInterfaceTypeAsInstanceOfClass(type1, node.classBuilder.cls,
|
||||
isNonNullableByDefault: isNonNullableByDefault)
|
||||
.withDeclaredNullability(
|
||||
uniteNullabilities(type1.nullability, type2.nullability));
|
||||
|
@ -246,8 +227,8 @@ class ClassHierarchyBuilder
|
|||
|
||||
@override
|
||||
InterfaceType getLegacyLeastUpperBoundFromSupertypeLists(
|
||||
/* InterfaceType | ExtensionType */ DartType type1,
|
||||
/* InterfaceType | ExtensionType */ DartType type2,
|
||||
TypeDeclarationType type1,
|
||||
TypeDeclarationType type2,
|
||||
List<InterfaceType> supertypes1,
|
||||
List<InterfaceType> supertypes2,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
|
|
|
@ -82,14 +82,15 @@ class TypeBuilderConstraintGatherer extends TypeConstraintGatherer
|
|||
InterfaceType getTypeAsInstanceOf(
|
||||
InterfaceType type, Class superclass, CoreTypes coreTypes,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
return hierarchy.getTypeAsInstanceOf(type, superclass,
|
||||
return hierarchy.getInterfaceTypeAsInstanceOfClass(type, superclass,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
}
|
||||
|
||||
@override
|
||||
List<DartType>? getTypeArgumentsAsInstanceOf(
|
||||
InterfaceType type, Class superclass) {
|
||||
return hierarchy.getTypeArgumentsAsInstanceOf(type, superclass);
|
||||
return hierarchy.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
type, superclass);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -903,9 +903,10 @@ class SourceClassBuilder extends ClassBuilderImpl
|
|||
for (Supertype constraint in cls.mixedInClass!.onClause) {
|
||||
InterfaceType requiredInterface =
|
||||
substitution.substituteSupertype(constraint).asInterfaceType;
|
||||
InterfaceType? implementedInterface = hierarchy.getTypeAsInstanceOf(
|
||||
supertype, requiredInterface.classNode,
|
||||
isNonNullableByDefault: libraryBuilder.isNonNullableByDefault);
|
||||
InterfaceType? implementedInterface =
|
||||
hierarchy.getInterfaceTypeAsInstanceOfClass(
|
||||
supertype, requiredInterface.classNode,
|
||||
isNonNullableByDefault: libraryBuilder.isNonNullableByDefault);
|
||||
if (implementedInterface == null ||
|
||||
!typeEnvironment.areMutualSubtypes(
|
||||
implementedInterface,
|
||||
|
@ -1374,7 +1375,7 @@ class SourceClassBuilder extends ClassBuilderImpl
|
|||
if (getter.enclosingClass!.typeParameters.isNotEmpty) {
|
||||
getterType = Substitution.fromPairs(
|
||||
getter.enclosingClass!.typeParameters,
|
||||
types.hierarchy.getTypeArgumentsAsInstanceOf(
|
||||
types.hierarchy.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
thisType, getter.enclosingClass!)!)
|
||||
.substituteType(getterType);
|
||||
}
|
||||
|
@ -1383,7 +1384,7 @@ class SourceClassBuilder extends ClassBuilderImpl
|
|||
if (setter.enclosingClass!.typeParameters.isNotEmpty) {
|
||||
setterType = Substitution.fromPairs(
|
||||
setter.enclosingClass!.typeParameters,
|
||||
types.hierarchy.getTypeArgumentsAsInstanceOf(
|
||||
types.hierarchy.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
thisType, setter.enclosingClass!)!)
|
||||
.substituteType(setterType);
|
||||
}
|
||||
|
@ -1531,8 +1532,8 @@ class SourceClassBuilder extends ClassBuilderImpl
|
|||
Class enclosingClass = interfaceMember.enclosingClass!;
|
||||
interfaceSubstitution = Substitution.fromPairs(
|
||||
enclosingClass.typeParameters,
|
||||
types.hierarchy
|
||||
.getTypeArgumentsAsInstanceOf(thisType, enclosingClass)!);
|
||||
types.hierarchy.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
thisType, enclosingClass)!);
|
||||
}
|
||||
|
||||
if (declaredFunction?.typeParameters.length !=
|
||||
|
@ -1643,8 +1644,8 @@ class SourceClassBuilder extends ClassBuilderImpl
|
|||
Class enclosingClass = declaredMember.enclosingClass!;
|
||||
declaredSubstitution = Substitution.fromPairs(
|
||||
enclosingClass.typeParameters,
|
||||
types.hierarchy
|
||||
.getTypeArgumentsAsInstanceOf(thisType, enclosingClass)!);
|
||||
types.hierarchy.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
thisType, enclosingClass)!);
|
||||
}
|
||||
return declaredSubstitution;
|
||||
}
|
||||
|
|
|
@ -1518,8 +1518,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
if (inferredExpressionType is InterfaceType) {
|
||||
// TODO(johnniwinther): Should we use the type of
|
||||
// `iterable.iterator.current` instead?
|
||||
List<DartType>? supertypeArguments = hierarchyBuilder
|
||||
.getTypeArgumentsAsInstanceOf(inferredExpressionType, iterableClass);
|
||||
List<DartType>? supertypeArguments =
|
||||
hierarchyBuilder.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
inferredExpressionType, iterableClass);
|
||||
if (supertypeArguments != null) {
|
||||
inferredType = supertypeArguments[0];
|
||||
}
|
||||
|
|
|
@ -1450,8 +1450,9 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
if (enclosingClass.typeParameters.isNotEmpty) {
|
||||
receiverType = resolveTypeParameter(receiverType);
|
||||
if (receiverType is InterfaceType) {
|
||||
List<DartType> castedTypeArguments = hierarchyBuilder
|
||||
.getTypeArgumentsAsInstanceOf(receiverType, enclosingClass)!;
|
||||
List<DartType> castedTypeArguments =
|
||||
hierarchyBuilder.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
receiverType, enclosingClass)!;
|
||||
calleeType = Substitution.fromPairs(
|
||||
enclosingClass.typeParameters, castedTypeArguments)
|
||||
.substituteType(calleeType);
|
||||
|
@ -1492,8 +1493,8 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
|
||||
DartType? getDerivedTypeArgumentOf(DartType type, Class class_) {
|
||||
if (type is InterfaceType) {
|
||||
List<DartType>? typeArgumentsAsInstanceOfClass =
|
||||
hierarchyBuilder.getTypeArgumentsAsInstanceOf(type, class_);
|
||||
List<DartType>? typeArgumentsAsInstanceOfClass = hierarchyBuilder
|
||||
.getInterfaceTypeArgumentsAsInstanceOfClass(type, class_);
|
||||
if (typeArgumentsAsInstanceOfClass != null) {
|
||||
return typeArgumentsAsInstanceOfClass[0];
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ class InheritanceDataExtractor extends CfeDataExtractor<String> {
|
|||
if (member.enclosingClass == _coreTypes.objectClass) {
|
||||
return;
|
||||
}
|
||||
InterfaceType supertype = _hierarchy.getTypeAsInstanceOf(
|
||||
InterfaceType supertype = _hierarchy.getInterfaceTypeAsInstanceOfClass(
|
||||
_coreTypes.thisInterfaceType(node, node.enclosingLibrary.nonNullable),
|
||||
member.enclosingClass!,
|
||||
isNonNullableByDefault:
|
||||
|
|
|
@ -11097,6 +11097,20 @@ sealed class DartType extends Node {
|
|||
void toTextInternal(AstPrinter printer);
|
||||
}
|
||||
|
||||
/// A type which is an instantiation of a [TypeDeclaration].
|
||||
sealed class TypeDeclarationType extends DartType {
|
||||
/// The [Reference] to the [TypeDeclaration] on which this
|
||||
/// [TypeDeclarationType] is built.
|
||||
Reference get typeDeclarationReference;
|
||||
|
||||
/// The type arguments used to instantiate this [TypeDeclarationType].
|
||||
List<DartType> get typeArguments;
|
||||
|
||||
/// The [TypeDeclaration] on which this [TypeDeclarationType] is built.
|
||||
TypeDeclaration get typeDeclaration =>
|
||||
typeDeclarationReference.asTypeDeclaration;
|
||||
}
|
||||
|
||||
abstract class AuxiliaryType extends DartType {
|
||||
const AuxiliaryType();
|
||||
|
||||
|
@ -11360,12 +11374,13 @@ class NullType extends DartType {
|
|||
}
|
||||
}
|
||||
|
||||
class InterfaceType extends DartType {
|
||||
class InterfaceType extends TypeDeclarationType {
|
||||
final Reference classReference;
|
||||
|
||||
@override
|
||||
final Nullability declaredNullability;
|
||||
|
||||
@override
|
||||
final List<DartType> typeArguments;
|
||||
|
||||
/// The [typeArguments] list must not be modified after this call. If the
|
||||
|
@ -11378,6 +11393,9 @@ class InterfaceType extends DartType {
|
|||
InterfaceType.byReference(
|
||||
this.classReference, this.declaredNullability, this.typeArguments);
|
||||
|
||||
@override
|
||||
Reference get typeDeclarationReference => classReference;
|
||||
|
||||
Class get classNode => classReference.asClass;
|
||||
|
||||
@override
|
||||
|
@ -11841,12 +11859,13 @@ class FutureOrType extends DartType {
|
|||
}
|
||||
}
|
||||
|
||||
class ExtensionType extends DartType {
|
||||
class ExtensionType extends TypeDeclarationType {
|
||||
final Reference extensionTypeDeclarationReference;
|
||||
|
||||
@override
|
||||
final Nullability declaredNullability;
|
||||
|
||||
@override
|
||||
final List<DartType> typeArguments;
|
||||
|
||||
ExtensionType(ExtensionTypeDeclaration extensionTypeDeclaration,
|
||||
|
@ -11862,6 +11881,9 @@ class ExtensionType extends DartType {
|
|||
ExtensionTypeDeclaration get extensionTypeDeclaration =>
|
||||
extensionTypeDeclarationReference.asExtensionTypeDeclaration;
|
||||
|
||||
@override
|
||||
Reference get typeDeclarationReference => extensionTypeDeclarationReference;
|
||||
|
||||
/// Returns the type erasure of this extension type.
|
||||
///
|
||||
/// This is the type used at runtime for this type, for instance in is-tests
|
||||
|
|
|
@ -508,6 +508,15 @@ class Reference implements Comparable<Reference> {
|
|||
return node as Library;
|
||||
}
|
||||
|
||||
TypeDeclaration get asTypeDeclaration {
|
||||
NamedNode? node = this.node;
|
||||
if (node == null) {
|
||||
throw '$this is not bound to an AST node. '
|
||||
'A type declaration was expected';
|
||||
}
|
||||
return node as TypeDeclaration;
|
||||
}
|
||||
|
||||
Class get asClass {
|
||||
NamedNode? node = this.node;
|
||||
if (node == null) {
|
||||
|
|
|
@ -31,15 +31,28 @@ abstract class ClassHierarchyBase {
|
|||
/// or `null` if [class_] does not implement [superclass] at all.
|
||||
Supertype? getClassAsInstanceOf(Class class_, Class superclass);
|
||||
|
||||
/// Returns the instantiation of [typeDeclaration] that is implemented by
|
||||
/// [type], or `null` if [type] does not implement [typeDeclaration] at all.
|
||||
TypeDeclarationType? getTypeAsInstanceOf(
|
||||
TypeDeclarationType type, TypeDeclaration typeDeclaration,
|
||||
{required bool isNonNullableByDefault});
|
||||
|
||||
/// Returns the type arguments of the instantiation of [typeDeclaration] that
|
||||
/// is implemented by [type], or `null` if [type] does not implement
|
||||
/// [typeDeclaration] at all.
|
||||
List<DartType>? getTypeArgumentsAsInstanceOf(
|
||||
TypeDeclarationType type, TypeDeclaration typeDeclaration);
|
||||
|
||||
/// Returns the instantiation of [superclass] that is implemented by [type],
|
||||
/// or `null` if [type] does not implement [superclass] at all.
|
||||
InterfaceType? getTypeAsInstanceOf(InterfaceType type, Class superclass,
|
||||
InterfaceType? getInterfaceTypeAsInstanceOfClass(
|
||||
InterfaceType type, Class superclass,
|
||||
{required bool isNonNullableByDefault});
|
||||
|
||||
/// Returns the type arguments of the instantiation of [superclass] that is
|
||||
/// implemented by [type], or `null` if [type] does not implement [superclass]
|
||||
/// at all.
|
||||
List<DartType>? getTypeArgumentsAsInstanceOf(
|
||||
List<DartType>? getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
InterfaceType type, Class superclass);
|
||||
|
||||
/// Returns the instantiation of [superDeclaration] that is implemented by
|
||||
|
@ -101,14 +114,65 @@ abstract class ClassHierarchyBase {
|
|||
/// its non-extension supertypes. It is used as a part of the algorithm for
|
||||
/// finding the upper bound of extension types.
|
||||
InterfaceType getLegacyLeastUpperBoundFromSupertypeLists(
|
||||
/* InterfaceType | ExtensionType */ DartType type1,
|
||||
/* InterfaceType | ExtensionType */ DartType type2,
|
||||
TypeDeclarationType type1,
|
||||
TypeDeclarationType type2,
|
||||
List<InterfaceType> supertypes1,
|
||||
List<InterfaceType> supertypes2,
|
||||
{required bool isNonNullableByDefault});
|
||||
}
|
||||
|
||||
mixin ClassHierarchyExtensionTypeMixin implements ClassHierarchyBase {
|
||||
@override
|
||||
TypeDeclarationType? getTypeAsInstanceOf(
|
||||
TypeDeclarationType type, TypeDeclaration typeDeclaration,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
switch (type) {
|
||||
case InterfaceType():
|
||||
switch (typeDeclaration) {
|
||||
case Class():
|
||||
return getInterfaceTypeAsInstanceOfClass(type, typeDeclaration,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
case ExtensionTypeDeclaration():
|
||||
return null;
|
||||
}
|
||||
case ExtensionType():
|
||||
switch (typeDeclaration) {
|
||||
case Class():
|
||||
return getExtensionTypeAsInstanceOfClass(type, typeDeclaration,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
case ExtensionTypeDeclaration():
|
||||
return getExtensionTypeAsInstanceOfExtensionTypeDeclaration(
|
||||
type, typeDeclaration,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
List<DartType>? getTypeArgumentsAsInstanceOf(
|
||||
TypeDeclarationType type, TypeDeclaration typeDeclaration) {
|
||||
switch (type) {
|
||||
case InterfaceType():
|
||||
switch (typeDeclaration) {
|
||||
case Class():
|
||||
return getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
type, typeDeclaration);
|
||||
case ExtensionTypeDeclaration():
|
||||
return null;
|
||||
}
|
||||
case ExtensionType():
|
||||
switch (typeDeclaration) {
|
||||
case Class():
|
||||
return getExtensionTypeArgumentsAsInstanceOfClass(
|
||||
type, typeDeclaration);
|
||||
case ExtensionTypeDeclaration():
|
||||
// ignore: lines_longer_than_80_chars
|
||||
return getExtensionTypeArgumentsAsInstanceOfExtensionTypeDeclaration(
|
||||
type, typeDeclaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionType?
|
||||
getExtensionTypeDeclarationAsInstanceOfExtensionTypeDeclaration(
|
||||
ExtensionTypeDeclaration subDeclaration,
|
||||
|
@ -878,15 +942,13 @@ class ClosedWorldClassHierarchy
|
|||
}
|
||||
|
||||
InterfaceType _getLegacyLeastUpperBoundInternal(
|
||||
/* InterfaceType | ExtensionType */ DartType type1,
|
||||
/* InterfaceType | ExtensionType */ DartType type2,
|
||||
TypeDeclarationType type1,
|
||||
TypeDeclarationType type2,
|
||||
_ClassInfo? info1,
|
||||
_ClassInfo? info2,
|
||||
List<_ClassInfo> classInfos1,
|
||||
List<_ClassInfo> classInfos2,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
assert(type1 is InterfaceType || type1 is ExtensionType);
|
||||
assert(type2 is InterfaceType || type2 is ExtensionType);
|
||||
assert(type1 is! InterfaceType || info1 != null);
|
||||
assert(type2 is! InterfaceType || info2 != null);
|
||||
|
||||
|
@ -983,13 +1045,11 @@ class ClosedWorldClassHierarchy
|
|||
|
||||
@override
|
||||
InterfaceType getLegacyLeastUpperBoundFromSupertypeLists(
|
||||
/* InterfaceType | ExtensionType */ DartType type1,
|
||||
/* InterfaceType | ExtensionType */ DartType type2,
|
||||
TypeDeclarationType type1,
|
||||
TypeDeclarationType type2,
|
||||
List<InterfaceType> supertypes1,
|
||||
List<InterfaceType> supertypes2,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
assert(type1 is InterfaceType || type1 is ExtensionType);
|
||||
assert(type2 is InterfaceType || type2 is ExtensionType);
|
||||
assert(supertypes1.isNotEmpty || type1 is ExtensionType);
|
||||
assert(supertypes2.isNotEmpty || type2 is ExtensionType);
|
||||
|
||||
|
@ -1035,10 +1095,11 @@ class ClosedWorldClassHierarchy
|
|||
}
|
||||
|
||||
@override
|
||||
InterfaceType? getTypeAsInstanceOf(InterfaceType type, Class superclass,
|
||||
InterfaceType? getInterfaceTypeAsInstanceOfClass(
|
||||
InterfaceType type, Class superclass,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
List<DartType>? typeArguments =
|
||||
getTypeArgumentsAsInstanceOf(type, superclass);
|
||||
getInterfaceTypeArgumentsAsInstanceOfClass(type, superclass);
|
||||
if (typeArguments == null) return null;
|
||||
// The return value should be a legacy type if it's computed for an
|
||||
// opted-out library, unless the return value is Null? which is always
|
||||
|
@ -1049,7 +1110,7 @@ class ClosedWorldClassHierarchy
|
|||
}
|
||||
|
||||
@override
|
||||
List<DartType>? getTypeArgumentsAsInstanceOf(
|
||||
List<DartType>? getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
InterfaceType type, Class superclass) {
|
||||
if (type.classReference == superclass.reference) {
|
||||
// TODO(johnniwinther): This is necessary because [getClassAsInstanceOf]
|
||||
|
|
|
@ -865,6 +865,18 @@ class CoverageVisitor implements Visitor<void> {
|
|||
node.visitChildren(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitInterfaceType(InterfaceType node) {
|
||||
visited.add(DartTypeKind.InterfaceType);
|
||||
node.visitChildren(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitExtensionType(ExtensionType node) {
|
||||
visited.add(DartTypeKind.ExtensionType);
|
||||
node.visitChildren(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitAuxiliaryType(AuxiliaryType node) {
|
||||
throw new UnsupportedError(
|
||||
|
@ -901,12 +913,6 @@ class CoverageVisitor implements Visitor<void> {
|
|||
node.visitChildren(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitInterfaceType(InterfaceType node) {
|
||||
visited.add(DartTypeKind.InterfaceType);
|
||||
node.visitChildren(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitFunctionType(FunctionType node) {
|
||||
visited.add(DartTypeKind.FunctionType);
|
||||
|
@ -925,12 +931,6 @@ class CoverageVisitor implements Visitor<void> {
|
|||
node.visitChildren(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitExtensionType(ExtensionType node) {
|
||||
visited.add(DartTypeKind.ExtensionType);
|
||||
node.visitChildren(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitIntersectionType(IntersectionType node) {
|
||||
visited.add(DartTypeKind.IntersectionType);
|
||||
|
|
|
@ -742,6 +742,16 @@ class EquivalenceVisitor implements Visitor1<bool, Node> {
|
|||
return strategy.checkName(this, node, other);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitInterfaceType(InterfaceType node, Node other) {
|
||||
return strategy.checkInterfaceType(this, node, other);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitExtensionType(ExtensionType node, Node other) {
|
||||
return strategy.checkExtensionType(this, node, other);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitAuxiliaryType(AuxiliaryType node, Node other) {
|
||||
return strategy.checkAuxiliaryType(this, node, other);
|
||||
|
@ -772,11 +782,6 @@ class EquivalenceVisitor implements Visitor1<bool, Node> {
|
|||
return strategy.checkNullType(this, node, other);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitInterfaceType(InterfaceType node, Node other) {
|
||||
return strategy.checkInterfaceType(this, node, other);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitFunctionType(FunctionType node, Node other) {
|
||||
return strategy.checkFunctionType(this, node, other);
|
||||
|
@ -792,11 +797,6 @@ class EquivalenceVisitor implements Visitor1<bool, Node> {
|
|||
return strategy.checkFutureOrType(this, node, other);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitExtensionType(ExtensionType node, Node other) {
|
||||
return strategy.checkExtensionType(this, node, other);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitIntersectionType(IntersectionType node, Node other) {
|
||||
return strategy.checkIntersectionType(this, node, other);
|
||||
|
@ -5119,6 +5119,47 @@ class EquivalenceStrategy {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool checkInterfaceType(
|
||||
EquivalenceVisitor visitor, InterfaceType? node, Object? other) {
|
||||
if (identical(node, other)) return true;
|
||||
if (node is! InterfaceType) return false;
|
||||
if (other is! InterfaceType) return false;
|
||||
visitor.pushNodeState(node, other);
|
||||
bool result = true;
|
||||
if (!checkInterfaceType_classReference(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
if (!checkInterfaceType_declaredNullability(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
if (!checkInterfaceType_typeArguments(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
visitor.popState();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool checkExtensionType(
|
||||
EquivalenceVisitor visitor, ExtensionType? node, Object? other) {
|
||||
if (identical(node, other)) return true;
|
||||
if (node is! ExtensionType) return false;
|
||||
if (other is! ExtensionType) return false;
|
||||
visitor.pushNodeState(node, other);
|
||||
bool result = true;
|
||||
if (!checkExtensionType_extensionTypeDeclarationReference(
|
||||
visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
if (!checkExtensionType_declaredNullability(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
if (!checkExtensionType_typeArguments(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
visitor.popState();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool checkAuxiliaryType(
|
||||
EquivalenceVisitor visitor, AuxiliaryType? node, Object? other) {
|
||||
if (identical(node, other)) return true;
|
||||
|
@ -5188,26 +5229,6 @@ class EquivalenceStrategy {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool checkInterfaceType(
|
||||
EquivalenceVisitor visitor, InterfaceType? node, Object? other) {
|
||||
if (identical(node, other)) return true;
|
||||
if (node is! InterfaceType) return false;
|
||||
if (other is! InterfaceType) return false;
|
||||
visitor.pushNodeState(node, other);
|
||||
bool result = true;
|
||||
if (!checkInterfaceType_classReference(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
if (!checkInterfaceType_declaredNullability(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
if (!checkInterfaceType_typeArguments(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
visitor.popState();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool checkFunctionType(
|
||||
EquivalenceVisitor visitor, FunctionType? node, Object? other) {
|
||||
if (identical(node, other)) return true;
|
||||
|
@ -5274,27 +5295,6 @@ class EquivalenceStrategy {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool checkExtensionType(
|
||||
EquivalenceVisitor visitor, ExtensionType? node, Object? other) {
|
||||
if (identical(node, other)) return true;
|
||||
if (node is! ExtensionType) return false;
|
||||
if (other is! ExtensionType) return false;
|
||||
visitor.pushNodeState(node, other);
|
||||
bool result = true;
|
||||
if (!checkExtensionType_extensionTypeDeclarationReference(
|
||||
visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
if (!checkExtensionType_declaredNullability(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
if (!checkExtensionType_typeArguments(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
visitor.popState();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool checkIntersectionType(
|
||||
EquivalenceVisitor visitor, IntersectionType? node, Object? other) {
|
||||
if (identical(node, other)) return true;
|
||||
|
@ -9344,12 +9344,6 @@ class EquivalenceStrategy {
|
|||
return visitor.checkValues(node.text, other.text, 'text');
|
||||
}
|
||||
|
||||
bool checkNeverType_declaredNullability(
|
||||
EquivalenceVisitor visitor, NeverType node, NeverType other) {
|
||||
return visitor.checkValues(node.declaredNullability,
|
||||
other.declaredNullability, 'declaredNullability');
|
||||
}
|
||||
|
||||
bool checkInterfaceType_classReference(
|
||||
EquivalenceVisitor visitor, InterfaceType node, InterfaceType other) {
|
||||
return visitor.checkReferences(
|
||||
|
@ -9368,6 +9362,32 @@ class EquivalenceStrategy {
|
|||
visitor.checkNodes, 'typeArguments');
|
||||
}
|
||||
|
||||
bool checkExtensionType_extensionTypeDeclarationReference(
|
||||
EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
|
||||
return visitor.checkReferences(
|
||||
node.extensionTypeDeclarationReference,
|
||||
other.extensionTypeDeclarationReference,
|
||||
'extensionTypeDeclarationReference');
|
||||
}
|
||||
|
||||
bool checkExtensionType_declaredNullability(
|
||||
EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
|
||||
return visitor.checkValues(node.declaredNullability,
|
||||
other.declaredNullability, 'declaredNullability');
|
||||
}
|
||||
|
||||
bool checkExtensionType_typeArguments(
|
||||
EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
|
||||
return visitor.checkLists(node.typeArguments, other.typeArguments,
|
||||
visitor.checkNodes, 'typeArguments');
|
||||
}
|
||||
|
||||
bool checkNeverType_declaredNullability(
|
||||
EquivalenceVisitor visitor, NeverType node, NeverType other) {
|
||||
return visitor.checkValues(node.declaredNullability,
|
||||
other.declaredNullability, 'declaredNullability');
|
||||
}
|
||||
|
||||
bool checkFunctionType_typeParameters(
|
||||
EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
|
||||
return visitor.checkLists(node.typeParameters, other.typeParameters,
|
||||
|
@ -9433,26 +9453,6 @@ class EquivalenceStrategy {
|
|||
other.declaredNullability, 'declaredNullability');
|
||||
}
|
||||
|
||||
bool checkExtensionType_extensionTypeDeclarationReference(
|
||||
EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
|
||||
return visitor.checkReferences(
|
||||
node.extensionTypeDeclarationReference,
|
||||
other.extensionTypeDeclarationReference,
|
||||
'extensionTypeDeclarationReference');
|
||||
}
|
||||
|
||||
bool checkExtensionType_declaredNullability(
|
||||
EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
|
||||
return visitor.checkValues(node.declaredNullability,
|
||||
other.declaredNullability, 'declaredNullability');
|
||||
}
|
||||
|
||||
bool checkExtensionType_typeArguments(
|
||||
EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
|
||||
return visitor.checkLists(node.typeArguments, other.typeArguments,
|
||||
visitor.checkNodes, 'typeArguments');
|
||||
}
|
||||
|
||||
bool checkIntersectionType_left(EquivalenceVisitor visitor,
|
||||
IntersectionType node, IntersectionType other) {
|
||||
return visitor.checkNodes(node.left, other.left, 'left');
|
||||
|
|
|
@ -23,7 +23,7 @@ class HierarchyBasedTypeEnvironment extends TypeEnvironment {
|
|||
InterfaceType? getTypeAsInstanceOf(
|
||||
InterfaceType type, Class superclass, CoreTypes coreTypes,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
return hierarchy.getTypeAsInstanceOf(type, superclass,
|
||||
return hierarchy.getInterfaceTypeAsInstanceOfClass(type, superclass,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,8 @@ class HierarchyBasedTypeEnvironment extends TypeEnvironment {
|
|||
List<DartType>? getTypeArgumentsAsInstanceOf(
|
||||
InterfaceType type, Class superclass) {
|
||||
if (type.classNode == superclass) return type.typeArguments;
|
||||
return hierarchy.getTypeArgumentsAsInstanceOf(type, superclass);
|
||||
return hierarchy.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
type, superclass);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -925,31 +925,13 @@ mixin StandardBounds {
|
|||
}
|
||||
|
||||
// UP(C<T0, ..., Tn>, C<S0, ..., Sn>) = C<R0,..., Rn> where Ri is UP(Ti, Si)
|
||||
Class? cls;
|
||||
ExtensionTypeDeclaration? extensionTypeDeclaration;
|
||||
List<TypeParameter>? typeParameters;
|
||||
List<DartType>? leftArguments;
|
||||
List<DartType>? rightArguments;
|
||||
if (type1 is InterfaceType && type2 is InterfaceType) {
|
||||
if (type1.classNode == type2.classNode) {
|
||||
cls = type1.classNode;
|
||||
typeParameters = cls.typeParameters;
|
||||
leftArguments = type1.typeArguments;
|
||||
rightArguments = type2.typeArguments;
|
||||
}
|
||||
}
|
||||
if (type1 is ExtensionType && type2 is ExtensionType) {
|
||||
if (type1.extensionTypeDeclaration == type2.extensionTypeDeclaration) {
|
||||
extensionTypeDeclaration = type1.extensionTypeDeclaration;
|
||||
typeParameters = extensionTypeDeclaration.typeParameters;
|
||||
leftArguments = type1.typeArguments;
|
||||
rightArguments = type2.typeArguments;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeParameters != null &&
|
||||
leftArguments != null &&
|
||||
rightArguments != null) {
|
||||
if (type1 is TypeDeclarationType &&
|
||||
type2 is TypeDeclarationType &&
|
||||
type1.typeDeclarationReference == type2.typeDeclarationReference) {
|
||||
TypeDeclaration typeDeclaration = type1.typeDeclaration;
|
||||
List<TypeParameter> typeParameters = typeDeclaration.typeParameters;
|
||||
List<DartType> leftArguments = type1.typeArguments;
|
||||
List<DartType> rightArguments = type2.typeArguments;
|
||||
int n = typeParameters.length;
|
||||
List<DartType> typeArguments = new List<DartType>.of(leftArguments);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
|
@ -970,32 +952,32 @@ mixin StandardBounds {
|
|||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
}
|
||||
}
|
||||
if (cls != null) {
|
||||
return new InterfaceType(
|
||||
cls,
|
||||
uniteNullabilities(
|
||||
type1.declaredNullability, type2.declaredNullability),
|
||||
typeArguments);
|
||||
} else {
|
||||
return new ExtensionType(
|
||||
extensionTypeDeclaration!,
|
||||
uniteNullabilities(
|
||||
type1.declaredNullability, type2.declaredNullability),
|
||||
typeArguments);
|
||||
switch (typeDeclaration) {
|
||||
case Class():
|
||||
return new InterfaceType(
|
||||
typeDeclaration,
|
||||
uniteNullabilities(
|
||||
type1.declaredNullability, type2.declaredNullability),
|
||||
typeArguments);
|
||||
case ExtensionTypeDeclaration():
|
||||
return new ExtensionType(
|
||||
typeDeclaration,
|
||||
uniteNullabilities(
|
||||
type1.declaredNullability, type2.declaredNullability),
|
||||
typeArguments);
|
||||
}
|
||||
}
|
||||
|
||||
// UP(C0<T0, ..., Tn>, C1<S0, ..., Sk>)
|
||||
// = least upper bound of two interfaces as in Dart 1.
|
||||
return _getLegacyLeastUpperBound(type1, type2,
|
||||
return _getLegacyLeastUpperBound(
|
||||
type1 as TypeDeclarationType, type2 as TypeDeclarationType,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
}
|
||||
|
||||
DartType _getLegacyLeastUpperBound(DartType type1, DartType type2,
|
||||
DartType _getLegacyLeastUpperBound(
|
||||
TypeDeclarationType type1, TypeDeclarationType type2,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
assert((type1 is InterfaceType || type1 is ExtensionType) &&
|
||||
(type2 is InterfaceType || type2 is ExtensionType));
|
||||
|
||||
if (type1 is InterfaceType && type2 is InterfaceType) {
|
||||
return hierarchy.getLegacyLeastUpperBound(type1, type2,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
|
|
|
@ -423,13 +423,14 @@ class Types with StandardBounds {
|
|||
InterfaceType? getTypeAsInstanceOf(
|
||||
InterfaceType type, Class superclass, CoreTypes coreTypes,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
return hierarchy.getTypeAsInstanceOf(type, superclass,
|
||||
return hierarchy.getInterfaceTypeAsInstanceOfClass(type, superclass,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
}
|
||||
|
||||
List<DartType>? getTypeArgumentsAsInstanceOf(
|
||||
InterfaceType type, Class superclass) {
|
||||
return hierarchy.getTypeArgumentsAsInstanceOf(type, superclass);
|
||||
return hierarchy.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
type, superclass);
|
||||
}
|
||||
|
||||
List<DartType>? getExtensionTypeArgumentsAsInstanceOfExtensionTypeDeclaration(
|
||||
|
@ -497,8 +498,8 @@ class IsInterfaceSubtypeOf extends TypeRelation<InterfaceType> {
|
|||
if (s.classReference == t.classReference) {
|
||||
asSupertypeArguments = s.typeArguments;
|
||||
} else {
|
||||
asSupertypeArguments =
|
||||
types.hierarchy.getTypeArgumentsAsInstanceOf(s, t.classNode);
|
||||
asSupertypeArguments = types.hierarchy
|
||||
.getInterfaceTypeArgumentsAsInstanceOfClass(s, t.classNode);
|
||||
}
|
||||
if (asSupertypeArguments == null) {
|
||||
return const IsSubtypeOf.never();
|
||||
|
|
|
@ -479,6 +479,14 @@ abstract class Substitution {
|
|||
supertype.classNode.typeParameters, supertype.typeArguments));
|
||||
}
|
||||
|
||||
/// Returns the [Substitution] for the type parameters on the type declaration
|
||||
/// of [type] with the type arguments provided in [type].
|
||||
static Substitution fromTypeDeclarationType(TypeDeclarationType type) {
|
||||
if (type.typeArguments.isEmpty) return _NullSubstitution.instance;
|
||||
return fromMap(new Map<TypeParameter, DartType>.fromIterables(
|
||||
type.typeDeclaration.typeParameters, type.typeArguments));
|
||||
}
|
||||
|
||||
/// Substitutes the type parameters on the class of [type] with the
|
||||
/// type arguments provided in [type].
|
||||
static Substitution fromInterfaceType(InterfaceType type) {
|
||||
|
|
|
@ -256,8 +256,8 @@ class TypeCheckingVisitor
|
|||
}
|
||||
if (type is InterfaceType && typeDeclaration is Class) {
|
||||
// The receiver type should implement the interface declaring the member.
|
||||
List<DartType>? upcastTypeArguments =
|
||||
hierarchy.getTypeArgumentsAsInstanceOf(type, typeDeclaration);
|
||||
List<DartType>? upcastTypeArguments = hierarchy
|
||||
.getInterfaceTypeArgumentsAsInstanceOfClass(type, typeDeclaration);
|
||||
if (upcastTypeArguments != null) {
|
||||
return Substitution.fromPairs(
|
||||
typeDeclaration.typeParameters, upcastTypeArguments);
|
||||
|
@ -940,7 +940,7 @@ class TypeCheckingVisitor
|
|||
hierarchy.getInterfaceMember(iterable.classNode, iteratorName);
|
||||
if (iteratorGetter == null) return const DynamicType();
|
||||
List<DartType> castedIterableArguments =
|
||||
hierarchy.getTypeArgumentsAsInstanceOf(
|
||||
hierarchy.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
iterable, iteratorGetter.enclosingClass!)!;
|
||||
DartType iteratorType = Substitution.fromPairs(
|
||||
iteratorGetter.enclosingClass!.typeParameters,
|
||||
|
@ -951,7 +951,7 @@ class TypeCheckingVisitor
|
|||
hierarchy.getInterfaceMember(iteratorType.classNode, currentName);
|
||||
if (currentGetter == null) return const DynamicType();
|
||||
List<DartType> castedIteratorTypeArguments =
|
||||
hierarchy.getTypeArgumentsAsInstanceOf(
|
||||
hierarchy.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
iteratorType, currentGetter.enclosingClass!)!;
|
||||
return Substitution.fromPairs(
|
||||
currentGetter.enclosingClass!.typeParameters,
|
||||
|
@ -965,7 +965,8 @@ class TypeCheckingVisitor
|
|||
DartType getStreamElementType(DartType stream) {
|
||||
if (stream is InterfaceType) {
|
||||
List<DartType>? asStreamArguments =
|
||||
hierarchy.getTypeArgumentsAsInstanceOf(stream, coreTypes.streamClass);
|
||||
hierarchy.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
stream, coreTypes.streamClass);
|
||||
if (asStreamArguments == null) return const DynamicType();
|
||||
return asStreamArguments.single;
|
||||
}
|
||||
|
@ -1065,7 +1066,8 @@ class TypeCheckingVisitor
|
|||
: coreTypes.iterableClass;
|
||||
DartType type = visitExpression(node.expression);
|
||||
List<DartType>? asContainerArguments = type is InterfaceType
|
||||
? hierarchy.getTypeArgumentsAsInstanceOf(type, container)
|
||||
? hierarchy.getInterfaceTypeArgumentsAsInstanceOfClass(
|
||||
type, container)
|
||||
: null;
|
||||
if (asContainerArguments != null) {
|
||||
checkAssignable(
|
||||
|
|
|
@ -1346,11 +1346,11 @@ class B<T*> extends self::A<self::B::T*, core::bool*> {}
|
|||
|
||||
var b_int = new InterfaceType(b, Nullability.legacy, [int]);
|
||||
expect(
|
||||
hierarchy.getTypeAsInstanceOf(b_int, a,
|
||||
hierarchy.getInterfaceTypeAsInstanceOfClass(b_int, a,
|
||||
isNonNullableByDefault: library.isNonNullableByDefault),
|
||||
new InterfaceType(a, Nullability.legacy, [int, bool]));
|
||||
expect(
|
||||
hierarchy.getTypeAsInstanceOf(b_int, objectClass,
|
||||
hierarchy.getInterfaceTypeAsInstanceOfClass(b_int, objectClass,
|
||||
isNonNullableByDefault: library.isNonNullableByDefault),
|
||||
new InterfaceType(objectClass, Nullability.legacy));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue