Version 2.14.0-341.0.dev
Merge commit 'be212c94ae5b7b0999650a29a83f4be3d6a8c6d1' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 546ad7a..c3b657c 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -797,7 +797,7 @@
"name": "webkit_inspection_protocol",
"rootUri": "../third_party/pkg/webkit_inspection_protocol",
"packageUri": "lib/",
- "languageVersion": "2.0"
+ "languageVersion": "2.12"
},
{
"name": "yaml",
diff --git a/DEPS b/DEPS
index a11c660..f498427 100644
--- a/DEPS
+++ b/DEPS
@@ -73,7 +73,7 @@
# Revisions of /third_party/* dependencies.
"args_rev": "d8fea36c10ef96797be02e3d132d572445cd86f4",
- "async_rev": "8193eac211905cf33ae1f514022fdbd843836be5",
+ "async_rev": "25a7e2ec39c03622b86918cb9ce3e7d00dd283d1",
"bazel_worker_rev": "0885637b037979afbf5bcd05fd748b309fd669c0",
"benchmark_harness_rev": "c546dbd9f639f75cd2f75de8df2eb9f8ea15e8e7",
"boolean_selector_rev": "665e6921ab246569420376f827bff4585dff0b14",
@@ -103,7 +103,7 @@
# and land the review.
#
# For more details, see https://github.com/dart-lang/sdk/issues/30164
- "dart_style_rev": "9d9dff90d9a2e0793ad2f795f36c2777f720eda0",
+ "dart_style_rev": "06bfd19593ed84dd288f67e02c6a753e6516288a",
"dartdoc_rev" : "c9621b92c738ec21a348cc2de032858276e9c774",
"devtools_rev" : "64cffbed6366329ad05e44d48fa2298367643bb6",
@@ -146,7 +146,7 @@
"resource_rev": "6b79867d0becf5395e5819a75720963b8298e9a7",
"root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
"rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
- "shelf_static_rev": "fb6b7d0ee4ad936a84e503ae6b3703cc99e61d52",
+ "shelf_static_rev": "202ec1a53c9a830c17cf3b718d089cf7eba568ad",
"shelf_packages_handler_rev": "78302e67c035047e6348e692b0c1182131f0fe35",
"shelf_proxy_tag": "v1.0.0",
"shelf_rev": "46483f896cc4308ee3d8e997030ae799b72aa16a",
@@ -174,7 +174,7 @@
"web_socket_channel_rev": "6448ce532445a8a458fa191d9346df071ae0acad",
"WebCore_rev": "fb11e887f77919450e497344da570d780e078bc8",
"webdev_rev": "b0aae7b6944d484722e6af164abedd864a2a0afa",
- "webkit_inspection_protocol_rev": "6b15729292d030f2e5c5861022da4c5a4c11961c",
+ "webkit_inspection_protocol_rev": "dd6fb5d8b536e19cedb384d0bbf1f5631923f1e8",
"yaml_rev": "b4c4411631bda556ce9a45af1ab0eecaf9f3ac53",
"zlib_rev": "bf44340d1b6be1af8950bbdf664fec0cf5a831cc",
"crashpad_rev": "bf327d8ceb6a669607b0dbab5a83a275d03f99ed",
diff --git a/build/fuchsia/dart.cmx b/build/fuchsia/dart.cmx
index d57d9ac..0bd0e668 100644
--- a/build/fuchsia/dart.cmx
+++ b/build/fuchsia/dart.cmx
@@ -1,27 +1,28 @@
{
- "program": {
- "binary": "exe.stripped/dart"
- },
- "sandbox": {
- "features": [
- "config-data",
- "deprecated-ambient-replace-as-executable",
- "root-ssl-certificates",
- "isolated-cache-storage",
- "isolated-persistent-storage",
- "isolated-temp"
- ],
- "services": [
- "fuchsia.deprecatedtimezone.Timezone",
- "fuchsia.device.NameProvider",
- "fuchsia.feedback.CrashReporter",
- "fuchsia.intl.PropertyProvider",
- "fuchsia.logger.LogSink",
- "fuchsia.net.NameLookup",
- "fuchsia.posix.socket.Provider",
- "fuchsia.sysmem.Allocator",
- "fuchsia.timezone.Timezone",
- "fuchsia.tracing.provider.Registry"
- ]
- }
+ "program": {
+ "binary": "exe.stripped/dart"
+ },
+ "sandbox": {
+ "features": [
+ "config-data",
+ "deprecated-ambient-replace-as-executable",
+ "isolated-cache-storage",
+ "isolated-persistent-storage",
+ "isolated-temp",
+ "root-ssl-certificates"
+ ],
+ "services": [
+ "fuchsia.deprecatedtimezone.Timezone",
+ "fuchsia.device.NameProvider",
+ "fuchsia.feedback.CrashReporter",
+ "fuchsia.intl.PropertyProvider",
+ "fuchsia.logger.LogSink",
+ "fuchsia.net.NameLookup",
+ "fuchsia.net.name.Lookup",
+ "fuchsia.posix.socket.Provider",
+ "fuchsia.sysmem.Allocator",
+ "fuchsia.timezone.Timezone",
+ "fuchsia.tracing.provider.Registry"
+ ]
+ }
}
diff --git a/pkg/analysis_server/lib/src/cider/rename.dart b/pkg/analysis_server/lib/src/cider/rename.dart
index 6ea1b32..71e8148 100644
--- a/pkg/analysis_server/lib/src/cider/rename.dart
+++ b/pkg/analysis_server/lib/src/cider/rename.dart
@@ -2,6 +2,8 @@
// 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.
+import 'package:analysis_server/src/services/correction/status.dart';
+import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/line_info.dart';
@@ -17,6 +19,14 @@
CanRenameResponse(this.lineInfo, this.refactoringElement, this.oldName);
}
+class CheckNameResponse {
+ final LineInfo lineInfo;
+ final RefactoringStatus status;
+ final String oldName;
+
+ CheckNameResponse(this.lineInfo, this.status, this.oldName);
+}
+
class CiderRenameComputer {
final FileResolver _fileResolver;
@@ -51,6 +61,32 @@
return null;
}
+ CheckNameResponse? checkNewName(String filePath, int line, int column, String name) {
+ var resolvedUnit = _fileResolver.resolve(path: filePath);
+ var lineInfo = resolvedUnit.lineInfo;
+ var offset = lineInfo.getOffsetOfLine(line) + column;
+
+ var node = NodeLocator(offset).searchWithin(resolvedUnit.unit);
+ var element = getElementOfNode(node);
+
+ if (node == null || element == null) {
+ return null;
+ }
+
+ RefactoringStatus? status;
+ if (element is LocalVariableElement) {
+ status = validateVariableName(name);
+ } else if (element is ParameterElement) {
+ status = validateParameterName(name);
+ } else if (element is FunctionElement) {
+ status = validateFunctionName(name);
+ }
+ if (status == null){
+ return null;
+ }
+ return CheckNameResponse(lineInfo, status, element.displayName);
+ }
+
bool _canRenameElement(Element element) {
if (element is PropertyAccessorElement) {
element = element.variable;
diff --git a/pkg/analysis_server/test/src/cider/rename_test.dart b/pkg/analysis_server/test/src/cider/rename_test.dart
index 31c96d5..028aaea 100644
--- a/pkg/analysis_server/test/src/cider/rename_test.dart
+++ b/pkg/analysis_server/test/src/cider/rename_test.dart
@@ -107,6 +107,65 @@
expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
+ void test_checkName_function() {
+ var result = _checkName(r'''
+int ^foo() => 2;
+''', 'bar');
+
+ expect(result, isNotNull);
+ expect(result?.status.problems.length, 0);
+ expect(result?.oldName, 'foo');
+ }
+
+ void test_checkName_local() {
+ var result = _checkName(r'''
+void foo() {
+ var ^a = 0; var b = a + 1;
+}
+''', 'bar');
+
+ expect(result, isNotNull);
+ expect(result?.status.problems.length, 0);
+ expect(result?.oldName, 'a');
+ }
+
+ void test_checkName_local_invalid() {
+ var result = _checkName(r'''
+void foo() {
+ var ^a = 0; var b = a + 1;
+}
+''', 'Aa');
+
+ expect(result, isNotNull);
+ expect(result?.status.problems.length, 1);
+ expect(result?.oldName, 'a');
+ }
+
+ void test_checkName_parameter() {
+ var result = _checkName(r'''
+void foo(String ^a) {
+ var b = a + 1;
+}
+''', 'bar');
+
+ expect(result, isNotNull);
+ expect(result?.status.problems.length, 0);
+ expect(result?.oldName, 'a');
+ }
+
+ CheckNameResponse? _checkName(String content, String newName) {
+ _updateFile(content);
+
+ return CiderRenameComputer(
+ fileResolver,
+ ).checkNewName(
+ convertPath(testPath),
+ _correctionContext.line,
+ _correctionContext.character,
+ newName,
+ );
+ }
+
CanRenameResponse? _compute(String content) {
_updateFile(content);
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 771756b..57ecf0f 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
library dart2js.cmdline.options;
/// Commandline flags used in `dart2js.dart` and/or `apiimpl.dart`.
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index dc97091..5859d8e 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
// TODO(johnniwinther): Add a test that ensure that this library doesn't depend
// on the dart2js internals.
library compiler.src.kernel.dart2js_target;
@@ -78,9 +80,7 @@
@override
final String name;
- final CompilerOptions options;
-
- Map<String, ir.Class> _nativeClasses;
+ final CompilerOptions? options;
Dart2jsTarget(this.name, this.flags, {this.options});
@@ -89,7 +89,7 @@
@override
int get enabledLateLowerings =>
- (options != null && options.experimentLateInstanceVariables)
+ (options != null && options!.experimentLateInstanceVariables)
? LateLowering.none
: _enabledLateLowerings;
@@ -111,7 +111,7 @@
int get enabledConstructorTearOffLowerings => ConstructorTearOffLowering.none;
@override
- List<String> get extraRequiredLibraries => _requiredLibraries[name];
+ List<String> get extraRequiredLibraries => _requiredLibraries[name]!;
@override
List<String> get extraIndexedLibraries => const [
@@ -151,12 +151,12 @@
CoreTypes coreTypes,
ClassHierarchy hierarchy,
List<ir.Library> libraries,
- Map<String, String> environmentDefines,
+ Map<String, String>? environmentDefines,
DiagnosticReporter diagnosticReporter,
- ReferenceFromIndex referenceFromIndex,
- {void logger(String msg),
- ChangedStructureNotifier changedStructureNotifier}) {
- _nativeClasses ??= JsInteropChecks.getNativeClasses(component);
+ ReferenceFromIndex? referenceFromIndex,
+ {void Function(String msg)? logger,
+ ChangedStructureNotifier? changedStructureNotifier}) {
+ var nativeClasses = JsInteropChecks.getNativeClasses(component);
var jsUtilOptimizer = JsUtilOptimizer(coreTypes, hierarchy);
for (var library in libraries) {
// TODO (rileyporter): Merge js_util optimizations with other lowerings
@@ -165,7 +165,7 @@
JsInteropChecks(
coreTypes,
diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,
- _nativeClasses)
+ nativeClasses)
.visitLibrary(library);
}
lowering.transformLibraries(libraries, coreTypes, hierarchy, options);
@@ -192,7 +192,7 @@
}
return new ir.StaticInvocation(
coreTypes.index
- .getTopLevelMember('dart:core', '_createInvocationMirror'),
+ .getTopLevelProcedure('dart:core', '_createInvocationMirror'),
new ir.Arguments(<ir.Expression>[
new ir.StringLiteral(name)..fileOffset = offset,
new ir.ListLiteral(
@@ -282,7 +282,7 @@
@override
final bool supportsUnevaluatedConstants;
- const Dart2jsConstantsBackend({this.supportsUnevaluatedConstants});
+ const Dart2jsConstantsBackend({required this.supportsUnevaluatedConstants});
@override
NumberSemantics get numberSemantics => NumberSemantics.js;
diff --git a/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart b/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
index 246429e..1d24a30 100644
--- a/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
+++ b/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
const int invocationMirrorMethodKind = 0;
const int invocationMirrorGetterKind = 1;
const int invocationMirrorSetterKind = 2;
diff --git a/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart b/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart
index ebc00ae..87ad9f3 100644
--- a/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
import 'package:kernel/kernel.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart';
@@ -26,10 +28,6 @@
TreeNode transformStaticInvocation(
StaticInvocation invocation, Member contextMember) {
final target = invocation.target;
- if (target == null) {
- return invocation;
- }
-
final transformer = transformers[target];
if (transformer != null) {
return transformer(invocation, contextMember);
diff --git a/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
index 210bbcb..212aac6 100644
--- a/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/type_algebra.dart';
@@ -11,9 +13,9 @@
class _Reader {
final Procedure _procedure;
final FunctionType _type;
- FunctionType _typeWithoutTypeParameters;
+ late final FunctionType _typeWithoutTypeParameters;
- _Reader(this._procedure) : _type = _procedure.getterType {
+ _Reader(this._procedure) : _type = _procedure.getterType as FunctionType {
_typeWithoutTypeParameters = _type.withoutTypeParameters;
}
}
@@ -31,7 +33,8 @@
// Each map contains the mapping from late local variables to cells for a
// given function scope. All late local variables are lowered to cells.
- final List<Map<VariableDeclaration, VariableDeclaration>> _variableCells = [];
+ final List<Map<VariableDeclaration, VariableDeclaration>?> _variableCells =
+ [];
// Uninitialized late static fields are lowered to cells.
final Map<Field, Field> _fieldCells = {};
@@ -44,9 +47,9 @@
// [Reference] to its [Field].
final Map<Procedure, Field> _getterToField = {};
- Member _contextMember;
+ Member? _contextMember;
- LateLowering(this._coreTypes, CompilerOptions _options)
+ LateLowering(this._coreTypes, CompilerOptions? _options)
: _omitLateNames = _options?.omitLateNames ?? false,
_lowerInstanceVariables =
_options?.experimentLateInstanceVariables ?? false,
@@ -55,7 +58,7 @@
_readInitialized = _Reader(_coreTypes.initializedCellRead),
_readInitializedFinal = _Reader(_coreTypes.initializedCellReadFinal);
- Nullability get nonNullable => _contextMember.enclosingLibrary.nonNullable;
+ Nullability get nonNullable => _contextMember!.enclosingLibrary.nonNullable;
bool _shouldLowerVariable(VariableDeclaration variable) => variable.isLate;
@@ -73,7 +76,7 @@
String _mangleFieldName(Field field) {
assert(_shouldLowerInstanceField(field));
- Class cls = field.parent;
+ Class cls = field.enclosingClass!;
return '_#${cls.name}#${field.name.text}';
}
@@ -81,7 +84,7 @@
List<Reference> additionalExports = library.additionalExports;
Set<Reference> newExports = {};
additionalExports.removeWhere((Reference reference) {
- Field cell = _fieldCells[reference.node];
+ Field? cell = _fieldCells[reference.node];
if (cell == null) return false;
newExports.add(cell.getterReference);
return true;
@@ -123,7 +126,7 @@
Arguments([name, initializer])..fileOffset = fileOffset)
..fileOffset = fileOffset;
- StringLiteral _nameLiteral(String name, int fileOffset) =>
+ StringLiteral _nameLiteral(String? name, int fileOffset) =>
StringLiteral(name ?? '')..fileOffset = fileOffset;
InstanceInvocation _callReader(
@@ -138,7 +141,8 @@
interfaceTarget: procedure,
functionType:
Substitution.fromPairs(reader._type.typeParameters, typeArguments)
- .substituteType(reader._typeWithoutTypeParameters))
+ .substituteType(reader._typeWithoutTypeParameters)
+ as FunctionType)
..fileOffset = fileOffset;
}
@@ -161,7 +165,7 @@
_variableCells.removeLast();
}
- VariableDeclaration _lookupVariableCell(VariableDeclaration variable) {
+ VariableDeclaration? _lookupVariableCell(VariableDeclaration variable) {
assert(_shouldLowerVariable(variable));
for (final scope in _variableCells) {
if (scope == null) continue;
@@ -190,7 +194,7 @@
VariableDeclaration _uninitializedVariableCell(VariableDeclaration variable) {
assert(_shouldLowerUninitializedVariable(variable));
int fileOffset = variable.fileOffset;
- String name = variable.name;
+ String? name = variable.name;
final cell = VariableDeclaration(name,
initializer:
_callCellConstructor(_nameLiteral(name, fileOffset), fileOffset),
@@ -213,11 +217,11 @@
VariableDeclaration _initializedVariableCell(VariableDeclaration variable) {
assert(_shouldLowerInitializedVariable(variable));
int fileOffset = variable.fileOffset;
- String name = variable.name;
+ String? name = variable.name;
final cell = VariableDeclaration(name,
initializer: _callInitializedCellConstructor(
_nameLiteral(name, fileOffset),
- _initializerClosure(variable.initializer, variable.type),
+ _initializerClosure(variable.initializer!, variable.type),
fileOffset),
type: InterfaceType(_coreTypes.initializedCellClass, nonNullable),
isFinal: true)
@@ -226,7 +230,7 @@
}
TreeNode transformVariableDeclaration(
- VariableDeclaration variable, Member contextMember) {
+ VariableDeclaration variable, Member? contextMember) {
_contextMember = contextMember;
if (!_shouldLowerVariable(variable)) return variable;
@@ -309,8 +313,8 @@
Name name = field.name;
String nameText = name.text;
DartType type = field.type;
- Expression initializer = field.initializer;
- Class enclosingClass = field.enclosingClass;
+ Expression? initializer = field.initializer;
+ Class enclosingClass = field.enclosingClass!;
Name mangledName = Name(_mangleFieldName(field), field.enclosingLibrary);
Field backingField = Field.mutable(mangledName,
@@ -436,7 +440,7 @@
VariableGet setterValueRead() =>
VariableGet(setterValue)..fileOffset = fileOffset;
- Statement setterBody() {
+ Statement? setterBody() {
if (!field.isFinal) {
// The lowered setter for `late T field;` and `late T field = e;` is
//
@@ -470,7 +474,7 @@
}
}
- Statement body = setterBody();
+ Statement? body = setterBody();
if (body != null) {
Procedure setter = Procedure(
name,
@@ -506,17 +510,14 @@
// getter for the backing field.
// TODO(fishythefish): Clean this up when [FieldInitializer] maintains a
// correct [Reference] to its [Field].
- NamedNode node = initializer.fieldReference.node;
- assert(node != null);
+ NamedNode node = initializer.fieldReference.node!;
Field backingField;
if (node is Field) {
if (!_shouldLowerInstanceField(node)) return initializer;
backingField = _backingInstanceField(node);
} else {
- backingField = _getterToField[node];
+ backingField = _getterToField[node]!;
}
- assert(backingField != null);
-
return FieldInitializer(backingField, initializer.value)
..fileOffset = initializer.fileOffset;
}
diff --git a/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart b/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart
index c315199..7df3d66 100644
--- a/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
@@ -26,11 +28,11 @@
ListFactorySpecializer(this.coreTypes, this.hierarchy)
: _listGenerateFactory =
- coreTypes.index.getMember('dart:core', 'List', 'generate'),
+ coreTypes.index.getProcedure('dart:core', 'List', 'generate'),
_arrayAllocateFixedFactory = coreTypes.index
- .getMember('dart:_interceptors', 'JSArray', 'allocateFixed'),
+ .getProcedure('dart:_interceptors', 'JSArray', 'allocateFixed'),
_arrayAllocateGrowableFactory = coreTypes.index
- .getMember('dart:_interceptors', 'JSArray', 'allocateGrowable'),
+ .getProcedure('dart:_interceptors', 'JSArray', 'allocateGrowable'),
_jsArrayClass =
coreTypes.index.getClass('dart:_interceptors', 'JSArray'),
_intClass = coreTypes.index.getClass('dart:core', 'int') {
@@ -42,17 +44,14 @@
});
}
- Procedure _intPlus;
- Procedure get intPlus =>
- _intPlus ??= hierarchy.getInterfaceMember(_intClass, Name('+'));
+ late final Procedure intPlus =
+ hierarchy.getInterfaceMember(_intClass, Name('+')) as Procedure;
- Procedure _intLess;
- Procedure get intLess =>
- _intLess ??= hierarchy.getInterfaceMember(_intClass, Name('<'));
+ late final Procedure intLess =
+ hierarchy.getInterfaceMember(_intClass, Name('<')) as Procedure;
- Procedure _jsArrayIndexSet;
- Procedure get jsArrayIndexSet => _jsArrayIndexSet ??=
- hierarchy.getInterfaceMember(_jsArrayClass, Name('[]='));
+ late final Procedure jsArrayIndexSet =
+ hierarchy.getInterfaceMember(_jsArrayClass, Name('[]=')) as Procedure;
/// Replace calls to `List.generate(length, (i) => e)` with an expansion
///
@@ -74,7 +73,7 @@
assert(args.positional.length == 2);
final length = args.positional[0];
final generator = args.positional[1];
- final bool growable =
+ final bool? growable =
_getConstantNamedOptionalArgument(args, 'growable', true);
if (growable == null) return node;
@@ -90,18 +89,18 @@
// If the length is a constant, use the constant directly so that the
// inferrer can see the constant length.
- int /*?*/ lengthConstant = _getLengthArgument(args);
- VariableDeclaration lengthVariable;
+ int? lengthConstant = _getLengthArgument(args);
+ VariableDeclaration? lengthVariable;
Expression getLength() {
if (lengthConstant != null) return IntLiteral(lengthConstant);
lengthVariable ??= VariableDeclaration('_length',
initializer: length, isFinal: true, type: intType)
..fileOffset = node.fileOffset;
- return VariableGet(lengthVariable)..fileOffset = node.fileOffset;
+ return VariableGet(lengthVariable!)..fileOffset = node.fileOffset;
}
- TreeNode allocation = StaticInvocation(
+ Expression allocation = StaticInvocation(
growable ? _arrayAllocateGrowableFactory : _arrayAllocateFixedFactory,
Arguments(
[getLength()],
@@ -122,11 +121,8 @@
initializer: IntLiteral(0),
type: intType,
)..fileOffset = node.fileOffset;
- indexVariable.fileOffset = (generator as FunctionExpression)
- .function
- .positionalParameters
- .first
- .fileOffset;
+ indexVariable.fileOffset =
+ generator.function.positionalParameters.first.fileOffset;
final loop = ForStatement(
// initializers: _i = 0
@@ -138,7 +134,7 @@
Name('<'),
Arguments([getLength()]),
interfaceTarget: intLess,
- functionType: intLess.getterType,
+ functionType: intLess.getterType as FunctionType,
),
// updates: _i++
[
@@ -164,7 +160,7 @@
return BlockExpression(
Block([
- if (lengthVariable != null) lengthVariable,
+ if (lengthVariable != null) lengthVariable!,
listVariable,
loop,
]),
@@ -185,7 +181,7 @@
/// Returns constant value of the first argument in [args], or null if it is
/// not a constant.
- int /*?*/ _getLengthArgument(Arguments args) {
+ int? _getLengthArgument(Arguments args) {
if (args.positional.length < 1) return null;
final value = args.positional.first;
if (value is IntLiteral) {
@@ -202,7 +198,7 @@
/// Returns constant value of the only named optional argument in [args], or
/// null if it is not a bool constant. Returns [defaultValue] if optional
/// argument is not passed. Argument is asserted to have the given [name].
- bool /*?*/ _getConstantNamedOptionalArgument(
+ bool? _getConstantNamedOptionalArgument(
Arguments args, String name, bool defaultValue) {
if (args.named.isEmpty) {
return defaultValue;
@@ -224,15 +220,15 @@
/// Choose a name for the `_list` temporary. If the `List.generate` expression
/// is an initializer for a variable, use that name so that dart2js can try to
/// use one JavaScript variable with the source name for 'both' variables.
- String _listNameFromContext(Expression node) {
- TreeNode parent = node.parent;
+ String? _listNameFromContext(Expression node) {
+ TreeNode? parent = node.parent;
if (parent is VariableDeclaration) return parent.name;
return '_list';
}
String _indexNameFromContext(FunctionExpression generator) {
final function = generator.function;
- String /*?*/ candidate = function.positionalParameters.first.name;
+ String? candidate = function.positionalParameters.first.name;
if (candidate == null || candidate == '' || candidate == '_') return '_i';
return candidate;
}
@@ -246,8 +242,8 @@
final int constructorFileOffset;
final VariableDeclaration listVariable;
final FunctionNode function;
- VariableDeclaration argument;
- VariableDeclaration parameter;
+ late final VariableDeclaration argument;
+ late final VariableDeclaration parameter;
int functionNestingLevel = 0;
ListGenerateLoopBodyInliner(this.listFactorySpecializer,
@@ -298,7 +294,7 @@
}
Statement run() {
- final body = cloneInContext(function.body);
+ Statement body = cloneInContext(function.body!);
return Block([parameter, body]);
}
@@ -335,9 +331,11 @@
value,
]),
interfaceTarget: listFactorySpecializer.jsArrayIndexSet,
- functionType: Substitution.fromInterfaceType(listVariable.type)
- .substituteType(
- listFactorySpecializer.jsArrayIndexSet.getterType))
+ functionType:
+ Substitution.fromInterfaceType(listVariable.type as InterfaceType)
+ .substituteType(
+ listFactorySpecializer.jsArrayIndexSet.getterType)
+ as FunctionType)
..isInvariant = true
..isBoundsSafe = true
..fileOffset = constructorFileOffset,
@@ -355,7 +353,7 @@
@override
VariableDeclaration getVariableClone(VariableDeclaration variable) {
- VariableDeclaration clone = super.getVariableClone(variable);
+ VariableDeclaration? clone = super.getVariableClone(variable);
return clone ?? variable;
}
}
diff --git a/pkg/compiler/lib/src/kernel/transformations/lowering.dart b/pkg/compiler/lib/src/kernel/transformations/lowering.dart
index e9cad5b..e04314b 100644
--- a/pkg/compiler/lib/src/kernel/transformations/lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/lowering.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
@@ -16,7 +18,7 @@
/// Each transformation is applied locally to AST nodes of certain types after
/// transforming children nodes.
void transformLibraries(List<Library> libraries, CoreTypes coreTypes,
- ClassHierarchy hierarchy, CompilerOptions options) {
+ ClassHierarchy hierarchy, CompilerOptions? options) {
final transformer = _Lowering(coreTypes, hierarchy, options);
libraries.forEach(transformer.visitLibrary);
@@ -31,10 +33,10 @@
final FactorySpecializer factorySpecializer;
final LateLowering _lateLowering;
- Member _currentMember;
+ Member? _currentMember;
_Lowering(
- CoreTypes coreTypes, ClassHierarchy hierarchy, CompilerOptions _options)
+ CoreTypes coreTypes, ClassHierarchy hierarchy, CompilerOptions? _options)
: factorySpecializer = FactorySpecializer(coreTypes, hierarchy),
_lateLowering = LateLowering(coreTypes, _options);
@@ -51,7 +53,7 @@
@override
TreeNode visitStaticInvocation(StaticInvocation node) {
node.transformChildren(this);
- return factorySpecializer.transformStaticInvocation(node, _currentMember);
+ return factorySpecializer.transformStaticInvocation(node, _currentMember!);
}
@override
@@ -71,37 +73,37 @@
@override
TreeNode visitVariableGet(VariableGet node) {
node.transformChildren(this);
- return _lateLowering.transformVariableGet(node, _currentMember);
+ return _lateLowering.transformVariableGet(node, _currentMember!);
}
@override
TreeNode visitVariableSet(VariableSet node) {
node.transformChildren(this);
- return _lateLowering.transformVariableSet(node, _currentMember);
+ return _lateLowering.transformVariableSet(node, _currentMember!);
}
@override
TreeNode visitField(Field node) {
_currentMember = node;
node.transformChildren(this);
- return _lateLowering.transformField(node, _currentMember);
+ return _lateLowering.transformField(node, _currentMember!);
}
@override
TreeNode visitFieldInitializer(FieldInitializer node) {
node.transformChildren(this);
- return _lateLowering.transformFieldInitializer(node, _currentMember);
+ return _lateLowering.transformFieldInitializer(node, _currentMember!);
}
@override
TreeNode visitStaticGet(StaticGet node) {
node.transformChildren(this);
- return _lateLowering.transformStaticGet(node, _currentMember);
+ return _lateLowering.transformStaticGet(node, _currentMember!);
}
@override
TreeNode visitStaticSet(StaticSet node) {
node.transformChildren(this);
- return _lateLowering.transformStaticSet(node, _currentMember);
+ return _lateLowering.transformStaticSet(node, _currentMember!);
}
}
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index c5288eb..a710db6 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
library dart2js.src.options;
import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
@@ -32,8 +34,8 @@
class FeatureOption {
final String flag;
final bool isNegativeFlag;
- bool _state;
- bool get isEnabled => _state;
+ bool? _state;
+ bool get isEnabled => _state!;
bool get isDisabled => !isEnabled;
void set state(bool value) {
assert(_state == null);
@@ -67,10 +69,10 @@
FeatureOption newHolders = FeatureOption('new-holders');
/// [FeatureOption]s which default to enabled.
- List<FeatureOption> shipping;
+ late final List<FeatureOption> shipping = [legacyJavaScript];
/// [FeatureOption]s which default to disabled.
- List<FeatureOption> canary;
+ late final List<FeatureOption> canary = [newHolders];
/// Forces canary feature on. This must run after [Option].parse.
void forceCanary() {
@@ -79,12 +81,6 @@
}
}
- // Initialize feature lists.
- FeatureOptions() {
- shipping = [legacyJavaScript];
- canary = [newHolders];
- }
-
void parse(List<String> options) {
_extractFeatures(options, shipping, FeatureStatus.shipping);
_extractFeatures(options, canary, FeatureStatus.canary);
@@ -122,12 +118,12 @@
/// as few as possible.
class CompilerOptions implements DiagnosticOptions {
/// The entry point of the application that is being compiled.
- Uri entryPoint;
+ Uri? entryPoint;
/// Location of the package configuration file.
///
/// If not null then [packageRoot] should be null.
- Uri packageConfig;
+ Uri? packageConfig;
/// List of kernel files to load.
///
@@ -140,18 +136,18 @@
/// At this time, this list points to full kernel files. In the future, we may
/// use a list of outline files for modular compiles, and only use full kernel
/// files for linking.
- List<Uri> dillDependencies;
+ List<Uri>? dillDependencies;
/// Location from which serialized inference data is read.
///
/// If this is set, the [entryPoint] is expected to be a .dill file and the
/// frontend work is skipped.
- Uri readDataUri;
+ Uri? readDataUri;
/// Location to which inference data is serialized.
///
/// If this is set, the compilation stops after type inference.
- Uri writeDataUri;
+ Uri? writeDataUri;
/// Serialize data without the closed world.
/// TODO(joshualitt) make this the default right after landing in Google3 and
@@ -162,22 +158,22 @@
///
/// If this is set, the [entryPoint] is expected to be a .dill file and the
/// frontend work is skipped.
- Uri readClosedWorldUri;
+ Uri? readClosedWorldUri;
/// Location to which inference data is serialized.
///
/// If this is set, the compilation stops after computing the closed world.
- Uri writeClosedWorldUri;
+ Uri? writeClosedWorldUri;
/// Location from which codegen data is read.
///
/// If this is set, the compilation starts at codegen enqueueing.
- Uri readCodegenUri;
+ Uri? readCodegenUri;
/// Location to which codegen data is serialized.
///
/// If this is set, the compilation stops after code generation.
- Uri writeCodegenUri;
+ Uri? writeCodegenUri;
/// Whether to run only the CFE and emit the generated kernel file in
/// [outputUri].
@@ -205,7 +201,7 @@
explicitExperimentalFlags: explicitExperimentalFlags);
/// A possibly null state object for kernel compilation.
- fe.InitializedCompilerState kernelInitializedCompilerState;
+ fe.InitializedCompilerState? kernelInitializedCompilerState;
/// Whether we allow mocking compilation of libraries such as dart:io and
/// dart:html for unit testing purposes.
@@ -230,11 +226,11 @@
/// Location where to generate a map containing details of how deferred
/// libraries are subdivided.
- Uri deferredMapUri;
+ Uri? deferredMapUri;
/// Location where to generate an internal format representing the deferred
/// graph.
- Uri deferredGraphUri;
+ Uri? deferredGraphUri;
/// The maximum number of deferred fragments to generate. If the number of
/// fragments exceeds this amount, then they may be merged.
@@ -242,8 +238,8 @@
/// will not merge fragments with unrelated dependencies and thus we may
/// generate more fragments than the 'mergeFragmentsThreshold' under some
/// situations.
- int mergeFragmentsThreshold = null; // default value, no max.
- int _mergeFragmentsThreshold;
+ int? mergeFragmentsThreshold = null; // default value, no max.
+ int? _mergeFragmentsThreshold;
/// Whether to disable inlining during the backend optimizations.
// TODO(sigmund): negate, so all flags are positive
@@ -276,7 +272,7 @@
/// Diagnostic option: List of packages for which warnings and hints are
/// reported. If `null`, no package warnings or hints are reported. If
/// empty, all warnings and hints are reported.
- List<String> shownPackageWarnings; // &&&&&
+ List<String>? shownPackageWarnings;
/// Whether to disable global type inference.
bool disableTypeInference = false;
@@ -304,7 +300,7 @@
/// If set, SSA intermediate form is dumped for methods with names matching
/// this RegExp pattern.
- String dumpSsaPattern = null;
+ String? dumpSsaPattern = null;
/// Whether we allow passing an extra argument to `assert`, containing a
/// reason for why an assertion fails. (experimental)
@@ -354,19 +350,19 @@
bool generateSourceMap = true;
/// URI of the main output of the compiler.
- Uri outputUri;
+ Uri? outputUri;
/// Location of the libraries specification file.
- Uri librariesSpecificationUri;
+ Uri? librariesSpecificationUri;
/// Location of the kernel platform `.dill` files.
- Uri platformBinaries;
+ Uri? platformBinaries;
/// Whether to print legacy types as T* rather than T.
bool printLegacyStars = false;
/// URI where the compiler should generate the output source map file.
- Uri sourceMapUri;
+ Uri? sourceMapUri;
/// The compiler is run from the build bot.
bool testMode = false;
@@ -387,29 +383,29 @@
/// What should the compiler do with parameter type assertions.
///
/// This is an internal configuration option derived from other flags.
- CheckPolicy defaultParameterCheckPolicy;
+ late CheckPolicy defaultParameterCheckPolicy;
/// What should the compiler do with implicit downcasts.
///
/// This is an internal configuration option derived from other flags.
- CheckPolicy defaultImplicitDowncastCheckPolicy;
+ late CheckPolicy defaultImplicitDowncastCheckPolicy;
/// What the compiler should do with a boolean value in a condition context
/// when the language specification says it is a runtime error for it to be
/// null.
///
/// This is an internal configuration option derived from other flags.
- CheckPolicy defaultConditionCheckPolicy;
+ late CheckPolicy defaultConditionCheckPolicy;
/// What should the compiler do with explicit casts.
///
/// This is an internal configuration option derived from other flags.
- CheckPolicy defaultExplicitCastCheckPolicy;
+ late CheckPolicy defaultExplicitCastCheckPolicy;
/// What should the compiler do with List index bounds checks.
///
/// This is an internal configuration option derived from other flags.
- CheckPolicy defaultIndexBoundsCheckPolicy;
+ late CheckPolicy defaultIndexBoundsCheckPolicy;
/// Whether to generate code compliant with content security policy (CSP).
bool useContentSecurityPolicy = false;
@@ -492,14 +488,14 @@
}
/// If specified, a bundle of optimizations to enable (or disable).
- int optimizationLevel = null;
+ int? optimizationLevel = null;
/// The shard to serialize when using [writeCodegenUri].
- int codegenShard;
+ int? codegenShard;
/// The number of shards to serialize when using [writeCodegenUri] or to
/// deserialize when using [readCodegenUri].
- int codegenShards;
+ int? codegenShards;
/// Arguments passed to the front end about how it is invoked.
///
@@ -515,7 +511,7 @@
/// Verbosity level used for filtering messages during compilation.
fe.Verbosity verbosity = fe.Verbosity.all;
- FeatureOptions features;
+ late FeatureOptions features;
// -------------------------------------------------
// Options for deprecated features
@@ -523,11 +519,11 @@
/// Create an options object by parsing flags from [options].
static CompilerOptions parse(List<String> options,
- {FeatureOptions featureOptions,
- Uri librariesSpecificationUri,
- Uri platformBinaries,
- void Function(String) onError,
- void Function(String) onWarning}) {
+ {FeatureOptions? featureOptions,
+ Uri? librariesSpecificationUri,
+ Uri? platformBinaries,
+ void Function(String)? onError,
+ void Function(String)? onWarning}) {
if (featureOptions == null) featureOptions = FeatureOptions();
featureOptions.parse(options);
Map<fe.ExperimentalFlag, bool> explicitExperimentalFlags =
@@ -545,7 +541,7 @@
..benchmarkingExperiment =
_hasOption(options, Flags.benchmarkingExperiment)
..buildId =
- _extractStringOption(options, '--build-id=', _UNDETERMINED_BUILD_ID)
+ _extractStringOption(options, '--build-id=', _UNDETERMINED_BUILD_ID)!
..compileForServer = _hasOption(options, Flags.serverMode)
..deferredMapUri = _extractUriOption(options, '--deferred-map=')
..deferredGraphUri =
@@ -638,11 +634,11 @@
.._mergeFragmentsThreshold =
_extractIntOption(options, '${Flags.mergeFragmentsThreshold}=')
..cfeInvocationModes = fe.InvocationMode.parseArguments(
- _extractStringOption(options, '${Flags.cfeInvocationModes}=', ''),
+ _extractStringOption(options, '${Flags.cfeInvocationModes}=', '')!,
onError: onError)
..verbosity = fe.Verbosity.parseArgument(
_extractStringOption(
- options, '${Flags.verbosity}=', fe.Verbosity.defaultValue),
+ options, '${Flags.verbosity}=', fe.Verbosity.defaultValue)!,
onError: onError)
..features = featureOptions;
}
@@ -654,7 +650,7 @@
if (librariesSpecificationUri == null) {
throw new ArgumentError("[librariesSpecificationUri] is null.");
}
- if (librariesSpecificationUri.path.endsWith('/')) {
+ if (librariesSpecificationUri!.path.endsWith('/')) {
throw new ArgumentError(
"[librariesSpecificationUri] should be a file: $librariesSpecificationUri");
}
@@ -697,12 +693,12 @@
disableTypeInference = true;
disableRtiOptimization = true;
}
- if (optimizationLevel >= 2) {
+ if (optimizationLevel! >= 2) {
enableMinification = true;
laxRuntimeTypeToString = true;
omitLateNames = true;
}
- if (optimizationLevel >= 3) {
+ if (optimizationLevel! >= 3) {
omitImplicitChecks = true;
}
if (optimizationLevel == 4) {
@@ -752,7 +748,7 @@
/// Returns `true` if warnings and hints are shown for all packages.
@override
bool get showAllPackageWarnings {
- return shownPackageWarnings != null && shownPackageWarnings.isEmpty;
+ return shownPackageWarnings != null && shownPackageWarnings!.isEmpty;
}
/// Returns `true` if warnings and hints are hidden for all packages.
@@ -767,7 +763,7 @@
}
if (shownPackageWarnings != null) {
return uri.scheme == 'package' &&
- shownPackageWarnings.contains(uri.pathSegments.first);
+ shownPackageWarnings!.contains(uri.pathSegments.first);
}
return false;
}
@@ -794,8 +790,8 @@
'isEmitted=$isEmitted)';
}
-String _extractStringOption(
- List<String> options, String prefix, String defaultValue) {
+String? _extractStringOption(
+ List<String> options, String prefix, String? defaultValue) {
for (String option in options) {
if (option.startsWith(prefix)) {
return option.substring(prefix.length);
@@ -804,13 +800,13 @@
return defaultValue;
}
-Uri _extractUriOption(List<String> options, String prefix) {
- String option = _extractStringOption(options, prefix, null);
+Uri? _extractUriOption(List<String> options, String prefix) {
+ String? option = _extractStringOption(options, prefix, null);
return (option == null) ? null : Uri.parse(option);
}
-int _extractIntOption(List<String> options, String prefix) {
- String option = _extractStringOption(options, prefix, null);
+int? _extractIntOption(List<String> options, String prefix) {
+ String? option = _extractStringOption(options, prefix, null);
return (option == null) ? null : int.parse(option);
}
@@ -821,7 +817,7 @@
/// Extract list of comma separated values provided for [flag]. Returns an
/// empty list if [option] contain [flag] without arguments. Returns `null` if
/// [option] doesn't contain [flag] with or without arguments.
-List<String> _extractOptionalCsvOption(List<String> options, String flag) {
+List<String>? _extractOptionalCsvOption(List<String> options, String flag) {
String prefix = '$flag=';
for (String option in options) {
if (option == flag) {
@@ -837,15 +833,15 @@
/// Extract list of comma separated Uris provided for [flag]. Returns an
/// empty list if [option] contain [flag] without arguments. Returns `null` if
/// [option] doesn't contain [flag] with or without arguments.
-List<Uri> _extractUriListOption(List<String> options, String flag) {
- List<String> stringUris = _extractOptionalCsvOption(options, flag);
+List<Uri>? _extractUriListOption(List<String> options, String flag) {
+ List<String>? stringUris = _extractOptionalCsvOption(options, flag);
if (stringUris == null) return null;
return stringUris.map(Uri.parse).toList();
}
Map<fe.ExperimentalFlag, bool> _extractExperiments(List<String> options,
- {void Function(String) onError, void Function(String) onWarning}) {
- List<String> experiments =
+ {void Function(String)? onError, void Function(String)? onWarning}) {
+ List<String>? experiments =
_extractOptionalCsvOption(options, Flags.enableLanguageExperiments);
onError ??= (String error) => throw new ArgumentError(error);
onWarning ??= (String warning) => print(warning);
diff --git a/pkg/compiler/lib/src/util/indentation.dart b/pkg/compiler/lib/src/util/indentation.dart
index fb7cc21..d792f2f 100644
--- a/pkg/compiler/lib/src/util/indentation.dart
+++ b/pkg/compiler/lib/src/util/indentation.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
part of dart2js.util;
/// Indentation utility class. Should be used as a mixin in most cases.
@@ -64,7 +66,7 @@
String popTag() {
assert(!tagStack.isEmpty);
String tag = tagStack.head;
- tagStack = tagStack.tail;
+ tagStack = tagStack.tail!;
indentLess();
return tag;
}
@@ -81,7 +83,7 @@
/// The method "opens" the node, meaning that all output after calling
/// this method and before calling closeNode() will represent contents
/// of given node.
- void openNode(N node, String type, [Map params]) {
+ void openNode(N node, String type, [Map? params]) {
if (params == null) params = new Map();
addCurrentIndent();
sb.write("<");
@@ -92,7 +94,7 @@
}
/// Adds given node to result string.
- void openAndCloseNode(N node, String type, [Map params]) {
+ void openAndCloseNode(N node, String type, [Map? params]) {
if (params == null) params = {};
addCurrentIndent();
sb.write("<");
@@ -110,7 +112,7 @@
sb.write(">\n");
}
- void addTypeWithParams(String type, [Map params]) {
+ void addTypeWithParams(String type, [Map? params]) {
if (params == null) params = new Map();
sb.write("${type}");
params.forEach((k, v) {
diff --git a/pkg/compiler/lib/src/util/util.dart b/pkg/compiler/lib/src/util/util.dart
index 3a9949d..703bf10 100644
--- a/pkg/compiler/lib/src/util/util.dart
+++ b/pkg/compiler/lib/src/util/util.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
library dart2js.util;
import 'package:front_end/src/api_unstable/dart2js.dart'
@@ -45,13 +47,13 @@
}
/// Mix the bits of `object.hashCode` with [existing].
- static int objectHash(Object object, [int existing = 0]) {
+ static int objectHash(Object? object, [int existing = 0]) {
return mixHashCodeBits(existing, object.hashCode);
}
/// Mix the bits of `.hashCode` all non-null objects.
- static int objectsHash(Object obj1,
- [Object obj2, Object obj3, Object obj4, Object obj5]) {
+ static int objectsHash(Object? obj1,
+ [Object? obj2, Object? obj3, Object? obj4, Object? obj5]) {
int hash = 0;
if (obj5 != null) hash = objectHash(obj5, hash);
if (obj4 != null) hash = objectHash(obj4, hash);
@@ -61,7 +63,7 @@
}
/// Mix the bits of the element hash codes of [list] with [existing].
- static int listHash(List list, [int existing = 0]) {
+ static int listHash(List? list, [int existing = 0]) {
int h = existing;
if (list != null) {
int length = list.length;
@@ -73,7 +75,7 @@
}
/// Mix the bits of the element hash codes of [iterable] with [existing].
- static int setHash<E>(Iterable<E> iterable, [int existing = 0]) {
+ static int setHash<E>(Iterable<E>? iterable, [int existing = 0]) {
int h = existing;
if (iterable != null) {
for (E e in iterable) {
@@ -111,7 +113,7 @@
}
}
-bool identicalElements<E>(List<E> a, List<E> b) {
+bool identicalElements<E>(List<E>? a, List<E>? b) {
if (identical(a, b)) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
@@ -123,7 +125,7 @@
return true;
}
-bool equalElements<E>(List<E> a, List<E> b) {
+bool equalElements<E>(List<E>? a, List<E>? b) {
if (identical(a, b)) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
@@ -135,13 +137,13 @@
return true;
}
-bool equalSets<E>(Set<E> a, Set<E> b) {
+bool equalSets<E>(Set<E>? a, Set<E>? b) {
if (identical(a, b)) return true;
if (a == null || b == null) return false;
return a.length == b.length && a.containsAll(b) && b.containsAll(a);
}
-bool equalMaps<K, V>(Map<K, V> a, Map<K, V> b) {
+bool equalMaps<K, V>(Map<K, V>? a, Map<K, V>? b) {
if (identical(a, b)) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
@@ -153,7 +155,7 @@
/// File name prefix used to shorten the file name in stack traces printed by
/// [trace].
-String stackTraceFilePrefix = null;
+String? stackTraceFilePrefix = null;
/// Writes the characters of [string] on [buffer]. The characters
/// are escaped as suitable for JavaScript and JSON. [buffer] is
diff --git a/pkg/dartdev/test/commands/format_test.dart b/pkg/dartdev/test/commands/format_test.dart
index 82e68d2..568f3ce 100644
--- a/pkg/dartdev/test/commands/format_test.dart
+++ b/pkg/dartdev/test/commands/format_test.dart
@@ -2,6 +2,7 @@
// 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.
+import 'dart:convert';
import 'dart:io';
import 'package:test/test.dart';
@@ -98,4 +99,16 @@
startsWith('No file or directory found at "$unknownFilePath".'));
expect(result.stdout, startsWith('Formatted no files in '));
});
+
+ test('formats from stdin and exits', () async {
+ p = project(mainSrc: 'int get foo => 1;\n');
+ var process = await p.start(['format']);
+ process.stdin.writeln('main( ) { }');
+
+ var result = process.stdout.reduce((a, b) => a + b);
+
+ await process.stdin.close();
+ expect(await process.exitCode, 0);
+ expect(utf8.decode(await result), 'main() {}\n');
+ });
}
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
index 1e1f94d..40f3f36 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
@@ -420,7 +420,7 @@
await driver.check(
breakpointId: 'globalFunctionBP',
expression: 'C._staticField',
- expectedError: "Error: Getter not found: '_staticField'.");
+ expectedResult: '2');
});
test('access field', () async {
@@ -476,7 +476,7 @@
await driver.check(
breakpointId: 'globalFunctionBP',
expression: 'C._staticField = 2',
- expectedError: "Setter not found: '_staticField'.");
+ expectedResult: '2');
});
test('static field modification', () async {
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index ac1c9ad..83c9a50 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -1553,6 +1553,8 @@
TypeCheck explicitCast(AsExpression cast) =>
summaryCollector.explicitCasts[cast];
+ TypeCheck isTest(IsExpression node) => summaryCollector.isTests[node];
+
NarrowNotNull nullTest(TreeNode node) => summaryCollector.nullTests[node];
Type fieldType(Field field) => _fieldValues[field]?.value;
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index 1c9ae91..dcae2df 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -538,6 +538,7 @@
final TreeNode node;
final Type staticType;
+ final SubtypeTestKind kind;
// 'isTestedOnlyOnCheckedEntryPoint' is whether or not this parameter's type-check will
// occur on the "checked" entrypoint in the VM but will be skipped on
@@ -547,9 +548,10 @@
VariableDeclaration get parameter =>
node is VariableDeclaration ? node : null;
- bool canAlwaysSkip = true;
+ bool alwaysPass = true;
+ bool alwaysFail = true;
- TypeCheck(this.arg, this.type, this.node, this.staticType) {
+ TypeCheck(this.arg, this.type, this.node, this.staticType, this.kind) {
assert(node != null);
isTestedOnlyOnCheckedEntryPoint =
parameter != null && !parameter.isCovariant;
@@ -573,14 +575,14 @@
// TODO(sjindel/tfa): Narrow the result if possible.
assert(checkType is UnknownType || checkType is RuntimeType);
- bool canSkip = true; // Can this check be skipped on this invocation.
+ bool pass = true; // Can this check be skipped on this invocation.
if (checkType is UnknownType) {
// If we don't know what the RHS of the check is going to be, we can't
// guarantee that it will pass.
- canSkip = false;
+ pass = false;
} else if (checkType is RuntimeType) {
- canSkip = argType.isSubtypeOfRuntimeType(typeHierarchy, checkType);
+ pass = argType.isSubtypeOfRuntimeType(typeHierarchy, checkType, kind);
argType = argType.intersection(
typeHierarchy.fromStaticType(checkType.representedTypeRaw, true),
typeHierarchy);
@@ -591,8 +593,8 @@
// If this check might be skipped on an
// unchecked entry-point, we need to signal that the call-site must be
// checked.
- if (!canSkip) {
- canAlwaysSkip = false;
+ if (!pass) {
+ alwaysPass = false;
if (isTestedOnlyOnCheckedEntryPoint) {
callHandler.typeCheckTriggered();
}
@@ -601,7 +603,13 @@
}
}
- argType = argType.intersection(staticType, typeHierarchy);
+ argType = argType
+ .intersection(staticType, typeHierarchy)
+ .specialize(typeHierarchy);
+
+ if (argType is! EmptyType) {
+ alwaysFail = false;
+ }
return argType;
}
@@ -782,7 +790,7 @@
final params = <VariableDeclaration>[];
for (Statement statement in _statements) {
if (statement is TypeCheck &&
- statement.canAlwaysSkip &&
+ statement.alwaysPass &&
statement.parameter != null) {
params.add(statement.parameter);
}
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index b5b213f..cd78792 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -534,6 +534,7 @@
final Map<TreeNode, Call> callSites = <TreeNode, Call>{};
final Map<AsExpression, TypeCheck> explicitCasts =
<AsExpression, TypeCheck>{};
+ final Map<IsExpression, TypeCheck> isTests = <IsExpression, TypeCheck>{};
final Map<TreeNode, NarrowNotNull> nullTests = <TreeNode, NarrowNotNull>{};
final _FallthroughDetector _fallthroughDetector = new _FallthroughDetector();
final Set<Name> _nullMethodsAndGetters = <Name>{};
@@ -1064,10 +1065,14 @@
}
}
- TypeCheck _typeCheck(TypeExpr value, DartType type, TreeNode node) {
+ TypeCheck _typeCheck(TypeExpr value, DartType type, TreeNode node,
+ [SubtypeTestKind kind = SubtypeTestKind.Subtype]) {
final TypeExpr runtimeType = _translator.translate(type);
- final typeCheck = new TypeCheck(
- value, runtimeType, node, _typesBuilder.fromStaticType(type, true));
+ final bool canBeNull = (kind == SubtypeTestKind.IsTest)
+ ? _canBeNullAfterSuccessfulIsCheck(type)
+ : true;
+ final typeCheck = new TypeCheck(value, runtimeType, node,
+ _typesBuilder.fromStaticType(type, canBeNull), kind);
_summary.add(typeCheck);
return typeCheck;
}
@@ -1128,19 +1133,17 @@
return narrow;
}
- // Narrow type of [arg] after successful 'is' test against [type].
- TypeExpr _makeNarrowAfterSuccessfulIsCheck(TypeExpr arg, DartType type) {
+ bool _canBeNullAfterSuccessfulIsCheck(DartType type) {
// 'x is type' can succeed for null if type is
// - a top type (dynamic, void, Object? or Object*)
// - nullable (including Null)
// - a type parameter (it can be instantiated with Null)
// - legacy Never
final nullability = type.nullability;
- final bool canBeNull = _environment.isTop(type) ||
+ return _environment.isTop(type) ||
nullability == Nullability.nullable ||
type is TypeParameterType ||
(type is NeverType && nullability == Nullability.legacy);
- return _makeNarrow(arg, _typesBuilder.fromStaticType(type, canBeNull));
}
TypeExpr _makeNarrowNotNull(TreeNode node, TypeExpr arg) {
@@ -1400,11 +1403,12 @@
} else if (node is IsExpression && node.operand is VariableGet) {
// Handle 'x is T', where x is a variable.
final operand = node.operand as VariableGet;
- _addUse(_visit(operand));
+ final TypeCheck typeCheck =
+ _typeCheck(_visit(operand), node.type, node, SubtypeTestKind.IsTest);
+ isTests[node] = typeCheck;
final int varIndex = _variablesInfo.varIndex[operand.variable];
if (_variableCells[varIndex] == null) {
- trueState[varIndex] =
- _makeNarrowAfterSuccessfulIsCheck(_visit(operand), node.type);
+ trueState[varIndex] = typeCheck;
}
_variableValues = null;
return;
@@ -1535,7 +1539,11 @@
@override
TypeExpr visitIsExpression(IsExpression node) {
- _visit(node.operand);
+ final operandNode = node.operand;
+ final TypeExpr operand = _visit(operandNode);
+ final TypeCheck typeCheck =
+ _typeCheck(operand, node.type, node, SubtypeTestKind.IsTest);
+ isTests[node] = typeCheck;
return _boolType;
}
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 5fb8cc5..feb185d 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -1049,7 +1049,11 @@
final List<ast.Statement> statements = <ast.Statement>[];
for (var arg in args) {
if (mayHaveSideEffects(arg)) {
- statements.add(ExpressionStatement(arg));
+ if (arg is BlockExpression && !mayHaveSideEffects(arg.value)) {
+ statements.add(arg.body);
+ } else {
+ statements.add(ExpressionStatement(arg));
+ }
}
}
if (statements.isEmpty) {
@@ -1245,8 +1249,8 @@
}
final nullTest = _getNullTest(node);
if (nullTest.isAlwaysNull || nullTest.isAlwaysNotNull) {
- return _evaluateArguments(
- [node.expression], BoolLiteral(nullTest.isAlwaysNull));
+ return _evaluateArguments([node.expression],
+ BoolLiteral(nullTest.isAlwaysNull)..fileOffset = node.fileOffset);
}
return node;
}
@@ -1502,11 +1506,138 @@
return _visitAssertNode(node, removalSentinel);
}
+ // Expression is an extended bool literal if it is
+ // - a BoolLiteral
+ // - a BlockExpression with a BoolLiteral value.
+ bool _isExtendedBoolLiteral(Expression expr) =>
+ expr is BoolLiteral ||
+ (expr is BlockExpression && expr.value is BoolLiteral);
+
+ // Returns value of an extended bool literal.
+ bool _getExtendedBoolLiteralValue(Expression expr) => (expr is BoolLiteral)
+ ? expr.value
+ : ((expr as BlockExpression).value as BoolLiteral).value;
+
+ // Returns Block corresponding to the given extended bool literal,
+ // or null if the expression is a simple bool literal.
+ Block _getExtendedBoolLiteralBlock(Expression expr) =>
+ (expr is BoolLiteral) ? null : (expr as BlockExpression).body;
+
+ @override
+ TreeNode visitIfStatement(IfStatement node, TreeNode removalSentinel) {
+ final condition = transform(node.condition);
+ if (_isExtendedBoolLiteral(condition)) {
+ final bool conditionValue = _getExtendedBoolLiteralValue(condition);
+ final Block conditionBlock = _getExtendedBoolLiteralBlock(condition);
+ ast.Statement body;
+ if (conditionValue) {
+ body = transform(node.then);
+ } else {
+ if (node.otherwise != null) {
+ body = transformOrRemoveStatement(node.otherwise);
+ }
+ }
+ if (conditionBlock != null) {
+ if (body != null) {
+ conditionBlock.addStatement(body);
+ }
+ return conditionBlock;
+ } else {
+ return body ?? EmptyStatement();
+ }
+ }
+ node.condition = condition..parent = node;
+ node.then = transform(node.then)..parent = node;
+ if (node.otherwise != null) {
+ node.otherwise = transformOrRemoveStatement(node.otherwise);
+ node.otherwise?.parent = node;
+ }
+ return node;
+ }
+
+ @override
+ visitConditionalExpression(
+ ConditionalExpression node, TreeNode removalSentinel) {
+ final condition = transform(node.condition);
+ if (_isExtendedBoolLiteral(condition)) {
+ final bool value = _getExtendedBoolLiteralValue(condition);
+ final Expression expr = transform(value ? node.then : node.otherwise);
+ if (condition is BlockExpression) {
+ condition.value = expr;
+ expr.parent = condition;
+ return condition;
+ } else {
+ return expr;
+ }
+ }
+ node.condition = condition..parent = node;
+ node.then = transform(node.then)..parent = node;
+ node.otherwise = transform(node.otherwise)..parent = node;
+ node.staticType = visitDartType(node.staticType, cannotRemoveSentinel);
+ return node;
+ }
+
+ @override
+ TreeNode visitNot(Not node, TreeNode removalSentinel) {
+ node.transformOrRemoveChildren(this);
+ final operand = node.operand;
+ if (_isExtendedBoolLiteral(operand)) {
+ final bool value = _getExtendedBoolLiteralValue(operand);
+ if (operand is BlockExpression) {
+ (operand.value as BoolLiteral).value = !value;
+ } else {
+ (operand as BoolLiteral).value = !value;
+ }
+ return operand;
+ }
+ return node;
+ }
+
+ @override
+ TreeNode visitLogicalExpression(
+ LogicalExpression node, TreeNode removalSentinel) {
+ final left = transform(node.left);
+ final operatorEnum = node.operatorEnum;
+ if (_isExtendedBoolLiteral(left)) {
+ final leftValue = _getExtendedBoolLiteralValue(left);
+ if (leftValue && operatorEnum == LogicalExpressionOperator.OR) {
+ return left;
+ } else if (!leftValue && operatorEnum == LogicalExpressionOperator.AND) {
+ return left;
+ }
+ }
+ final right = transform(node.right);
+ // Without sound null safety arguments of logical expression
+ // are implicitly checked for null, so transform the node only
+ // if using sound null safety or it evaluates to a bool literal.
+ if (_isExtendedBoolLiteral(left) &&
+ (shaker.typeFlowAnalysis.target.flags.enableNullSafety ||
+ _isExtendedBoolLiteral(right))) {
+ return _evaluateArguments([left], right);
+ }
+ node.left = left..parent = node;
+ node.right = right..parent = node;
+ return node;
+ }
+
+ @override
+ TreeNode visitIsExpression(IsExpression node, TreeNode removalSentinel) {
+ TypeCheck check = shaker.typeFlowAnalysis.isTest(node);
+ if (check != null && (check.alwaysFail || check.alwaysPass)) {
+ final operand = transform(node.operand);
+ final result = BoolLiteral(!check.alwaysFail)
+ ..fileOffset = node.fileOffset;
+ return _evaluateArguments([operand], result);
+ }
+ node.transformOrRemoveChildren(this);
+ return node;
+ }
+
@override
TreeNode visitAsExpression(AsExpression node, TreeNode removalSentinel) {
node.transformOrRemoveChildren(this);
TypeCheck check = shaker.typeFlowAnalysis.explicitCast(node);
- if (check != null && check.canAlwaysSkip) {
+ if (check != null && check.alwaysPass) {
return StaticInvocation(
unsafeCast, Arguments([node.operand], types: [node.type]))
..fileOffset = node.fileOffset;
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index 4d13774..588512c 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -154,6 +154,13 @@
Type getComputedType(List<Type> types);
}
+/// Kind of a subtype test: subtype/cast/'as' test or instance check/'is' test.
+/// There is a subtle difference in how these tests handle null value.
+enum SubtypeTestKind {
+ Subtype,
+ IsTest,
+}
+
/// Base class for types inferred by the type flow analysis.
/// [Type] describes a specific set of values (Dart instances) and does not
/// directly correspond to a Dart type.
@@ -174,8 +181,8 @@
// Returns 'true' if this type will definitely pass a runtime type-check
// against 'runtimeType'. Returns 'false' if the test might fail (e.g. due to
// an approximation).
- bool isSubtypeOfRuntimeType(
- TypeHierarchy typeHierarchy, RuntimeType runtimeType);
+ bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
+ RuntimeType runtimeType, SubtypeTestKind kind);
@override
Type getComputedType(List<Type> types) => this;
@@ -241,7 +248,8 @@
@override
Type intersection(Type other, TypeHierarchy typeHierarchy) => this;
- bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+ bool isSubtypeOfRuntimeType(
+ TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
return true;
}
}
@@ -271,12 +279,27 @@
bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
baseType.isSubtypeOf(typeHierarchy, cls);
- bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
- if (typeHierarchy.nullSafety &&
- other.nullability == Nullability.nonNullable) {
- return false;
+ bool isSubtypeOfRuntimeType(
+ TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
+ switch (kind) {
+ case SubtypeTestKind.Subtype:
+ if (typeHierarchy.nullSafety &&
+ other.nullability == Nullability.nonNullable) {
+ return false;
+ }
+ break;
+ case SubtypeTestKind.IsTest:
+ if (other.nullability != Nullability.nullable) {
+ final rhs = other._type;
+ if (!(rhs is InterfaceType &&
+ rhs.nullability == Nullability.legacy &&
+ rhs.classNode == typeHierarchy.coreTypes.objectClass)) {
+ return false;
+ }
+ }
+ break;
}
- return baseType.isSubtypeOfRuntimeType(typeHierarchy, other);
+ return baseType.isSubtypeOfRuntimeType(typeHierarchy, other, kind);
}
@override
@@ -349,7 +372,8 @@
return other;
}
- bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+ bool isSubtypeOfRuntimeType(
+ TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
final rhs = other._type;
return (rhs is DynamicType) ||
(rhs is VoidType) ||
@@ -403,8 +427,9 @@
bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
types.every((ConcreteType t) => t.isSubtypeOf(typeHierarchy, cls));
- bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) =>
- types.every((t) => t.isSubtypeOfRuntimeType(typeHierarchy, other));
+ bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other,
+ SubtypeTestKind kind) =>
+ types.every((t) => t.isSubtypeOfRuntimeType(typeHierarchy, other, kind));
@override
int get order => TypeOrder.Set.index;
@@ -577,7 +602,8 @@
bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
typeHierarchy.isSubtype(this.cls.classNode, cls);
- bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+ bool isSubtypeOfRuntimeType(
+ TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
final rhs = other._type;
if (rhs is DynamicType || rhs is VoidType) return true;
if (rhs is InterfaceType) {
@@ -795,8 +821,8 @@
bool isSubtypeOf(TypeHierarchy typeHierarchy, Class other) =>
typeHierarchy.isSubtype(cls.classNode, other);
- bool isSubtypeOfRuntimeType(
- TypeHierarchy typeHierarchy, RuntimeType runtimeType) {
+ bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
+ RuntimeType runtimeType, SubtypeTestKind kind) {
final rhs = runtimeType._type;
if (rhs is DynamicType || rhs is VoidType) return true;
if (rhs is InterfaceType) {
@@ -836,7 +862,7 @@
}
assert(ta is RuntimeType);
if (!ta.isSubtypeOfRuntimeType(
- typeHierarchy, runtimeType.typeArgs[i])) {
+ typeHierarchy, runtimeType.typeArgs[i], SubtypeTestKind.Subtype)) {
return false;
}
}
@@ -856,9 +882,10 @@
final RuntimeType lhs =
typeArg is RuntimeType ? typeArg : RuntimeType(DynamicType(), null);
return lhs.isSubtypeOfRuntimeType(
- typeHierarchy, runtimeType.typeArgs[0]);
+ typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
} else {
- return isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+ return isSubtypeOfRuntimeType(
+ typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
}
}
return false;
@@ -1149,8 +1176,11 @@
Class getConcreteClass(TypeHierarchy typeHierarchy) =>
throw "ERROR: ConcreteClass does not support getConcreteClass.";
- bool isSubtypeOfRuntimeType(
- TypeHierarchy typeHierarchy, RuntimeType runtimeType) {
+ bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
+ RuntimeType runtimeType, SubtypeTestKind kind) {
+ if (kind != SubtypeTestKind.Subtype) {
+ throw 'RuntimeType could be only tested for subtyping.';
+ }
final rhs = runtimeType._type;
if (typeHierarchy.nullSafety &&
_type.nullability == Nullability.nullable &&
@@ -1170,14 +1200,15 @@
if (_type is InterfaceType) {
Class thisClass = (_type as InterfaceType).classNode;
if (thisClass == typeHierarchy.coreTypes.futureClass) {
- return typeArgs[0]
- .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+ return typeArgs[0].isSubtypeOfRuntimeType(
+ typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
} else {
- return isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+ return isSubtypeOfRuntimeType(
+ typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
}
} else if (_type is FutureOrType) {
- return typeArgs[0]
- .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+ return typeArgs[0].isSubtypeOfRuntimeType(
+ typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
}
}
@@ -1216,8 +1247,8 @@
assert(usableTypeArgs.length - interfaceOffset >=
runtimeType.numImmediateTypeArgs);
for (int i = 0; i < runtimeType.numImmediateTypeArgs; ++i) {
- if (!usableTypeArgs[interfaceOffset + i]
- .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[i])) {
+ if (!usableTypeArgs[interfaceOffset + i].isSubtypeOfRuntimeType(
+ typeHierarchy, runtimeType.typeArgs[i], SubtypeTestKind.Subtype)) {
return false;
}
}
@@ -1264,7 +1295,11 @@
throw "ERROR: UnknownType does not support intersection with ${other.runtimeType}";
}
- bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+ bool isSubtypeOfRuntimeType(
+ TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
+ if (kind != SubtypeTestKind.Subtype) {
+ throw 'UnknownType could be only tested for subtyping.';
+ }
final rhs = other._type;
return (rhs is DynamicType) ||
(rhs is VoidType) ||
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
index 625d97f..5b8180a 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
@@ -12,15 +12,16 @@
i_0 = _Join [dart.core::int*] (_T (dart.core::_Smi, 0), t3)
t5* = _Call [dart.core::num.<] (i_0, _T (dart.core::_Smi, 10))
t6* = _Call direct [#lib::bar] ()
-t7* = _Call direct [#lib::foo] ()
-t8 = _Join [dynamic] (_T (dart.core::bool, true), t7)
-t9 = _TypeCheck (t8 against dart.core::bool*) (for (x ?{dynamic} true : #lib::foo()) as dart.core::bool*)
-t10* = _Call direct [#lib::bar] ()
+t7 = _TypeCheck (t6 against dart.core::bool*) (for x is dart.core::bool*)
+t8* = _Call direct [#lib::foo] ()
+t9 = _Join [dynamic] (_T (dart.core::bool, true), t8)
+t10 = _TypeCheck (t9 against dart.core::bool*) (for (x ?{dynamic} true : #lib::foo()) as dart.core::bool*)
t11* = _Call direct [#lib::bar] ()
-t12* = _Call direct [#lib::foo] ()
-t13 = _TypeCheck (t12 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
-t14* = _Call direct [#lib::foo] ()
-t15 = _TypeCheck (t14 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
+t12* = _Call direct [#lib::bar] ()
+t13* = _Call direct [#lib::foo] ()
+t14 = _TypeCheck (t13 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
+t15* = _Call direct [#lib::foo] ()
+t16 = _TypeCheck (t15 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
y_0 = _Join [dart.core::bool*] (_T (dart.core::bool), _T (dart.core::bool, true))
RESULT: _T {}?
------------ main ------------
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
index 54aa62d..80bbada 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
@@ -124,7 +124,7 @@
RESULT: _T {}?
------------ if8 ------------
%x = _Parameter #0 [_T ANY?]
-t1 = _Narrow (%x to _T (dart.core::String)+)
+t1 = _TypeCheck (%x against dart.core::String) (for x is dart.core::String)
t2 = _Call direct [#lib::foo] (t1)
RESULT: _T {}?
------------ if9 ------------
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
index 4bba0a1..b5c21e4 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
@@ -21,7 +21,7 @@
------------ bar ------------
%a1 = _Parameter #0 [_T (dart.core::Object)+?]
%a2 = _Parameter #1 [_T (dart.core::int)+?]
-t2 = _Narrow (%a1 to _T (dart.core::int)+)
+t2 = _TypeCheck (%a1 against dart.core::int*) (for v1 is dart.core::int*)
t3* = _Call [dart.core::num.+] (t2, %a2)
t4* = _Call [dart.core::num.*] (t3, _T (dart.core::_Smi, 3))
t5* = _Call [dart.core::int.unary-] (_T (dart.core::_Smi, 1))
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart
new file mode 100644
index 0000000..fa5a893
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart
@@ -0,0 +1,51 @@
+// 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 elimination of 'is' tests.
+
+// @dart = 2.12
+
+class A {}
+
+class B extends A {
+ void foo() {
+ print('foo');
+ }
+
+ bool get bar => int.parse('1') == 1;
+}
+
+class C implements A {}
+
+A obj = int.parse('2') == 2 ? C() : A();
+A getObj() => obj;
+
+void test1() {
+ var x = getObj();
+ if (x is B) {
+ x.foo();
+ }
+}
+
+void test2(x) {
+ if (x is B && x.bar) {
+ print('bye');
+ }
+}
+
+void test3(x) {
+ if (x is! B) {
+ return;
+ }
+ print('bye');
+}
+
+test4() => (getObj() is B) ? 3 : 4;
+
+void main() {
+ test1();
+ test2(obj);
+ test3(obj);
+ test4();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart.expect
new file mode 100644
index 0000000..3af08e0
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart.expect
@@ -0,0 +1,40 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class C extends core::Object implements self::A {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+}
+static field self::A obj = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("2") =={core::num::==}{(core::Object) → core::bool} 2 ?{self::A} new self::C::•() : new self::A::•();
+static method getObj() → self::A
+ return self::obj;
+static method test1() → void {
+ self::A x = self::getObj();
+ ;
+}
+static method test2() → void {
+ ;
+}
+static method test3() → void {
+ {
+ return;
+ }
+ core::print("bye");
+}
+[@vm.unboxing-info.metadata=()->i]static method test4() → dynamic
+ return block {
+ self::getObj();
+ } =>4;
+static method main() → void {
+ self::test1();
+ let final self::A #t1 = self::obj in self::test2();
+ let final self::A #t2 = self::obj in self::test3();
+ self::test4();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
index 2fa9807..11d07aa 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
@@ -13,10 +13,8 @@
}
[@vm.inferred-type.metadata=#lib::A?]static field self::A* staticField = new self::A::•("hi", "bye");
static method testNonNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if( block {
+ {
[@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*};
- } =>false) {
- core::print("null");
}
}
static method testNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
@@ -25,16 +23,17 @@
}
}
static method testAlwaysNullIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if( block {
+ {
[@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*};
- } =>true) {
- core::print("null");
+ {
+ core::print("null");
+ }
}
}
static method testNonNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(!( block {
+ if(( block {
[@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*};
- } =>false) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
+ } =>true) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
core::print("not null");
}
}
@@ -44,22 +43,20 @@
}
}
static method testAlwaysNullIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(!( block {
+ {
[@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*};
- } =>true) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
- core::print("not null");
}
}
static method testNonNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
- return !( block {
+ return block {
[@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*};
- } =>false) ?{core::String*} "not null" : "null";
+ } =>"not null";
static method testNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
return !([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String*} == null) ?{core::String*} "not null" : "null";
static method testAlwaysNullCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
- return !( block {
+ return block {
[@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*};
- } =>true) ?{core::String*} "not null" : "null";
+ } =>"null";
static method someCondition() → dynamic
return [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1;
static method main() → void {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
index 89b2f4f..162174d 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
@@ -19,8 +19,7 @@
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method add(generic-covariant-impl self::_SplayTree::Node n) → dynamic {
self::_SplayTree::Node? root = [@vm.direct-call.metadata=#lib::SplayTreeMap._root] [@vm.inferred-type.metadata=#lib::_SplayTreeMapNode<dynamic>] this.{self::_SplayTree::_root}{self::_SplayTree::Node?};
- if(false)
- return;
+ ;
core::print([@vm.direct-call.metadata=#lib::_SplayTreeNode.left] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] root{self::_SplayTree::Node}.{self::_SplayTreeNode::left}{self::_SplayTree::Node?});
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] abstract get /*isLegacy*/ _root() → self::_SplayTree::Node?;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect
index 82edbf6..37b6a68 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect
@@ -16,11 +16,11 @@
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method noSuchMethod(core::Invocation i) → dynamic
return throw "Not implemented";
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {[@vm.inferred-type.metadata=dart.core::Null? (value: null)] (core::Object) →? core::bool test = #C1}) → asy::Future<self::B::T%>
- return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onError)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::T%>;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError) → asy::Future<self::B::T%>
+ return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onError)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C3: #C4}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::T%>;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ whenComplete(() → FutureOr<void>action) → asy::Future<self::B::T%>
- return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(action)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::T%>;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ then<R extends core::Object? = dynamic>((self::B::T%) → FutureOr<self::B::then::R%>onValue, {core::Function? onError = #C1}) → asy::Future<self::B::then::R%>
+ return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(action)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::T%>;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ then<R extends core::Object? = dynamic>((self::B::T%) → FutureOr<self::B::then::R%>onValue, {core::Function? onError = #C4}) → asy::Future<self::B::then::R%>
return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, core::List::unmodifiable<core::Type*>([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Type*>] core::_GrowableList::_literal1<core::Type*>(self::B::then::R%)), core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onValue)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C9: onError}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::then::R%>;
}
static method createB<T extends core::Object? = dynamic>() → self::B<dynamic>
@@ -29,10 +29,10 @@
core::print([@vm.inferred-type.metadata=#lib::B<?>] self::createB<core::int>() as{ForNonNullableByDefault} FutureOr<core::double>);
}
constants {
- #C1 = null
- #C2 = #catchError
- #C3 = <core::Type*>[]
- #C4 = #test
+ #C1 = #catchError
+ #C2 = <core::Type*>[]
+ #C3 = #test
+ #C4 = null
#C5 = #whenComplete
#C6 = <dynamic>[]
#C7 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C6}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
index 9f7ad71..7ac9fc8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
@@ -34,7 +34,7 @@
static method testDynamic() → dynamic
return _in::unsafeCast<dynamic>(#C3);
static method testObjectNegative() → dynamic
- return let dynamic #t1 = #C2 in true ?{core::Object} #t1 as{ForNonNullableByDefault} core::Object : #t1{core::Object};
+ return let dynamic #t1 = #C2 in #t1 as{ForNonNullableByDefault} core::Object;
static method testNullableObject() → dynamic
return #C2;
static method testAOfNum1([@vm.inferred-type.metadata=#lib::B<dart.core::int>] dynamic x) → dynamic
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
index 96487b0..6cd1f40 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
@@ -4,8 +4,6 @@
abstract class I extends core::Object {
}
-abstract class A extends core::Object implements self::I {
-}
class B extends core::Object implements self::I {
synthetic constructor •() → self::B
: super core::Object::•()
@@ -13,9 +11,7 @@
}
[@vm.inferred-type.metadata=#lib::B?]static field self::I ii = new self::B::•();
static method bar([@vm.inferred-type.metadata=#lib::B?] self::I i) → void {
- if(i is{ForNonNullableByDefault} self::A) {
- throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
- }
+ ;
}
static method main(core::List<core::String> args) → dynamic {
self::bar([@vm.inferred-type.metadata=#lib::B?] self::ii);
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index d983c2c..4a6ac6b 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -5582,6 +5582,7 @@
DECLARE_OBJECT_STORE_FIELD,
DECLARE_OBJECT_STORE_FIELD,
DECLARE_OBJECT_STORE_FIELD,
+ DECLARE_OBJECT_STORE_FIELD,
DECLARE_OBJECT_STORE_FIELD)
#undef DECLARE_OBJECT_STORE_FIELD
};
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index dccfad1..a425e97 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -127,7 +127,11 @@
static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 4;
#elif defined(TARGET_ARCH_ARM64)
static constexpr intptr_t kNativeCallbackTrampolineSize = 12;
+#if defined(DART_COMPRESSED_POINTERS)
+ static constexpr intptr_t kNativeCallbackSharedStubSize = 276;
+#else
static constexpr intptr_t kNativeCallbackSharedStubSize = 268;
+#endif
static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2;
#endif
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 5f947b7..9892d6f 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -123,7 +123,7 @@
#define EMIT_FIELD_NAME(type, name) #name "_",
OBJECT_STORE_FIELD_LIST(EMIT_FIELD_NAME, EMIT_FIELD_NAME,
EMIT_FIELD_NAME, EMIT_FIELD_NAME,
- EMIT_FIELD_NAME)
+ EMIT_FIELD_NAME, EMIT_FIELD_NAME)
#undef EMIT_FIELD_NAME
};
ObjectPtr* current = from();
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index e502c01..267ff50 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -36,10 +36,11 @@
//
// R_ - needs getter only
// RW - needs getter and setter
+// ARW - needs getter and setter with atomic access
// CR - needs lazy Core init getter
// FR - needs lazy Async init getter
// IR - needs lazy Isolate init getter
-#define OBJECT_STORE_FIELD_LIST(R_, RW, CR, FR, IR) \
+#define OBJECT_STORE_FIELD_LIST(R_, RW, ARW, CR, FR, IR) \
CR(Class, list_class) /* maybe be null, lazily built */ \
CR(Type, non_nullable_list_rare_type) /* maybe be null, lazily built */ \
CR(Type, non_nullable_map_rare_type) /* maybe be null, lazily built */ \
@@ -173,8 +174,8 @@
RW(Function, complete_on_async_return) \
RW(Function, complete_on_async_error) \
RW(Class, async_star_stream_controller) \
- RW(Smi, future_timeout_future_index) \
- RW(Smi, future_wait_future_index) \
+ ARW(Smi, future_timeout_future_index) \
+ ARW(Smi, future_wait_future_index) \
RW(CompressedStackMaps, canonicalized_stack_map_entries) \
RW(ObjectPool, global_object_pool) \
RW(Array, unique_dynamic_targets) \
@@ -391,12 +392,24 @@
ObjectStore();
~ObjectStore();
+#define DECLARE_OFFSET(name) \
+ static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
#define DECLARE_GETTER(Type, name) \
Type##Ptr name() const { return name##_; } \
- static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
+ DECLARE_OFFSET(name)
#define DECLARE_GETTER_AND_SETTER(Type, name) \
DECLARE_GETTER(Type, name) \
void set_##name(const Type& value) { name##_ = value.ptr(); }
+#define DECLARE_ATOMIC_GETTER_AND_SETTER(Type, name) \
+ template <std::memory_order order = std::memory_order_relaxed> \
+ Type##Ptr name() const { \
+ return name##_.load(order); \
+ } \
+ template <std::memory_order order = std::memory_order_relaxed> \
+ void set_##name(const Type& value) { \
+ name##_.store(value.ptr(), order); \
+ } \
+ DECLARE_OFFSET(name)
#define DECLARE_LAZY_INIT_GETTER(Type, name, init) \
Type##Ptr name() { \
if (name##_.load() == Type::null()) { \
@@ -404,7 +417,7 @@
} \
return name##_.load(); \
} \
- static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
+ DECLARE_OFFSET(name)
#define DECLARE_LAZY_INIT_CORE_GETTER(Type, name) \
DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitCoreMembers)
#define DECLARE_LAZY_INIT_ASYNC_GETTER(Type, name) \
@@ -413,11 +426,14 @@
DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitIsolateMembers)
OBJECT_STORE_FIELD_LIST(DECLARE_GETTER,
DECLARE_GETTER_AND_SETTER,
+ DECLARE_ATOMIC_GETTER_AND_SETTER,
DECLARE_LAZY_INIT_CORE_GETTER,
DECLARE_LAZY_INIT_ASYNC_GETTER,
DECLARE_LAZY_INIT_ISOLATE_GETTER)
+#undef DECLARE_OFFSET
#undef DECLARE_GETTER
#undef DECLARE_GETTER_AND_SETTER
+#undef DECLARE_ATOMIC_GETTER_AND_SETTER
#undef DECLARE_LAZY_INIT_GETTER
#undef DECLARE_LAZY_INIT_CORE_GETTER
#undef DECLARE_LAZY_INIT_ASYNC_GETTER
@@ -478,15 +494,19 @@
ObjectPtr* from() { return reinterpret_cast<ObjectPtr*>(&list_class_); }
#define DECLARE_OBJECT_STORE_FIELD(type, name) type##Ptr name##_;
+#define DECLARE_ATOMIC_OBJECT_STORE_FIELD(type, name) \
+ std::atomic<type##Ptr> name##_;
#define DECLARE_LAZY_OBJECT_STORE_FIELD(type, name) \
AcqRelAtomic<type##Ptr> name##_;
OBJECT_STORE_FIELD_LIST(DECLARE_OBJECT_STORE_FIELD,
DECLARE_OBJECT_STORE_FIELD,
+ DECLARE_ATOMIC_OBJECT_STORE_FIELD,
DECLARE_LAZY_OBJECT_STORE_FIELD,
DECLARE_LAZY_OBJECT_STORE_FIELD,
DECLARE_LAZY_OBJECT_STORE_FIELD)
-#undef DECLARE_LAZY_OBJECT_STORE_FIELD
#undef DECLARE_OBJECT_STORE_FIELD
+#undef DECLARE_ATOMIC_OBJECT_STORE_FIELD
+#undef DECLARE_LAZY_OBJECT_STORE_FIELD
ObjectPtr* to() {
return reinterpret_cast<ObjectPtr*>(&ffi_as_function_internal_);
}
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index b2e773d..b2545cf 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -257,9 +257,22 @@
// Remember context indices of _future variables in _Future.timeout and
// Future.wait. They are used while collecting async stack traces.
if (function.recognized_kind() == MethodRecognizer::kFutureTimeout) {
+#ifdef DEBUG
+ auto old_value = IsolateGroup::Current()
+ ->object_store()
+ ->future_timeout_future_index();
+ ASSERT(old_value == Object::null() ||
+ Smi::Value(old_value) == chained_future->index().value());
+#endif // DEBUG
IsolateGroup::Current()->object_store()->set_future_timeout_future_index(
Smi::Handle(Smi::New(chained_future->index().value())));
} else if (function.recognized_kind() == MethodRecognizer::kFutureWait) {
+#ifdef DEBUG
+ auto old_value =
+ IsolateGroup::Current()->object_store()->future_wait_future_index();
+ ASSERT(old_value == Object::null() ||
+ Smi::Value(old_value) == chained_future->index().value());
+#endif // DEBUG
IsolateGroup::Current()->object_store()->set_future_wait_future_index(
Smi::Handle(Smi::New(chained_future->index().value())));
} else {
diff --git a/tools/VERSION b/tools/VERSION
index 8119d92..6197956 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 340
+PRERELEASE 341
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart
index 7b9a07d..882c827 100644
--- a/tools/generate_package_config.dart
+++ b/tools/generate_package_config.dart
@@ -92,22 +92,20 @@
packages.sort((a, b) => a["name"].compareTo(b["name"]));
var configFile = File(p.join(repoRoot, '.dart_tool', 'package_config.json'));
+ var json =
+ jsonDecode(configFile.readAsStringSync()) as Map<dynamic, dynamic>;
+ var oldPackages = json['packages'] as List<dynamic>;
// Validate the packages entry only, to avoid spurious failures from changes
// in the dates embedded in the other entries.
- if (checkOnly) {
- var json =
- jsonDecode(configFile.readAsStringSync()) as Map<dynamic, dynamic>;
- var oldPackages = json['packages'] as List<dynamic>;
- if (jsonEncode(packages) == jsonEncode(oldPackages)) {
- print("Package config up to date");
- exit(0);
- } else {
- print("Package config out of date");
- print("Run `gclient sync -D && dart tools/generate_package_config.dart` "
- "to update.");
- exit(1);
- }
+ if (jsonEncode(packages) == jsonEncode(oldPackages)) {
+ print("Package config up to date");
+ exit(0);
+ } else if (checkOnly) {
+ print("Package config out of date");
+ print("Run `gclient sync -D && dart tools/generate_package_config.dart` "
+ "to update.");
+ exit(1);
}
var year = DateTime.now().year;
@@ -130,8 +128,8 @@
};
// TODO(rnystrom): Consider using package_config_v2 to generate this instead.
- var json = JsonEncoder.withIndent(' ').convert(config);
- configFile.writeAsStringSync('$json\n');
+ var jsonString = JsonEncoder.withIndent(' ').convert(config);
+ configFile.writeAsStringSync('$jsonString\n');
print('Generated .dart_tool/package_config.dart containing '
'${packages.length} packages.');
}