Version 2.13.0-135.0.dev Merge commit 'a7e5965495dd60bfe0c6717c416cc133526ca5a3' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json index 36ef5eb..6fffc20 100644 --- a/.dart_tool/package_config.json +++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@ "constraint, update this by running tools/generate_package_config.dart." ], "configVersion": 2, - "generated": "2021-03-09T13:31:13.443396", + "generated": "2021-03-12T09:00:31.497265", "generator": "tools/generate_package_config.dart", "packages": [ {
diff --git a/DEPS b/DEPS index e47320e..318184f 100644 --- a/DEPS +++ b/DEPS
@@ -159,7 +159,7 @@ "test_process_tag": "1.0.3", "term_glyph_rev": "6a0f9b6fb645ba75e7a00a4e20072678327a0347", "test_reflective_loader_rev": "54e930a11c372683792e22bddad79197728c91ce", - "test_rev": "2cd8a4e774439447b01f9d381da020319a9808d8", + "test_rev": "e673623f45d75ccec750d35271b0b4d1423e9fac", "typed_data_tag": "f94fc57b8e8c0e4fe4ff6cfd8290b94af52d3719", "usage_rev": "6c64d9e7b6b3758d06d030efcb5afe20bfc04dde", "vector_math_rev": "0c9f5d68c047813a6dcdeb88ba7a42daddf25025",
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index 5413fb9..b2a37c1 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -7152,6 +7152,13 @@ aliasElement: this, aliasArguments: typeArguments, ); + } else if (type is TypeParameterType) { + return TypeParameterTypeImpl( + element: type.element, + nullabilitySuffix: resultNullability, + aliasElement: this, + aliasArguments: typeArguments, + ); } else { return (type as TypeImpl).withNullability(resultNullability); }
diff --git a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart index 8f1d3e5..e4f5c28 100644 --- a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart +++ b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
@@ -135,6 +135,8 @@ element: type.element, nullabilitySuffix: newNullability ?? type.nullabilitySuffix, promotedBound: newPromotedBound ?? promotedBound, + aliasElement: type.aliasElement, + aliasArguments: type.aliasArguments, ); } @@ -149,6 +151,8 @@ return TypeParameterTypeImpl( element: type.element, nullabilitySuffix: newNullability, + aliasElement: type.aliasElement, + aliasArguments: type.aliasArguments, ); }
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart index 312a064..a1b36a1 100644 --- a/pkg/analyzer/lib/src/dart/element/type.dart +++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -1801,7 +1801,13 @@ required TypeParameterElement element, required this.nullabilitySuffix, this.promotedBound, - }) : super(element); + TypeAliasElement? aliasElement, + List<DartType>? aliasArguments, + }) : super( + element, + aliasElement: aliasElement, + aliasArguments: aliasArguments, + ); @override DartType get bound =>
diff --git a/pkg/analyzer/lib/src/dart/element/type_demotion.dart b/pkg/analyzer/lib/src/dart/element/type_demotion.dart index 92390a4..4b1cc1a 100644 --- a/pkg/analyzer/lib/src/dart/element/type_demotion.dart +++ b/pkg/analyzer/lib/src/dart/element/type_demotion.dart
@@ -38,6 +38,8 @@ return TypeParameterTypeImpl( element: type.element, nullabilitySuffix: newNullability ?? type.nullabilitySuffix, + aliasElement: type.aliasElement, + aliasArguments: type.aliasArguments, ); } }
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart index 383977d..9f484b6 100644 --- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart +++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -744,6 +744,13 @@ aliasElement: aliasElement, aliasArguments: aliasArguments, ); + } else if (type is TypeParameterType) { + return TypeParameterTypeImpl( + element: type.element, + nullabilitySuffix: type.nullabilitySuffix, + aliasElement: aliasElement, + aliasArguments: aliasArguments, + ); } else if (type is VoidType) { // TODO(scheglov) add support for `void` aliasing return type;
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart index 0598c70..ece3d72 100644 --- a/pkg/analyzer/test/src/summary/resynthesize_common.dart +++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -12509,10 +12509,6 @@ withAliasElementArguments: true); } - @FailingTest( - issue: 'https://github.com/dart-lang/sdk/issues/45291', - reason: 'Must be implemented', - ) test_typedef_nonFunction_aliasElement_typeParameterType() async { featureSet = FeatureSets.nonFunctionTypeAliases; var library = await checkLibrary(r'''
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/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart index 45bfd1e..db32bfe 100644 --- a/pkg/dartdev/lib/src/commands/run.dart +++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -243,13 +243,18 @@ class _DebuggingSession { Future<bool> start( String host, String port, bool disableServiceAuthCodes) async { - final serviceInfo = await Service.getInfo(); final ddsSnapshot = (dirname(sdk.dart).endsWith('bin')) ? sdk.ddsSnapshot : absolute(dirname(sdk.dart), 'gen', 'dds.dart.snapshot'); if (!Sdk.checkArtifactExists(ddsSnapshot)) { return false; } + ServiceProtocolInfo serviceInfo = await Service.getInfo(); + // Wait for VM service to publish its connection info. + while (serviceInfo.serverUri == null) { + await Future.delayed(Duration(milliseconds: 10)); + serviceInfo = await Service.getInfo(); + } final process = await Process.start( sdk.dart, [
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/dev_compiler/lib/src/kernel/expression_compiler_worker.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart index 16a64f3..ab5c83e 100644 --- a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart +++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
@@ -684,7 +684,7 @@ ..addOption('sdk-root') ..addOption('asset-server-address') ..addOption('asset-server-port') - ..addOption('module-format') + ..addOption('module-format', defaultsTo: 'amd') ..addFlag('track-widget-creation', defaultsTo: false) ..addFlag('sound-null-safety', defaultsTo: false) ..addFlag('verbose', defaultsTo: false);
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/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart index 1089515..ec0a9bb 100644 --- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart +++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -3340,6 +3340,29 @@ } @override + ExecutionStatus visitIfStatement(IfStatement node) { + Constant condition = evaluate(node.condition); + if (condition is AbortConstant) return new ReturnStatus(condition); + if (condition is BoolConstant) { + if (condition.value) { + return node.then.accept(this); + } else if (node.otherwise != null) { + return node.otherwise.accept(this); + } else { + return const ProceedStatus(); + } + } else { + return new ReturnStatus(exprEvaluator.createErrorConstant( + node.condition, + templateConstEvalInvalidType.withArguments( + condition, + exprEvaluator.typeEnvironment.coreTypes.boolLegacyRawType, + condition.getType(exprEvaluator._staticTypeContext), + exprEvaluator.isNonNullableByDefault))); + } + } + + @override ExecutionStatus visitExpressionStatement(ExpressionStatement node) { Constant value = evaluate(node.expression); if (value is AbortConstant) return new ReturnStatus(value); @@ -3436,7 +3459,12 @@ EvaluationEnvironment.withParent(this._parent); /// Whether the current environment is empty. - bool get isEmpty => _typeVariables.isEmpty && _variables.isEmpty; + bool get isEmpty { + // Since we look up variables in enclosing environment, the environment + // is not empty if its parent is not empty. + if (_parent != null && !_parent.isEmpty) return false; + return _typeVariables.isEmpty && _variables.isEmpty; + } void addTypeParameterValue(TypeParameter parameter, DartType value) { assert(!_typeVariables.containsKey(parameter));
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..35da3d2c 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/testcases/const_functions/const_functions_if_statements.dart b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart new file mode 100644 index 0000000..a4118a3 --- /dev/null +++ b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart
@@ -0,0 +1,75 @@ +// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Tests if statements for const functions. + +import "package:expect/expect.dart"; + +const var1 = ifTest(1); +const var2 = ifTest(2); +const var3 = ifTest(3); +int ifTest(int a) { + if (a == 1) { + return 100; + } else if (a == 2) { + return 200; + } else { + return 300; + } +} + +const one = 1; +const var4 = ifTest2(1); +const var5 = ifTest2(2); +int ifTest2(int a) { + if (a == one) { + return 100; + } else { + return 200; + } +} + +const var6 = ifTest3(1); +const var6_1 = ifTest3(2); +const var6_2 = ifTest3(0); +int ifTest3(int a) { + if (a > 0) { + if (a == 1) return 100; + return 200; + } + return 300; +} + +const var7 = ifTest4(1); +int ifTest4(int a) { + int b = a; + if (a == 1) { + b += a; + if (a % 2 == 1) { + b += a; + } + } else if (a == 2) { + b -= a; + } + + return b; +} + +const var8 = ifTest5(); +int ifTest5() { + var x = 10; + if (true) var x = 20; + return x; +} + +void main() { + Expect.equals(var1, 100); + Expect.equals(var2, 200); + Expect.equals(var3, 300); + Expect.equals(var4, 100); + Expect.equals(var5, 200); + Expect.equals(var6, 100); + Expect.equals(var7, 3); + Expect.equals(var8, 10); +}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.strong.expect b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.strong.expect new file mode 100644 index 0000000..8d0f813 --- /dev/null +++ b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.strong.expect
@@ -0,0 +1,86 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; +import "package:expect/expect.dart" as exp; + +import "package:expect/expect.dart"; + +static const field core::int var1 = #C1; +static const field core::int var2 = #C2; +static const field core::int var3 = #C3; +static const field core::int one = #C4; +static const field core::int var4 = #C1; +static const field core::int var5 = #C2; +static const field core::int var6 = #C1; +static const field core::int var6_1 = #C2; +static const field core::int var6_2 = #C3; +static const field core::int var7 = #C5; +static const field core::int var8 = #C6; +static method ifTest(core::int a) → core::int { + if(a.{core::num::==}(1)) { + return 100; + } + else + if(a.{core::num::==}(2)) { + return 200; + } + else { + return 300; + } +} +static method ifTest2(core::int a) → core::int { + if(a.{core::num::==}(#C4)) { + return 100; + } + else { + return 200; + } +} +static method ifTest3(core::int a) → core::int { + if(a.{core::num::>}(0)) { + if(a.{core::num::==}(1)) + return 100; + return 200; + } + return 300; +} +static method ifTest4(core::int a) → core::int { + core::int b = a; + if(a.{core::num::==}(1)) { + b = b.{core::num::+}(a); + if(a.{core::num::%}(2).{core::num::==}(1)) { + b = b.{core::num::+}(a); + } + } + else + if(a.{core::num::==}(2)) { + b = b.{core::num::-}(a); + } + return b; +} +static method ifTest5() → core::int { + core::int x = 10; + if(true) { + core::int x = 20; + } + return x; +} +static method main() → void { + exp::Expect::equals(#C1, 100); + exp::Expect::equals(#C2, 200); + exp::Expect::equals(#C3, 300); + exp::Expect::equals(#C1, 100); + exp::Expect::equals(#C2, 200); + exp::Expect::equals(#C1, 100); + exp::Expect::equals(#C5, 3); + exp::Expect::equals(#C6, 10); +} + +constants { + #C1 = 100 + #C2 = 200 + #C3 = 300 + #C4 = 1 + #C5 = 3 + #C6 = 10 +}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.strong.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.strong.transformed.expect new file mode 100644 index 0000000..8d0f813 --- /dev/null +++ b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.strong.transformed.expect
@@ -0,0 +1,86 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; +import "package:expect/expect.dart" as exp; + +import "package:expect/expect.dart"; + +static const field core::int var1 = #C1; +static const field core::int var2 = #C2; +static const field core::int var3 = #C3; +static const field core::int one = #C4; +static const field core::int var4 = #C1; +static const field core::int var5 = #C2; +static const field core::int var6 = #C1; +static const field core::int var6_1 = #C2; +static const field core::int var6_2 = #C3; +static const field core::int var7 = #C5; +static const field core::int var8 = #C6; +static method ifTest(core::int a) → core::int { + if(a.{core::num::==}(1)) { + return 100; + } + else + if(a.{core::num::==}(2)) { + return 200; + } + else { + return 300; + } +} +static method ifTest2(core::int a) → core::int { + if(a.{core::num::==}(#C4)) { + return 100; + } + else { + return 200; + } +} +static method ifTest3(core::int a) → core::int { + if(a.{core::num::>}(0)) { + if(a.{core::num::==}(1)) + return 100; + return 200; + } + return 300; +} +static method ifTest4(core::int a) → core::int { + core::int b = a; + if(a.{core::num::==}(1)) { + b = b.{core::num::+}(a); + if(a.{core::num::%}(2).{core::num::==}(1)) { + b = b.{core::num::+}(a); + } + } + else + if(a.{core::num::==}(2)) { + b = b.{core::num::-}(a); + } + return b; +} +static method ifTest5() → core::int { + core::int x = 10; + if(true) { + core::int x = 20; + } + return x; +} +static method main() → void { + exp::Expect::equals(#C1, 100); + exp::Expect::equals(#C2, 200); + exp::Expect::equals(#C3, 300); + exp::Expect::equals(#C1, 100); + exp::Expect::equals(#C2, 200); + exp::Expect::equals(#C1, 100); + exp::Expect::equals(#C5, 3); + exp::Expect::equals(#C6, 10); +} + +constants { + #C1 = 100 + #C2 = 200 + #C3 = 300 + #C4 = 1 + #C5 = 3 + #C6 = 10 +}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.textual_outline.expect b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.textual_outline.expect new file mode 100644 index 0000000..0af1a72 --- /dev/null +++ b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.textual_outline.expect
@@ -0,0 +1,19 @@ +import "package:expect/expect.dart"; + +const var1 = ifTest(1); +const var2 = ifTest(2); +const var3 = ifTest(3); +int ifTest(int a) {} +const one = 1; +const var4 = ifTest2(1); +const var5 = ifTest2(2); +int ifTest2(int a) {} +const var6 = ifTest3(1); +const var6_1 = ifTest3(2); +const var6_2 = ifTest3(0); +int ifTest3(int a) {} +const var7 = ifTest4(1); +int ifTest4(int a) {} +const var8 = ifTest5(); +int ifTest5() {} +void main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.textual_outline_modelled.expect new file mode 100644 index 0000000..5f5b560 --- /dev/null +++ b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@ +import "package:expect/expect.dart"; + +const one = 1; +const var1 = ifTest(1); +const var2 = ifTest(2); +const var3 = ifTest(3); +const var4 = ifTest2(1); +const var5 = ifTest2(2); +const var6 = ifTest3(1); +const var6_1 = ifTest3(2); +const var6_2 = ifTest3(0); +const var7 = ifTest4(1); +const var8 = ifTest5(); +int ifTest(int a) {} +int ifTest2(int a) {} +int ifTest3(int a) {} +int ifTest4(int a) {} +int ifTest5() {} +void main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.weak.expect b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.weak.expect new file mode 100644 index 0000000..8d0f813 --- /dev/null +++ b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.weak.expect
@@ -0,0 +1,86 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; +import "package:expect/expect.dart" as exp; + +import "package:expect/expect.dart"; + +static const field core::int var1 = #C1; +static const field core::int var2 = #C2; +static const field core::int var3 = #C3; +static const field core::int one = #C4; +static const field core::int var4 = #C1; +static const field core::int var5 = #C2; +static const field core::int var6 = #C1; +static const field core::int var6_1 = #C2; +static const field core::int var6_2 = #C3; +static const field core::int var7 = #C5; +static const field core::int var8 = #C6; +static method ifTest(core::int a) → core::int { + if(a.{core::num::==}(1)) { + return 100; + } + else + if(a.{core::num::==}(2)) { + return 200; + } + else { + return 300; + } +} +static method ifTest2(core::int a) → core::int { + if(a.{core::num::==}(#C4)) { + return 100; + } + else { + return 200; + } +} +static method ifTest3(core::int a) → core::int { + if(a.{core::num::>}(0)) { + if(a.{core::num::==}(1)) + return 100; + return 200; + } + return 300; +} +static method ifTest4(core::int a) → core::int { + core::int b = a; + if(a.{core::num::==}(1)) { + b = b.{core::num::+}(a); + if(a.{core::num::%}(2).{core::num::==}(1)) { + b = b.{core::num::+}(a); + } + } + else + if(a.{core::num::==}(2)) { + b = b.{core::num::-}(a); + } + return b; +} +static method ifTest5() → core::int { + core::int x = 10; + if(true) { + core::int x = 20; + } + return x; +} +static method main() → void { + exp::Expect::equals(#C1, 100); + exp::Expect::equals(#C2, 200); + exp::Expect::equals(#C3, 300); + exp::Expect::equals(#C1, 100); + exp::Expect::equals(#C2, 200); + exp::Expect::equals(#C1, 100); + exp::Expect::equals(#C5, 3); + exp::Expect::equals(#C6, 10); +} + +constants { + #C1 = 100 + #C2 = 200 + #C3 = 300 + #C4 = 1 + #C5 = 3 + #C6 = 10 +}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.weak.outline.expect b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.weak.outline.expect new file mode 100644 index 0000000..ee08b4b --- /dev/null +++ b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.weak.outline.expect
@@ -0,0 +1,29 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; + +import "package:expect/expect.dart"; + +static const field core::int var1 = self::ifTest(1); +static const field core::int var2 = self::ifTest(2); +static const field core::int var3 = self::ifTest(3); +static const field core::int one = 1; +static const field core::int var4 = self::ifTest2(1); +static const field core::int var5 = self::ifTest2(2); +static const field core::int var6 = self::ifTest3(1); +static const field core::int var6_1 = self::ifTest3(2); +static const field core::int var6_2 = self::ifTest3(0); +static const field core::int var7 = self::ifTest4(1); +static const field core::int var8 = self::ifTest5(); +static method ifTest(core::int a) → core::int + ; +static method ifTest2(core::int a) → core::int + ; +static method ifTest3(core::int a) → core::int + ; +static method ifTest4(core::int a) → core::int + ; +static method ifTest5() → core::int + ; +static method main() → void + ;
diff --git a/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.weak.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.weak.transformed.expect new file mode 100644 index 0000000..8d0f813 --- /dev/null +++ b/pkg/front_end/testcases/const_functions/const_functions_if_statements.dart.weak.transformed.expect
@@ -0,0 +1,86 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; +import "package:expect/expect.dart" as exp; + +import "package:expect/expect.dart"; + +static const field core::int var1 = #C1; +static const field core::int var2 = #C2; +static const field core::int var3 = #C3; +static const field core::int one = #C4; +static const field core::int var4 = #C1; +static const field core::int var5 = #C2; +static const field core::int var6 = #C1; +static const field core::int var6_1 = #C2; +static const field core::int var6_2 = #C3; +static const field core::int var7 = #C5; +static const field core::int var8 = #C6; +static method ifTest(core::int a) → core::int { + if(a.{core::num::==}(1)) { + return 100; + } + else + if(a.{core::num::==}(2)) { + return 200; + } + else { + return 300; + } +} +static method ifTest2(core::int a) → core::int { + if(a.{core::num::==}(#C4)) { + return 100; + } + else { + return 200; + } +} +static method ifTest3(core::int a) → core::int { + if(a.{core::num::>}(0)) { + if(a.{core::num::==}(1)) + return 100; + return 200; + } + return 300; +} +static method ifTest4(core::int a) → core::int { + core::int b = a; + if(a.{core::num::==}(1)) { + b = b.{core::num::+}(a); + if(a.{core::num::%}(2).{core::num::==}(1)) { + b = b.{core::num::+}(a); + } + } + else + if(a.{core::num::==}(2)) { + b = b.{core::num::-}(a); + } + return b; +} +static method ifTest5() → core::int { + core::int x = 10; + if(true) { + core::int x = 20; + } + return x; +} +static method main() → void { + exp::Expect::equals(#C1, 100); + exp::Expect::equals(#C2, 200); + exp::Expect::equals(#C3, 300); + exp::Expect::equals(#C1, 100); + exp::Expect::equals(#C2, 200); + exp::Expect::equals(#C1, 100); + exp::Expect::equals(#C5, 3); + exp::Expect::equals(#C6, 10); +} + +constants { + #C1 = 100 + #C2 = 200 + #C3 = 300 + #C4 = 1 + #C5 = 3 + #C6 = 10 +}
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
diff --git a/tests/language/const_functions/const_functions_if_statements_test.dart b/tests/language/const_functions/const_functions_if_statements_test.dart new file mode 100644 index 0000000..e4998ee --- /dev/null +++ b/tests/language/const_functions/const_functions_if_statements_test.dart
@@ -0,0 +1,97 @@ +// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Tests if statements for const functions. + +// SharedOptions=--enable-experiment=const-functions + +import "package:expect/expect.dart"; + +const var1 = ifTest(1); +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE +const var2 = ifTest(2); +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE +const var3 = ifTest(3); +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE +int ifTest(int a) { + if (a == 1) { + return 100; + } else if (a == 2) { + return 200; + } else { + return 300; + } +} + +const one = 1; +const var4 = ifTest2(1); +// ^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE +const var5 = ifTest2(2); +// ^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE +int ifTest2(int a) { + if (a == one) { + return 100; + } else { + return 200; + } +} + +const var6 = ifTest3(1); +// ^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE +const var6_1 = ifTest3(2); +// ^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE +const var6_2 = ifTest3(0); +// ^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE +int ifTest3(int a) { + if (a > 0) { + if (a == 1) return 100; + return 200; + } + return 300; +} + +const var7 = ifTest4(1); +// ^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE +int ifTest4(int a) { + int b = a; + if (a == 1) { + b += a; + if (a % 2 == 1) { + b += a; + } + } else if (a == 2) { + b -= a; + } + + return b; +} + +const var8 = ifTest5(); +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE +int ifTest5() { + var x = 10; + if (true) var x = 20; + return x; +} + +void main() { + Expect.equals(var1, 100); + Expect.equals(var2, 200); + Expect.equals(var3, 300); + Expect.equals(var4, 100); + Expect.equals(var5, 200); + Expect.equals(var6, 100); + Expect.equals(var7, 3); + Expect.equals(var8, 10); +}
diff --git a/tools/VERSION b/tools/VERSION index 529971b..ea5a9d5 100644 --- a/tools/VERSION +++ b/tools/VERSION
@@ -27,5 +27,5 @@ MAJOR 2 MINOR 13 PATCH 0 -PRERELEASE 134 +PRERELEASE 135 PRERELEASE_PATCH 0 \ No newline at end of file