[cfe] Move ExtensionType into pkg/kernel/lib/ast.dart
Change-Id: I2e8231dad00accafb09d1ec88416242d3d5815a4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/190483
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/compiler/lib/src/ir/util.dart b/pkg/compiler/lib/src/ir/util.dart
index 44de884..b8c1318 100644
--- a/pkg/compiler/lib/src/ir/util.dart
+++ b/pkg/compiler/lib/src/ir/util.dart
@@ -208,6 +208,11 @@
}
@override
+ bool visitExtensionType(ir.ExtensionType node) {
+ return visitList(node.typeArguments);
+ }
+
+ @override
bool visitFutureOrType(ir.FutureOrType node) {
return visit(node.typeArgument);
}
diff --git a/pkg/compiler/test/helpers/ir_types.dart b/pkg/compiler/test/helpers/ir_types.dart
index 2be57b7..b9745e5 100644
--- a/pkg/compiler/test/helpers/ir_types.dart
+++ b/pkg/compiler/test/helpers/ir_types.dart
@@ -98,6 +98,12 @@
}
@override
+ void visitExtensionType(ir.ExtensionType node, StringBuffer sb) {
+ sb.write(node.extension.name);
+ _writeTypeArguments(node.typeArguments, sb);
+ }
+
+ @override
void visitFutureOrType(ir.FutureOrType node, StringBuffer sb) {
sb.write('FutureOr<');
writeType(node.typeArgument, sb);
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index a1437e9..8bcc7bf 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -2746,6 +2746,10 @@
_emitInterfaceType(type);
@override
+ js_ast.Expression visitExtensionType(ExtensionType type) =>
+ type.onType.accept(this);
+
+ @override
js_ast.Expression visitFutureOrType(FutureOrType type) =>
_normalizeFutureOr(type);
diff --git a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
index b953844..8617f88 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -9,7 +9,6 @@
import '../fasta_codes.dart'
show templateInternalProblemNotFoundIn, templateTypeArgumentMismatch;
-import '../kernel/internal_ast.dart';
import '../scope.dart';
import '../source/source_library_builder.dart';
import '../problems.dart';
diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index 06bdd72..35da3d2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -21,13 +21,9 @@
/// with the same kind of root node.
import 'package:kernel/ast.dart';
-import 'package:kernel/binary/ast_to_binary.dart';
import 'package:kernel/core_types.dart';
-import 'package:kernel/src/assumptions.dart';
import 'package:kernel/src/printer.dart';
-import 'package:kernel/src/text_util.dart';
import 'package:kernel/text/ast_to_text.dart' show Precedence, Printer;
-import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
import '../builder/type_alias_builder.dart';
@@ -54,8 +50,6 @@
import 'inference_visitor.dart';
-import 'type_labeler.dart';
-
/// Computes the return type of a (possibly factory) constructor.
InterfaceType computeConstructorReturnType(
Member constructor, CoreTypes coreTypes) {
@@ -4232,170 +4226,3 @@
}
throw new UnsupportedError("Clone not supported for ${node.runtimeType}.");
}
-
-class ExtensionType extends DartType {
- final Reference extensionName;
-
- @override
- final Nullability declaredNullability;
-
- final List<DartType> typeArguments;
-
- final DartType onType;
-
- ExtensionType(Extension extensionNode, Nullability declaredNullability,
- [List<DartType> typeArguments])
- : this.byReference(extensionNode.reference, declaredNullability,
- typeArguments ?? _defaultTypeArguments(extensionNode));
-
- ExtensionType.byReference(
- this.extensionName, this.declaredNullability, this.typeArguments)
- : assert(declaredNullability != null),
- onType = _computeOnType(extensionName, typeArguments);
-
- Extension get extensionNode => extensionName.asExtension;
-
- @override
- Nullability get nullability {
- return uniteNullabilities(
- declaredNullability, extensionNode.onType.nullability);
- }
-
- static List<DartType> _defaultTypeArguments(Extension extensionNode) {
- if (extensionNode.typeParameters.length == 0) {
- // Avoid allocating a list in this very common case.
- return const <DartType>[];
- } else {
- return new List<DartType>.filled(
- extensionNode.typeParameters.length, const DynamicType());
- }
- }
-
- static DartType _computeOnType(
- Reference extensionName, List<DartType> typeArguments) {
- Extension extensionNode = extensionName.asExtension;
- if (extensionNode.typeParameters.isEmpty) {
- return extensionNode.onType;
- } else {
- assert(extensionNode.typeParameters.length == typeArguments.length);
- return Substitution.fromPairs(extensionNode.typeParameters, typeArguments)
- .substituteType(extensionNode.onType);
- }
- }
-
- @override
- R accept<R>(DartTypeVisitor<R> v) {
- if (v is Printer) {
- // TODO(dmitryas): Move this guarded code into Printer.visitExtensionType
- // when it's available.
- Printer printer = v as Printer;
- printer.writeExtensionReferenceFromReference(extensionName);
- if (typeArguments.isNotEmpty) {
- printer.writeSymbol('<');
- printer.writeList(typeArguments, printer.writeType);
- printer.writeSymbol('>');
- printer.state = Printer.WORD;
- }
- printer.writeNullability(declaredNullability);
- // The following line is needed to supply the return value and make the
- // compiler happy. It should go away once ExtensionType is moved to
- // ast.dart.
- return null;
- } else if (v is BinaryPrinter) {
- // TODO(dmitryas): Remove the following line and implement
- // BinaryPrinter.visitExtensionType when it's available.
- return onType.accept(v);
- } else if (v is TypeLabeler) {
- // TODO(dmitryas): Move this guarded code into
- // TypeLabeler.visitExtensionType when it's available.
- TypeLabeler typeLabeler = v as TypeLabeler;
- typeLabeler.result.add(typeLabeler.nameForEntity(
- extensionNode,
- extensionNode.name,
- extensionNode.enclosingLibrary.importUri,
- extensionNode.enclosingLibrary.fileUri));
- if (typeArguments.isNotEmpty) {
- typeLabeler.result.add("<");
- bool first = true;
- for (DartType typeArg in typeArguments) {
- if (!first) typeLabeler.result.add(", ");
- typeArg.accept(typeLabeler);
- first = false;
- }
- typeLabeler.result.add(">");
- }
- typeLabeler.addNullability(declaredNullability);
- // The following line is needed to supply the return value and make the
- // compiler happy. It should go away once ExtensionType is moved to
- // ast.dart.
- return null;
- }
- // TODO(dmitryas): Change this to `v.visitExtensionType(this)` when
- // ExtensionType is moved to ast.dart.
- return v.defaultDartType(this);
- }
-
- @override
- R accept1<R, A>(DartTypeVisitor1<R, A> v, A arg) {
- // TODO(dmitryas): Change this to `v.visitExtensionType(this, arg)` when
- // ExtensionType is moved to ast.dart.
- return v.defaultDartType(this, arg);
- }
-
- @override
- void visitChildren(Visitor v) {
- // TODO(dmitryas): Uncomment the following line when ExtensionType is moved
- // to ast.dart.
- //extensionNode.acceptReference(v);
- visitList(typeArguments, v);
- }
-
- @override
- bool equals(Object other, Assumptions assumptions) {
- if (identical(this, other)) return true;
- if (other is ExtensionType) {
- if (nullability != other.nullability) return false;
- if (extensionName != other.extensionName) return false;
- if (typeArguments.length != other.typeArguments.length) return false;
- for (int i = 0; i < typeArguments.length; ++i) {
- if (!typeArguments[i].equals(other.typeArguments[i], assumptions)) {
- return false;
- }
- }
- return true;
- } else {
- return false;
- }
- }
-
- @override
- int get hashCode {
- int hash = 0x3fffffff & extensionName.hashCode;
- for (int i = 0; i < typeArguments.length; ++i) {
- hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
- }
- int nullabilityHash = (0x33333333 >> nullability.index) ^ 0x33333333;
- hash = 0x3fffffff & (hash * 31 + (hash ^ nullabilityHash));
- return hash;
- }
-
- @override
- ExtensionType withDeclaredNullability(Nullability declaredNullability) {
- return declaredNullability == this.declaredNullability
- ? this
- : new ExtensionType.byReference(
- extensionName, declaredNullability, typeArguments);
- }
-
- @override
- String toString() {
- return "ExtensionType(${toStringInternal()})";
- }
-
- @override
- void toTextInternal(AstPrinter printer) {
- printer.writeExtensionName(extensionName);
- printer.writeTypeArguments(typeArguments);
- printer.write(nullabilityToString(declaredNullability));
- }
-}
diff --git a/pkg/front_end/lib/src/fasta/kernel/invalid_type.dart b/pkg/front_end/lib/src/fasta/kernel/invalid_type.dart
index b66b0ab..bfaef2c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/invalid_type.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/invalid_type.dart
@@ -9,8 +9,6 @@
import '../type_inference/type_schema.dart';
-import 'internal_ast.dart';
-
/// Check if [type] contains [InvalidType] as its part.
///
/// The helper function is intended for stopping cascading errors because of
@@ -60,6 +58,15 @@
}
@override
+ bool visitExtensionType(
+ ExtensionType node, Set<TypedefType> visitedTypedefs) {
+ for (DartType typeArgument in node.typeArguments) {
+ if (typeArgument.accept1(this, visitedTypedefs)) return true;
+ }
+ return false;
+ }
+
+ @override
bool visitFutureOrType(FutureOrType node, Set<TypedefType> visitedTypedefs) {
return node.typeArgument.accept1(this, visitedTypedefs);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
index ac56037..80f2dcb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -4,23 +4,7 @@
// @dart = 2.9
-import 'package:kernel/ast.dart'
- show
- DartType,
- DartTypeVisitor,
- DynamicType,
- FunctionType,
- FutureOrType,
- InterfaceType,
- InvalidType,
- NamedType,
- NeverType,
- NullType,
- TypeParameter,
- TypeParameterType,
- TypedefType,
- Variance,
- VoidType;
+import 'package:kernel/ast.dart';
import 'package:kernel/type_algebra.dart' show containsTypeVariable;
@@ -1029,24 +1013,37 @@
return false;
}
+ @override
bool visitInvalidType(InvalidType node) => false;
+ @override
bool visitDynamicType(DynamicType node) => false;
+ @override
bool visitVoidType(VoidType node) => false;
+ @override
bool visitNeverType(NeverType node) => false;
+ @override
bool visitNullType(NullType node) => false;
+ @override
bool visitInterfaceType(InterfaceType node) {
return anyTypeVariables(node.typeArguments);
}
+ @override
+ bool visitExtensionType(ExtensionType node) {
+ return anyTypeVariables(node.typeArguments);
+ }
+
+ @override
bool visitFutureOrType(FutureOrType node) {
return node.typeArgument.accept(this);
}
+ @override
bool visitFunctionType(FunctionType node) {
if (anyTypeVariables(node.positionalParameters)) return true;
for (TypeParameter variable in node.typeParameters) {
@@ -1058,8 +1055,10 @@
return false;
}
+ @override
bool visitTypeParameterType(TypeParameterType node) => true;
+ @override
bool visitTypedefType(TypedefType node) {
return anyTypeVariables(node.typeArguments);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart b/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart
index 8735d07..f0e5030 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart
@@ -9,26 +9,7 @@
import 'package:_fe_analyzer_shared/src/parser/parser.dart'
show FormalParameterKind;
-import 'package:kernel/ast.dart'
- show
- Class,
- DartType,
- DartTypeVisitor,
- DynamicType,
- FunctionType,
- FutureOrType,
- InterfaceType,
- InvalidType,
- Library,
- NamedType,
- NeverType,
- NullType,
- TreeNode,
- TypeParameter,
- TypeParameterType,
- Typedef,
- TypedefType,
- VoidType;
+import 'package:kernel/ast.dart';
import '../builder/class_builder.dart';
import '../builder/dynamic_type_declaration_builder.dart';
@@ -131,6 +112,11 @@
}
@override
+ TypeBuilder visitExtensionType(ExtensionType node) {
+ throw "Not implemented";
+ }
+
+ @override
TypeBuilder visitFutureOrType(FutureOrType node) {
TypeBuilder argument = node.typeArgument.accept(this);
return new NamedTypeBuilder(
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
index 0b66c6e..bf845a4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
@@ -6,43 +6,7 @@
import 'dart:convert' show json;
-import 'package:kernel/ast.dart'
- show
- BoolConstant,
- Class,
- Constant,
- ConstantMapEntry,
- DartType,
- DoubleConstant,
- DynamicType,
- Field,
- FunctionType,
- FutureOrType,
- InvalidType,
- InstanceConstant,
- IntConstant,
- InterfaceType,
- Library,
- ListConstant,
- MapConstant,
- NeverType,
- NullConstant,
- NullType,
- Nullability,
- PartialInstantiationConstant,
- Procedure,
- SetConstant,
- StringConstant,
- SymbolConstant,
- TearOffConstant,
- TreeNode,
- Typedef,
- TypedefType,
- TypeLiteralConstant,
- TypeParameter,
- TypeParameterType,
- UnevaluatedConstant,
- VoidType;
+import 'package:kernel/ast.dart';
import 'package:kernel/visitor.dart' show ConstantVisitor, DartTypeVisitor;
@@ -286,6 +250,25 @@
addNullability(node.declaredNullability);
}
+ void visitExtensionType(ExtensionType node) {
+ result.add(nameForEntity(
+ node.extension,
+ node.extension.name,
+ node.extension.enclosingLibrary.importUri,
+ node.extension.enclosingLibrary.fileUri));
+ if (node.typeArguments.isNotEmpty) {
+ result.add("<");
+ bool first = true;
+ for (DartType typeArg in node.typeArguments) {
+ if (!first) result.add(", ");
+ typeArg.accept(this);
+ first = false;
+ }
+ result.add(">");
+ }
+ addNullability(node.declaredNullability);
+ }
+
void defaultConstant(Constant node) {}
void visitNullConstant(NullConstant node) {
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 72483c4..0c4eca9 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -896,7 +896,7 @@
Member targetTearoff;
ProcedureKind targetKind;
for (ExtensionMemberDescriptor descriptor
- in receiverType.extensionNode.members) {
+ in receiverType.extension.members) {
if (descriptor.name == name) {
switch (descriptor.kind) {
case ExtensionMemberKind.Method:
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
index 172476b..bc3f745 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
@@ -17,8 +17,6 @@
import 'package:kernel/src/hierarchy_based_type_environment.dart'
show HierarchyBasedTypeEnvironment;
-import '../kernel/internal_ast.dart' show ExtensionType;
-
import 'standard_bounds.dart' show TypeSchemaStandardBounds;
import 'type_constraint_gatherer.dart' show TypeConstraintGatherer;
@@ -373,7 +371,7 @@
if (coreTypes.isTop(supertype)) {
return const IsSubtypeOf.always();
} else if (supertype is ExtensionType &&
- subtype.extensionNode == supertype.extensionNode) {
+ subtype.extension == supertype.extension) {
assert(subtype.typeArguments.length == supertype.typeArguments.length);
IsSubtypeOf result = const IsSubtypeOf.always();
for (int i = 0; i < subtype.typeArguments.length; ++i) {
@@ -399,7 +397,7 @@
if (coreTypes.isBottom(subtype)) {
return const IsSubtypeOf.always();
} else if (subtype is ExtensionType &&
- subtype.extensionNode == unwrappedSupertype.extensionNode) {
+ subtype.extension == unwrappedSupertype.extension) {
assert(subtype.typeArguments.length ==
unwrappedSupertype.typeArguments.length);
IsSubtypeOf result = const IsSubtypeOf.always();
diff --git a/pkg/front_end/lib/src/testing/id_testing_utils.dart b/pkg/front_end/lib/src/testing/id_testing_utils.dart
index 94c3bfd..68cbf92 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -570,6 +570,16 @@
}
sb.write(nullabilityToText(node.nullability, typeRepresentation));
}
+
+ void visitExtensionType(ExtensionType node) {
+ sb.write(node.extension.name);
+ if (node.typeArguments.isNotEmpty) {
+ sb.write('<');
+ visitList(node.typeArguments);
+ sb.write('>');
+ }
+ sb.write(nullabilityToText(node.declaredNullability, typeRepresentation));
+ }
}
/// Returns `true` if [type] is `Object` from `dart:core`.
diff --git a/pkg/front_end/tool/_fasta/bench_maker.dart b/pkg/front_end/tool/_fasta/bench_maker.dart
index 0cc8476..22732a7 100644
--- a/pkg/front_end/tool/_fasta/bench_maker.dart
+++ b/pkg/front_end/tool/_fasta/bench_maker.dart
@@ -345,6 +345,11 @@
throw "not implemented";
}
+ @override
+ void visitExtensionType(ExtensionType node, StringBuffer sb) {
+ throw "not implemented";
+ }
+
Map<String, dynamic> toJson() {
return <String, dynamic>{
"classes": classes,
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index fe1c348..4ed539a 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -1466,6 +1466,8 @@
@override
R accept1<R, A>(TreeVisitor1<R, A> v, A arg) => v.visitExtension(this, arg);
+ R acceptReference<R>(Visitor<R> v) => v.visitExtensionReference(this);
+
@override
void visitChildren(Visitor v) {
visitList(typeParameters, v);
@@ -11150,6 +11152,123 @@
}
}
+class ExtensionType extends DartType {
+ final Reference extensionReference;
+
+ @override
+ final Nullability declaredNullability;
+
+ final List<DartType> typeArguments;
+
+ final DartType onType;
+
+ ExtensionType(Extension extensionNode, Nullability declaredNullability,
+ [List<DartType>? typeArguments])
+ : this.byReference(extensionNode.reference, declaredNullability,
+ typeArguments ?? _defaultTypeArguments(extensionNode));
+
+ ExtensionType.byReference(
+ this.extensionReference, this.declaredNullability, this.typeArguments)
+ // ignore: unnecessary_null_comparison
+ : assert(declaredNullability != null),
+ onType = _computeOnType(extensionReference, typeArguments);
+
+ Extension get extension => extensionReference.asExtension;
+
+ @override
+ Nullability get nullability {
+ return uniteNullabilities(
+ declaredNullability, extension.onType.nullability);
+ }
+
+ static List<DartType> _defaultTypeArguments(Extension extensionNode) {
+ if (extensionNode.typeParameters.length == 0) {
+ // Avoid allocating a list in this very common case.
+ return const <DartType>[];
+ } else {
+ return new List<DartType>.filled(
+ extensionNode.typeParameters.length, const DynamicType());
+ }
+ }
+
+ static DartType _computeOnType(
+ Reference extensionName, List<DartType> typeArguments) {
+ Extension extensionNode = extensionName.asExtension;
+ if (extensionNode.typeParameters.isEmpty) {
+ return extensionNode.onType;
+ } else {
+ assert(extensionNode.typeParameters.length == typeArguments.length);
+ return Substitution.fromPairs(extensionNode.typeParameters, typeArguments)
+ .substituteType(extensionNode.onType);
+ }
+ }
+
+ @override
+ R accept<R>(DartTypeVisitor<R> v) {
+ return v.visitExtensionType(this);
+ }
+
+ @override
+ R accept1<R, A>(DartTypeVisitor1<R, A> v, A arg) {
+ return v.visitExtensionType(this, arg);
+ }
+
+ @override
+ void visitChildren(Visitor v) {
+ extension.acceptReference(v);
+ visitList(typeArguments, v);
+ }
+
+ @override
+ bool equals(Object other, Assumptions? assumptions) {
+ if (identical(this, other)) return true;
+ if (other is ExtensionType) {
+ if (nullability != other.nullability) return false;
+ if (extensionReference != other.extensionReference) return false;
+ if (typeArguments.length != other.typeArguments.length) return false;
+ for (int i = 0; i < typeArguments.length; ++i) {
+ if (!typeArguments[i].equals(other.typeArguments[i], assumptions)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0x3fffffff & extensionReference.hashCode;
+ for (int i = 0; i < typeArguments.length; ++i) {
+ hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
+ }
+ int nullabilityHash = (0x33333333 >> nullability.index) ^ 0x33333333;
+ hash = 0x3fffffff & (hash * 31 + (hash ^ nullabilityHash));
+ return hash;
+ }
+
+ @override
+ ExtensionType withDeclaredNullability(Nullability declaredNullability) {
+ return declaredNullability == this.declaredNullability
+ ? this
+ : new ExtensionType.byReference(
+ extensionReference, declaredNullability, typeArguments);
+ }
+
+ @override
+ String toString() {
+ return "ExtensionType(${toStringInternal()})";
+ }
+
+ @override
+ void toTextInternal(AstPrinter printer) {
+ printer.writeExtensionName(extensionReference);
+ printer.writeTypeArguments(typeArguments);
+ printer.write(nullabilityToString(declaredNullability));
+ }
+}
+
/// A named parameter in [FunctionType].
class NamedType extends Node implements Comparable<NamedType> {
// Flag used for serialization if [isRequired].
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index bd8343c..0d63926 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -2288,6 +2288,12 @@
}
@override
+ void visitExtensionType(ExtensionType node) {
+ // TODO(dmitryas): Serialize ExtensionType.
+ node.onType.accept(this);
+ }
+
+ @override
void visitFutureOrType(FutureOrType node) {
// TODO(dmitryas): Remove special treatment of FutureOr when the VM supports
// the new encoding: just write the tag.
@@ -2525,6 +2531,11 @@
}
@override
+ void visitExtensionReference(Extension node) {
+ throw new UnsupportedError('serialization of Class references');
+ }
+
+ @override
void visitConstructorReference(Constructor node) {
throw new UnsupportedError('serialization of Constructor references');
}
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
index 6505325..13b791c 100644
--- a/pkg/kernel/lib/src/bounds_checks.dart
+++ b/pkg/kernel/lib/src/bounds_checks.dart
@@ -739,6 +739,21 @@
}
@override
+ int visitExtensionType(ExtensionType node,
+ Map<TypeParameter, Map<DartType, int>> computedVariances) {
+ int result = Variance.unrelated;
+ for (int i = 0; i < node.typeArguments.length; ++i) {
+ result = Variance.meet(
+ result,
+ Variance.combine(
+ node.extension.typeParameters[i].variance,
+ computeVariance(typeParameter, node.typeArguments[i],
+ computedVariances: computedVariances)));
+ }
+ return result;
+ }
+
+ @override
int visitFutureOrType(FutureOrType node,
Map<TypeParameter, Map<DartType, int>> computedVariances) {
return computeVariance(typeParameter, node.typeArgument,
diff --git a/pkg/kernel/lib/src/dart_type_equivalence.dart b/pkg/kernel/lib/src/dart_type_equivalence.dart
index d051caa..08c2009 100644
--- a/pkg/kernel/lib/src/dart_type_equivalence.dart
+++ b/pkg/kernel/lib/src/dart_type_equivalence.dart
@@ -171,6 +171,32 @@
}
@override
+ bool visitExtensionType(ExtensionType node, DartType other) {
+ // First, check Object*, Object?.
+ if (equateTopTypes && coreTypes.isTop(node)) {
+ return coreTypes.isTop(other);
+ }
+
+ if (other is ExtensionType) {
+ if (!_checkAndRegisterNullabilities(
+ node.declaredNullability, other.declaredNullability)) {
+ return false;
+ }
+ if (node.extension != other.extension) {
+ return false;
+ }
+ assert(node.typeArguments.length == other.typeArguments.length);
+ for (int i = 0; i < node.typeArguments.length; ++i) {
+ if (!node.typeArguments[i].accept1(this, other.typeArguments[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @override
bool visitFutureOrType(FutureOrType node, DartType other) {
// First, check FutureOr<dynamic>, FutureOr<Object?>, etc.
if (equateTopTypes && coreTypes.isTop(node)) {
diff --git a/pkg/kernel/lib/src/future_value_type.dart b/pkg/kernel/lib/src/future_value_type.dart
index ab5067b..773c8e7 100644
--- a/pkg/kernel/lib/src/future_value_type.dart
+++ b/pkg/kernel/lib/src/future_value_type.dart
@@ -94,6 +94,12 @@
}
@override
+ DartType visitExtensionType(DartType node, CoreTypes coreTypes) {
+ // Otherwise, for all S, futureValueType(S) = Object?.
+ return coreTypes.objectNullableRawType;
+ }
+
+ @override
DartType visitVoidType(DartType node, CoreTypes coreTypes) {
// futureValueType(void) = void.
return node;
diff --git a/pkg/kernel/lib/src/merge_visitor.dart b/pkg/kernel/lib/src/merge_visitor.dart
index bbc745e..b626fa1 100644
--- a/pkg/kernel/lib/src/merge_visitor.dart
+++ b/pkg/kernel/lib/src/merge_visitor.dart
@@ -175,6 +175,41 @@
}
@override
+ DartType? visitExtensionType(ExtensionType a, DartType b) {
+ if (b is ExtensionType &&
+ a.extension == b.extension &&
+ a.typeArguments.length == b.typeArguments.length) {
+ Nullability? nullability = mergeNullability(a.nullability, b.nullability);
+ if (nullability != null) {
+ return mergeExtensionTypes(a, b, nullability);
+ }
+ }
+ if (b is InvalidType) {
+ return b;
+ }
+ return null;
+ }
+
+ DartType? mergeExtensionTypes(
+ ExtensionType a, ExtensionType b, Nullability nullability) {
+ assert(a.extension == b.extension);
+ assert(a.typeArguments.length == b.typeArguments.length);
+ if (a.typeArguments.isEmpty) {
+ return new ExtensionType(a.extension, nullability);
+ }
+ List<DartType> newTypeArguments =
+ new List<DartType>.filled(a.typeArguments.length, dummyDartType);
+ for (int i = 0; i < a.typeArguments.length; i++) {
+ DartType? newType = a.typeArguments[i].accept1(this, b.typeArguments[i]);
+ if (newType == null) {
+ return null;
+ }
+ newTypeArguments[i] = newType;
+ }
+ return new ExtensionType(a.extension, nullability, newTypeArguments);
+ }
+
+ @override
DartType? visitFutureOrType(FutureOrType a, DartType b) {
if (b is FutureOrType) {
Nullability? nullability = mergeNullability(a.nullability, b.nullability);
diff --git a/pkg/kernel/lib/src/non_null.dart b/pkg/kernel/lib/src/non_null.dart
index 2d908f0..d8b3c73 100644
--- a/pkg/kernel/lib/src/non_null.dart
+++ b/pkg/kernel/lib/src/non_null.dart
@@ -53,6 +53,14 @@
}
@override
+ DartType? visitExtensionType(ExtensionType node) {
+ if (node.declaredNullability == Nullability.nonNullable) {
+ return null;
+ }
+ return node.withDeclaredNullability(Nullability.nonNullable);
+ }
+
+ @override
DartType? visitInvalidType(InvalidType node) => null;
@override
diff --git a/pkg/kernel/lib/src/replacement_visitor.dart b/pkg/kernel/lib/src/replacement_visitor.dart
index b3defb8..a3db97a2 100644
--- a/pkg/kernel/lib/src/replacement_visitor.dart
+++ b/pkg/kernel/lib/src/replacement_visitor.dart
@@ -268,5 +268,35 @@
}
@override
+ DartType? visitExtensionType(ExtensionType node, int variance) {
+ Nullability? newNullability = visitNullability(node);
+ List<DartType>? newTypeArguments = null;
+ for (int i = 0; i < node.typeArguments.length; i++) {
+ DartType? substitution = node.typeArguments[i].accept1(
+ this,
+ Variance.combine(
+ variance, node.extension.typeParameters[i].variance));
+ if (substitution != null) {
+ newTypeArguments ??= node.typeArguments.toList(growable: false);
+ newTypeArguments[i] = substitution;
+ }
+ }
+ return createExtensionType(node, newNullability, newTypeArguments);
+ }
+
+ DartType? createExtensionType(ExtensionType node, Nullability? newNullability,
+ List<DartType>? newTypeArguments) {
+ if (newNullability == null && newTypeArguments == null) {
+ // No nullability or type arguments needed to be substituted.
+ return null;
+ } else {
+ return new ExtensionType(
+ node.extension,
+ newNullability ?? node.nullability,
+ newTypeArguments ?? node.typeArguments);
+ }
+ }
+
+ @override
DartType? defaultDartType(DartType node, int variance) => null;
}
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 6aa0dc8..fe66446 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -2436,6 +2436,17 @@
writeNullability(node.nullability);
}
+ visitExtensionType(ExtensionType node) {
+ writeExtensionReferenceFromReference(node.extensionReference);
+ if (node.typeArguments.isNotEmpty) {
+ writeSymbol('<');
+ writeList(node.typeArguments, writeType);
+ writeSymbol('>');
+ state = Printer.WORD;
+ }
+ writeNullability(node.declaredNullability);
+ }
+
visitFutureOrType(FutureOrType node) {
writeWord('FutureOr');
writeSymbol('<');
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 0976e98..ebf18f2 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -675,6 +675,10 @@
return node.typeArguments.any(visit);
}
+ bool visitExtensionType(ExtensionType node) {
+ return node.typeArguments.any(visit);
+ }
+
bool visitFutureOrType(FutureOrType node) {
return visit(node.typeArgument);
}
@@ -727,6 +731,10 @@
return node.typeArguments.any(visit);
}
+ bool visitExtensionType(ExtensionType node) {
+ return node.typeArguments.any(visit);
+ }
+
bool visitFutureOrType(FutureOrType node) {
return visit(node.typeArgument);
}
@@ -782,6 +790,10 @@
return node.typeArguments.any(visit);
}
+ bool visitExtensionType(ExtensionType node) {
+ return node.typeArguments.any(visit);
+ }
+
bool visitFutureOrType(FutureOrType node) {
return visit(node.typeArgument);
}
@@ -881,6 +893,11 @@
}
@override
+ bool visitExtensionType(ExtensionType node) {
+ return node.typeArguments.isEmpty;
+ }
+
+ @override
bool visitInvalidType(InvalidType node) {
throw new UnsupportedError(
"Unsupported operation: _PrimitiveTypeVerifier(InvalidType).");
@@ -950,6 +967,11 @@
}
@override
+ DartType visitExtensionType(ExtensionType node, CoreTypes coreTypes) {
+ return node.withDeclaredNullability(Nullability.nonNullable);
+ }
+
+ @override
DartType visitInvalidType(InvalidType node, CoreTypes coreTypes) => node;
@override
@@ -1163,6 +1185,13 @@
}
@override
+ bool visitExtensionType(ExtensionType node) {
+ assert(node.declaredNullability != Nullability.undetermined);
+ return node.declaredNullability == Nullability.nullable ||
+ node.declaredNullability == Nullability.legacy;
+ }
+
+ @override
bool visitInvalidType(InvalidType node) => false;
@override
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index f4afa00..11032aa 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -529,6 +529,7 @@
R visitTypedefType(TypedefType node) => defaultDartType(node);
R visitNeverType(NeverType node) => defaultDartType(node);
R visitNullType(NullType node) => defaultDartType(node);
+ R visitExtensionType(ExtensionType node) => defaultDartType(node);
}
abstract class DartTypeVisitor1<R, T> {
@@ -545,6 +546,7 @@
R visitTypedefType(TypedefType node, T arg) => defaultDartType(node, arg);
R visitNeverType(NeverType node, T arg) => defaultDartType(node, arg);
R visitNullType(NullType node, T arg) => defaultDartType(node, arg);
+ R visitExtensionType(ExtensionType node, T arg) => defaultDartType(node, arg);
}
/// Visitor for [Constant] nodes.
@@ -783,6 +785,7 @@
R visitTypedefType(TypedefType node) => defaultDartType(node);
R visitNeverType(NeverType node) => defaultDartType(node);
R visitNullType(NullType node) => defaultDartType(node);
+ R visitExtensionType(ExtensionType node) => defaultDartType(node);
// Constants
R defaultConstant(Constant node) => defaultNode(node);
@@ -807,6 +810,8 @@
R visitTypedefReference(Typedef node);
+ R visitExtensionReference(Extension node);
+
// Constant references
R defaultConstantReference(Constant node);
@@ -906,6 +911,9 @@
R? visitTypedefReference(Typedef node) => null;
@override
+ R? visitExtensionReference(Extension node) => null;
+
+ @override
R? defaultConstantReference(Constant node) => null;
@override
@@ -924,6 +932,9 @@
void visitTypedefReference(Typedef node) {}
@override
+ void visitExtensionReference(Extension node) {}
+
+ @override
void defaultConstantReference(Constant node) {}
@override
@@ -944,6 +955,9 @@
R visitTypedefReference(Typedef node) => defaultValue;
@override
+ R visitExtensionReference(Extension node) => defaultValue;
+
+ @override
R defaultConstantReference(Constant node) => defaultValue;
@override