Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(708)

Unified Diff: pkg/compiler/lib/src/elements/resolution_types.dart

Issue 2829683007: Extract DartTypeVisitor and subclasses from resolution_types. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/compiler.dart ('k') | pkg/compiler/lib/src/elements/types.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/elements/resolution_types.dart
diff --git a/pkg/compiler/lib/src/elements/resolution_types.dart b/pkg/compiler/lib/src/elements/resolution_types.dart
index 078a1b2805eeb5ce8c48fcc91dd5c65cbb372e8a..016f5c3edf4754269b6552472be56fbc12037c89 100644
--- a/pkg/compiler/lib/src/elements/resolution_types.dart
+++ b/pkg/compiler/lib/src/elements/resolution_types.dart
@@ -161,11 +161,11 @@ abstract class ResolutionDartType implements DartType {
return new TypeDeclarationFormatter().format(this, name);
}
- accept(DartTypeVisitor visitor, var argument);
+ R accept<R, A>(ResolutionDartTypeVisitor<R, A> visitor, A argument);
- void visitChildren(DartTypeVisitor visitor, var argument) {}
+ void visitChildren<R, A>(ResolutionDartTypeVisitor visitor, var argument) {}
- static void visitList(
+ static void visitList<R, A>(
List<ResolutionDartType> types, DartTypeVisitor visitor, var argument) {
for (ResolutionDartType type in types) {
type.accept(visitor, argument);
@@ -239,7 +239,7 @@ class ResolutionTypeVariableType extends ResolutionDartType
f(this);
}
- accept(DartTypeVisitor visitor, var argument) {
+ R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) {
return visitor.visitTypeVariableType(this, argument);
}
@@ -288,7 +288,7 @@ class ResolutionVoidType extends ResolutionDartType implements VoidType {
return this;
}
- accept(DartTypeVisitor visitor, var argument) {
+ R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) {
return visitor.visitVoidType(this, argument);
}
@@ -342,7 +342,7 @@ class MalformedType extends ResolutionDartType {
@override
bool get isMalformed => true;
- accept(DartTypeVisitor visitor, var argument) {
+ R accept<R, A>(ResolutionDartTypeVisitor<R, A> visitor, A argument) {
return visitor.visitMalformedType(this, argument);
}
@@ -548,7 +548,7 @@ class ResolutionInterfaceType extends GenericType<ResolutionInterfaceType>
ResolutionInterfaceType asRaw() => super.asRaw();
- accept(DartTypeVisitor visitor, var argument) {
+ R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) {
return visitor.visitInterfaceType(this, argument);
}
@@ -750,7 +750,7 @@ class ResolutionFunctionType extends ResolutionDartType
});
}
- accept(DartTypeVisitor visitor, var argument) {
+ R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) {
return visitor.visitFunctionType(this, argument);
}
@@ -900,7 +900,7 @@ class ResolutionTypedefType extends GenericType<ResolutionTypedefType> {
ResolutionTypedefType asRaw() => super.asRaw();
- accept(DartTypeVisitor visitor, var argument) {
+ R accept<R, A>(ResolutionDartTypeVisitor<R, A> visitor, A argument) {
return visitor.visitTypedefType(this, argument);
}
}
@@ -923,7 +923,7 @@ class ResolutionDynamicType extends ResolutionDartType implements DynamicType {
List<ResolutionDartType> parameters) =>
this;
- accept(DartTypeVisitor visitor, var argument) {
+ R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) {
return visitor.visitDynamicType(this, argument);
}
@@ -973,42 +973,18 @@ class InterfaceMember implements MemberSignature {
Iterable<Member> get declarations => member.declarations;
}
-abstract class DartTypeVisitor<R, A> {
- const DartTypeVisitor();
-
- R visit(ResolutionDartType type, A argument) => type.accept(this, argument);
-
- R visitVoidType(ResolutionVoidType type, A argument) => null;
-
- R visitTypeVariableType(ResolutionTypeVariableType type, A argument) => null;
-
- R visitFunctionType(ResolutionFunctionType type, A argument) => null;
+abstract class ResolutionDartTypeVisitor<R, A> extends DartTypeVisitor<R, A> {
+ const ResolutionDartTypeVisitor();
R visitMalformedType(MalformedType type, A argument) => null;
- R visitInterfaceType(ResolutionInterfaceType type, A argument) => null;
-
R visitTypedefType(ResolutionTypedefType type, A argument) => null;
-
- R visitDynamicType(ResolutionDynamicType type, A argument) => null;
}
-abstract class BaseDartTypeVisitor<R, A> extends DartTypeVisitor<R, A> {
- const BaseDartTypeVisitor();
-
- R visitType(ResolutionDartType type, A argument);
-
- @override
- R visitVoidType(ResolutionVoidType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitTypeVariableType(ResolutionTypeVariableType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitFunctionType(ResolutionFunctionType type, A argument) =>
- visitType(type, argument);
+abstract class BaseResolutionDartTypeVisitor<R, A>
+ extends BaseDartTypeVisitor<R, A>
+ implements ResolutionDartTypeVisitor<R, A> {
+ const BaseResolutionDartTypeVisitor();
@override
R visitMalformedType(MalformedType type, A argument) =>
@@ -1023,294 +999,66 @@ abstract class BaseDartTypeVisitor<R, A> extends DartTypeVisitor<R, A> {
@override
R visitTypedefType(ResolutionTypedefType type, A argument) =>
visitGenericType(type, argument);
-
- @override
- R visitDynamicType(ResolutionDynamicType type, A argument) =>
- visitType(type, argument);
}
-/**
- * Abstract visitor for determining relations between types.
- */
-abstract class AbstractTypeRelation
- extends BaseDartTypeVisitor<bool, ResolutionDartType> {
- final Resolution resolution;
-
- AbstractTypeRelation(this.resolution);
+/// Abstract visitor for determining relations between types.
+abstract class AbstractTypeRelationMixin
+ implements AbstractTypeRelation, ResolutionDartTypeVisitor<bool, DartType> {
+ Resolution get resolution;
+ @override
CommonElements get commonElements => resolution.commonElements;
- bool visitType(ResolutionDartType t, ResolutionDartType s) {
- throw 'internal error: unknown type kind ${t.kind}';
+ /// Ensures that the super hierarchy of [type] is computed.
+ void ensureResolved(ResolutionInterfaceType type) {
+ // TODO(johnniwinther): Currently needed since literal types like int,
+ // double, bool etc. might not have been resolved yet.
+ type.element.ensureResolved(resolution);
}
- bool visitVoidType(ResolutionVoidType t, ResolutionDartType s) {
- assert(s is! ResolutionVoidType);
- return false;
+ /// Returns the unaliased version of [type].
+ DartType getUnaliased(ResolutionDartType type) {
+ type.computeUnaliased(resolution);
+ return type.unaliased;
}
- bool invalidTypeArguments(ResolutionDartType t, ResolutionDartType s);
-
- bool invalidFunctionReturnTypes(ResolutionDartType t, ResolutionDartType s);
-
- bool invalidFunctionParameterTypes(
- ResolutionDartType t, ResolutionDartType s);
+ @override
+ DartType getTypeVariableBound(TypeVariableElement element) => element.bound;
- bool invalidTypeVariableBounds(
- ResolutionDartType bound, ResolutionDartType s);
+ @override
+ FunctionType getCallType(ResolutionInterfaceType type) => type.callType;
- bool invalidCallableType(ResolutionDartType callType, ResolutionDartType s);
+ @override
+ InterfaceType asInstanceOf(ResolutionInterfaceType type, ClassEntity cls) =>
+ type.asInstanceOf(cls);
/// Handle as dynamic for both subtype and more specific relation to avoid
/// spurious errors from malformed types.
bool visitMalformedType(MalformedType t, ResolutionDartType s) => true;
- bool visitInterfaceType(ResolutionInterfaceType t, ResolutionDartType s) {
- // TODO(johnniwinther): Currently needed since literal types like int,
- // double, bool etc. might not have been resolved yet.
- t.element.ensureResolved(resolution);
-
- bool checkTypeArguments(
- ResolutionInterfaceType instance, ResolutionInterfaceType other) {
- List<ResolutionDartType> tTypeArgs = instance.typeArguments;
- List<ResolutionDartType> sTypeArgs = other.typeArguments;
- assert(tTypeArgs.length == sTypeArgs.length);
- for (int i = 0; i < tTypeArgs.length; i++) {
- if (invalidTypeArguments(tTypeArgs[i], sTypeArgs[i])) {
- return false;
- }
- }
- return true;
- }
-
- if (s is ResolutionInterfaceType) {
- ResolutionInterfaceType instance = t.asInstanceOf(s.element);
- if (instance != null && checkTypeArguments(instance, s)) {
- return true;
- }
- }
-
- if (s == commonElements.functionType && t.element.callType != null) {
- return true;
- } else if (s is ResolutionFunctionType) {
- ResolutionFunctionType callType = t.callType;
- return callType != null && !invalidCallableType(callType, s);
- }
-
- return false;
- }
-
- bool visitFunctionType(ResolutionFunctionType t, ResolutionDartType s) {
- if (s == commonElements.functionType) {
- return true;
- }
- if (s is! ResolutionFunctionType) return false;
- ResolutionFunctionType tf = t;
- ResolutionFunctionType sf = s;
- if (invalidFunctionReturnTypes(tf.returnType, sf.returnType)) {
- return false;
- }
-
- // TODO(johnniwinther): Rewrite the function subtyping to be more readable
- // but still as efficient.
-
- // For the comments we use the following abbreviations:
- // x.p : parameterTypes on [:x:],
- // x.o : optionalParameterTypes on [:x:], and
- // len(xs) : length of list [:xs:].
-
- Iterator<ResolutionDartType> tps = tf.parameterTypes.iterator;
- Iterator<ResolutionDartType> sps = sf.parameterTypes.iterator;
- bool sNotEmpty = sps.moveNext();
- bool tNotEmpty = tps.moveNext();
- tNext() => (tNotEmpty = tps.moveNext());
- sNext() => (sNotEmpty = sps.moveNext());
-
- bool incompatibleParameters() {
- while (tNotEmpty && sNotEmpty) {
- if (invalidFunctionParameterTypes(tps.current, sps.current)) {
- return true;
- }
- tNext();
- sNext();
- }
- return false;
- }
-
- if (incompatibleParameters()) return false;
- if (tNotEmpty) {
- // We must have [: len(t.p) <= len(s.p) :].
- return false;
- }
- if (!sf.namedParameters.isEmpty) {
- // We must have [: len(t.p) == len(s.p) :].
- if (sNotEmpty) {
- return false;
- }
- // Since named parameters are globally ordered we can determine the
- // subset relation with a linear search for [:sf.namedParameters:]
- // within [:tf.namedParameters:].
- List<String> tNames = tf.namedParameters;
- List<ResolutionDartType> tTypes = tf.namedParameterTypes;
- List<String> sNames = sf.namedParameters;
- List<ResolutionDartType> sTypes = sf.namedParameterTypes;
- int tIndex = 0;
- int sIndex = 0;
- while (tIndex < tNames.length && sIndex < sNames.length) {
- if (tNames[tIndex] == sNames[sIndex]) {
- if (invalidFunctionParameterTypes(tTypes[tIndex], sTypes[sIndex])) {
- return false;
- }
- sIndex++;
- }
- tIndex++;
- }
- if (sIndex < sNames.length) {
- // We didn't find all names.
- return false;
- }
- } else {
- // Check the remaining [: s.p :] against [: t.o :].
- tps = tf.optionalParameterTypes.iterator;
- tNext();
- if (incompatibleParameters()) return false;
- if (sNotEmpty) {
- // We must have [: len(t.p) + len(t.o) >= len(s.p) :].
- return false;
- }
- if (!sf.optionalParameterTypes.isEmpty) {
- // Check the remaining [: s.o :] against the remaining [: t.o :].
- sps = sf.optionalParameterTypes.iterator;
- sNext();
- if (incompatibleParameters()) return false;
- if (sNotEmpty) {
- // We didn't find enough parameters:
- // We must have [: len(t.p) + len(t.o) <= len(s.p) + len(s.o) :].
- return false;
- }
- } else {
- if (sNotEmpty) {
- // We must have [: len(t.p) + len(t.o) >= len(s.p) :].
- return false;
- }
- }
- }
- return true;
- }
-
- bool visitTypeVariableType(
- ResolutionTypeVariableType t, ResolutionDartType s) {
- // Identity check is handled in [isSubtype].
- ResolutionDartType bound = t.element.bound;
- if (bound.isTypeVariable) {
- // The bound is potentially cyclic so we need to be extra careful.
- Set<TypeVariableElement> seenTypeVariables =
- new Set<TypeVariableElement>();
- seenTypeVariables.add(t.element);
- while (bound.isTypeVariable) {
- TypeVariableElement element = bound.element;
- if (identical(bound.element, s.element)) {
- // [t] extends [s].
- return true;
- }
- if (seenTypeVariables.contains(element)) {
- // We have a cycle and have already checked all bounds in the cycle
- // against [s] and can therefore conclude that [t] is not a subtype
- // of [s].
- return false;
- }
- seenTypeVariables.add(element);
- bound = element.bound;
- }
- }
- if (invalidTypeVariableBounds(bound, s)) return false;
- return true;
- }
+ bool visitTypedefType(ResolutionTypedefType t, ResolutionDartType s) =>
+ visitType(t, s);
}
-class MoreSpecificVisitor extends AbstractTypeRelation {
- MoreSpecificVisitor(Resolution resolution) : super(resolution);
-
- bool isMoreSpecific(ResolutionDartType t, ResolutionDartType s) {
- if (identical(t, s) || s.treatAsDynamic || t == commonElements.nullType) {
- return true;
- }
- if (t.isVoid || s.isVoid) {
- return false;
- }
- if (t.treatAsDynamic) {
- return false;
- }
- if (s == commonElements.objectType) {
- return true;
- }
- t.computeUnaliased(resolution);
- t = t.unaliased;
- s.computeUnaliased(resolution);
- s = s.unaliased;
-
- return t.accept(this, s);
- }
-
- bool invalidTypeArguments(ResolutionDartType t, ResolutionDartType s) {
- return !isMoreSpecific(t, s);
- }
-
- bool invalidFunctionReturnTypes(ResolutionDartType t, ResolutionDartType s) {
- if (s.treatAsDynamic && t.isVoid) return true;
- return !s.isVoid && !isMoreSpecific(t, s);
- }
-
- bool invalidFunctionParameterTypes(
- ResolutionDartType t, ResolutionDartType s) {
- return !isMoreSpecific(t, s);
- }
-
- bool invalidTypeVariableBounds(
- ResolutionDartType bound, ResolutionDartType s) {
- return !isMoreSpecific(bound, s);
- }
+class ResolutionMoreSpecificVisitor extends MoreSpecificVisitor
+ with AbstractTypeRelationMixin {
+ final Resolution resolution;
- bool invalidCallableType(ResolutionDartType callType, ResolutionDartType s) {
- return !isMoreSpecific(callType, s);
- }
+ ResolutionMoreSpecificVisitor(this.resolution);
}
-/**
- * Type visitor that determines the subtype relation two types.
- */
-class SubtypeVisitor extends MoreSpecificVisitor {
- SubtypeVisitor(Resolution resolution) : super(resolution);
-
- bool isSubtype(ResolutionDartType t, ResolutionDartType s) {
- return t.treatAsDynamic || isMoreSpecific(t, s);
- }
-
- bool isAssignable(ResolutionDartType t, ResolutionDartType s) {
- return isSubtype(t, s) || isSubtype(s, t);
- }
-
- bool invalidTypeArguments(ResolutionDartType t, ResolutionDartType s) {
- return !isSubtype(t, s);
- }
-
- bool invalidFunctionReturnTypes(ResolutionDartType t, ResolutionDartType s) {
- return !s.isVoid && !isAssignable(t, s);
- }
+class ResolutionSubtypeVisitor extends SubtypeVisitor
+ with AbstractTypeRelationMixin {
+ final Resolution resolution;
- bool invalidFunctionParameterTypes(
- ResolutionDartType t, ResolutionDartType s) {
- return !isAssignable(t, s);
- }
+ ResolutionSubtypeVisitor(this.resolution);
+}
- bool invalidTypeVariableBounds(
- ResolutionDartType bound, ResolutionDartType s) {
- return !isSubtype(bound, s);
- }
+class ResolutionPotentialSubtypeVisitor extends PotentialSubtypeVisitor
+ with AbstractTypeRelationMixin {
+ final Resolution resolution;
- bool invalidCallableType(ResolutionDartType callType, ResolutionDartType s) {
- return !isSubtype(callType, s);
- }
+ ResolutionPotentialSubtypeVisitor(this.resolution);
}
/**
@@ -1330,18 +1078,21 @@ abstract class DartTypes {
CommonElements get commonElements;
/// Returns `true` if [t] is a subtype of [s].
- bool isSubtype(ResolutionDartType t, ResolutionDartType s);
+ bool isSubtype(DartType t, DartType s);
+
+ /// Returns `true` if [t] is assignable to [s].
+ bool isAssignable(DartType t, DartType s);
/// Returns `true` if [t] might be a subtype of [s] for some values of
/// type variables in [s] and [t].
- bool isPotentialSubtype(ResolutionDartType t, ResolutionDartType s);
+ bool isPotentialSubtype(DartType t, DartType s);
}
class Types implements DartTypes {
final Resolution resolution;
- final MoreSpecificVisitor moreSpecificVisitor;
- final SubtypeVisitor subtypeVisitor;
- final PotentialSubtypeVisitor potentialSubtypeVisitor;
+ final ResolutionMoreSpecificVisitor moreSpecificVisitor;
+ final ResolutionSubtypeVisitor subtypeVisitor;
+ final ResolutionPotentialSubtypeVisitor potentialSubtypeVisitor;
CommonElements get commonElements => resolution.commonElements;
@@ -1349,9 +1100,11 @@ class Types implements DartTypes {
Types(Resolution resolution)
: this.resolution = resolution,
- this.moreSpecificVisitor = new MoreSpecificVisitor(resolution),
- this.subtypeVisitor = new SubtypeVisitor(resolution),
- this.potentialSubtypeVisitor = new PotentialSubtypeVisitor(resolution);
+ this.moreSpecificVisitor =
+ new ResolutionMoreSpecificVisitor(resolution),
+ this.subtypeVisitor = new ResolutionSubtypeVisitor(resolution),
+ this.potentialSubtypeVisitor =
+ new ResolutionPotentialSubtypeVisitor(resolution);
Types copy(Resolution resolution) {
return new Types(resolution);
@@ -1865,22 +1618,6 @@ class Types implements DartTypes {
}
}
-/**
- * Type visitor that determines one type could a subtype of another given the
- * right type variable substitution. The computation is approximate and returns
- * [:false:] only if we are sure no such substitution exists.
- */
-class PotentialSubtypeVisitor extends SubtypeVisitor {
- PotentialSubtypeVisitor(Resolution resolution) : super(resolution);
-
- bool isSubtype(ResolutionDartType t, ResolutionDartType s) {
- if (t is ResolutionTypeVariableType || s is ResolutionTypeVariableType) {
- return true;
- }
- return super.isSubtype(t, s);
- }
-}
-
/// Visitor used to compute an instantiation of a generic type that is more
/// specific than a given type.
///
@@ -1889,7 +1626,7 @@ class PotentialSubtypeVisitor extends SubtypeVisitor {
/// constraints are too complex or the two types are too different, `false`
/// is returned. Otherwise, the [constraintMap] holds the valid constraints.
class MoreSpecificSubtypeVisitor
- extends BaseDartTypeVisitor<bool, ResolutionDartType> {
+ extends BaseResolutionDartTypeVisitor<bool, ResolutionDartType> {
final Types types;
Map<ResolutionTypeVariableType, ResolutionDartType> constraintMap;
@@ -1979,7 +1716,8 @@ class MoreSpecificSubtypeVisitor
/// Visitor used to print type annotation like they used in the source code.
/// The visitor is especially for printing a function type like
/// `(Foo,[Bar])->Baz` as `Baz m(Foo a1, [Bar a2])`.
-class TypeDeclarationFormatter extends BaseDartTypeVisitor<dynamic, String> {
+class TypeDeclarationFormatter
+ extends BaseResolutionDartTypeVisitor<dynamic, String> {
Set<String> usedNames;
StringBuffer sb;
« no previous file with comments | « pkg/compiler/lib/src/compiler.dart ('k') | pkg/compiler/lib/src/elements/types.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698